?
Current Path : /usr/share/ruby/vendor_ruby/puppet/pops/binder/ |
Linux gator3171.hostgator.com 4.19.286-203.ELK.el7.x86_64 #1 SMP Wed Jun 14 04:33:55 CDT 2023 x86_64 |
Current File : //usr/share/ruby/vendor_ruby/puppet/pops/binder/bindings_checker.rb |
# A validator/checker of a bindings model # @api public # class Puppet::Pops::Binder::BindingsChecker Bindings = Puppet::Pops::Binder::Bindings Issues = Puppet::Pops::Binder::BinderIssues Types = Puppet::Pops::Types attr_reader :type_calculator attr_reader :acceptor # @api public def initialize(diagnostics_producer) @@check_visitor ||= Puppet::Pops::Visitor.new(nil, "check", 0, 0) @type_calculator = Puppet::Pops::Types::TypeCalculator.new() @expression_validator = Puppet::Pops::Validation::ValidatorFactory_4_0.new().checker(diagnostics_producer) @acceptor = diagnostics_producer end # Validates the entire model by visiting each model element and calling `check`. # The result is collected (or acted on immediately) by the configured diagnostic provider/acceptor # given when creating this Checker. # # @api public # def validate(b) check(b) b.eAllContents.each {|c| check(c) } end # Performs binding validity check # @api private def check(b) @@check_visitor.visit_this_0(self, b) end # Checks that a binding has a producer and a type # @api private def check_Binding(b) # Must have a type acceptor.accept(Issues::MISSING_TYPE, b) unless b.type.is_a?(Types::PAnyType) # Must have a producer acceptor.accept(Issues::MISSING_PRODUCER, b) unless b.producer.is_a?(Bindings::ProducerDescriptor) end # Checks that the producer is a Multibind producer and that the type is a PCollectionType # @api private def check_Multibinding(b) # id is optional (empty id blocks contributions) # A multibinding must have PCollectionType acceptor.accept(Issues::MULTIBIND_TYPE_ERROR, b, {:actual_type => b.type}) unless b.type.is_a?(Types::PCollectionType) # if the producer is nil, a suitable producer will be picked automatically unless b.producer.nil? || b.producer.is_a?(Bindings::MultibindProducerDescriptor) acceptor.accept(Issues::MULTIBIND_NOT_COLLECTION_PRODUCER, b, {:actual_producer => b.producer}) end end # Checks that the bindings object contains at least one binding. Then checks each binding in turn # @api private def check_Bindings(b) acceptor.accept(Issues::MISSING_BINDINGS, b) unless has_entries?(b.bindings) end # Checks that a name has been associated with the bindings # @api private def check_NamedBindings(b) acceptor.accept(Issues::MISSING_BINDINGS_NAME, b) unless has_chars?(b.name) check_Bindings(b) end # Check layer has a name # @api private def check_NamedLayer(l) acceptor.accept(Issues::MISSING_LAYER_NAME, binding_parent(l)) unless has_chars?(l.name) end # Checks that the binding has layers and that each layer has a name and at least one binding # @api private def check_LayeredBindings(b) acceptor.accept(Issues::MISSING_LAYERS, b) unless has_entries?(b.layers) end # Checks that the non caching producer has a producer to delegate to # @api private def check_NonCachingProducerDescriptor(p) acceptor.accept(Issues::PRODUCER_MISSING_PRODUCER, p) unless p.producer.is_a?(Bindings::ProducerDescriptor) end # Checks that a constant value has been declared in the producer and that the type # of the value is compatible with the type declared in the binding # @api private def check_ConstantProducerDescriptor(p) # the product must be of compatible type # TODO: Likely to change when value becomes a typed Puppet Object b = binding_parent(p) if p.value.nil? acceptor.accept(Issues::MISSING_VALUE, p, {:binding => b}) else infered = type_calculator.infer(p.value) unless type_calculator.assignable?(b.type, infered) acceptor.accept(Issues::INCOMPATIBLE_TYPE, p, {:binding => b, :expected_type => b.type, :actual_type => infered}) end end end # Checks that an expression has been declared in the producer # @api private def check_EvaluatingProducerDescriptor(p) unless p.expression.is_a?(Puppet::Pops::Model::Expression) acceptor.accept(Issues::MISSING_EXPRESSION, p, {:binding => binding_parent(p)}) end end # Checks that a class name has been declared in the producer # @api private def check_InstanceProducerDescriptor(p) acceptor.accept(Issues::MISSING_CLASS_NAME, p, {:binding => binding_parent(p)}) unless has_chars?(p.class_name) end # Checks that a type and a name has been declared. The type must be assignable to the type # declared in the binding. The name can be an empty string to denote 'no name' # @api private def check_LookupProducerDescriptor(p) b = binding_parent(p) unless type_calculator.assignable(b.type, p.type) acceptor.accept(Issues::INCOMPATIBLE_TYPE, p, {:binding => b, :expected_type => b.type, :actual_type => p.type }) end acceptor.accept(Issues::MISSING_NAME, p, {:binding => b}) if p.name.nil? # empty string is OK end # Checks that a key has been declared, then calls producer_LookupProducerDescriptor to perform # checks associated with the super class # @api private def check_HashLookupProducerDescriptor(p) acceptor.accept(Issues::MISSING_KEY, p, {:binding => binding_parent(p)}) unless has_chars?(p.key) check_LookupProducerDescriptor(p) end # Checks that the type declared in the binder is a PArrayType # @api private def check_ArrayMultibindProducerDescriptor(p) b = binding_parent(p) acceptor.accept(Issues::MULTIBIND_INCOMPATIBLE_TYPE, p, {:binding => b, :actual_type => b.type}) unless b.type.is_a?(Types::PArrayType) end # Checks that the type declared in the binder is a PHashType # @api private def check_HashMultibindProducerDescriptor(p) b = binding_parent(p) acceptor.accept(Issues::MULTIBIND_INCOMPATIBLE_TYPE, p, {:binding => b, :actual_type => b.type}) unless b.type.is_a?(Types::PHashType) end # Checks that the producer that this producer delegates to is declared # @api private def check_ProducerProducerDescriptor(p) unless p.producer.is_a?(Bindings::ProducerDescriptor) acceptor.accept(Issues::PRODUCER_MISSING_PRODUCER, p, {:binding => binding_parent(p)}) end end # @api private def check_Expression(t) @expression_validator.validate(t) end # @api private def check_PAnyType(t) # Do nothing end # Returns true if the argument is a non empty string # @api private def has_chars?(s) s.is_a?(String) && !s.empty? end # @api private def has_entries?(s) !(s.nil? || s.empty?) end # @api private def binding_parent(p) begin x = p.eContainer if x.nil? acceptor.accept(Issues::MODEL_OBJECT_IS_UNBOUND, p) return nil end p = x end while !p.is_a?(Bindings::AbstractBinding) p end end