Class: Puppet::Pops::Binder::BindingsChecker

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/pops/binder/bindings_checker.rb

Overview

A validator/checker of a bindings model

Constant Summary collapse

Bindings =
Puppet::Pops::Binder::Bindings
Issues =
Puppet::Pops::Binder::BinderIssues
Types =
Puppet::Pops::Types

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(diagnostics_producer) ⇒ BindingsChecker

Returns a new instance of BindingsChecker.



13
14
15
16
17
18
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 13

def initialize(diagnostics_producer)
  @@check_visitor     ||= Puppet::Pops::Visitor.new(nil, "check", 0, 0)
  @type_calculator      = Puppet::Pops::Types::TypeCalculator.singleton
  @expression_validator = Puppet::Pops::Validation::ValidatorFactory_4_0.new().checker(diagnostics_producer)
  @acceptor             = diagnostics_producer
end

Instance Attribute Details

#acceptorObject (readonly)



10
11
12
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 10

def acceptor
  @acceptor
end

#type_calculatorObject (readonly)



9
10
11
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 9

def type_calculator
  @type_calculator
end

Instance Method Details

#binding_parent(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



186
187
188
189
190
191
192
193
194
195
196
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 186

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

#check(b) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Performs binding validity check



33
34
35
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 33

def check(b)
  @@check_visitor.visit_this_0(self, b)
end

#check_ArrayMultibindProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that the type declared in the binder is a PArrayType



144
145
146
147
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 144

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

#check_Binding(b) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that a binding has a producer and a type



39
40
41
42
43
44
45
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 39

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

#check_Bindings(b) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that the bindings object contains at least one binding. Then checks each binding in turn



63
64
65
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 63

def check_Bindings(b)
  acceptor.accept(Issues::MISSING_BINDINGS, b) unless has_entries?(b.bindings)
end

#check_ConstantProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 95

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

#check_EvaluatingProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that an expression has been declared in the producer



111
112
113
114
115
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 111

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

#check_Expression(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



165
166
167
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 165

def check_Expression(t)
  @expression_validator.validate(t)
end

#check_HashLookupProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that a key has been declared, then calls producer_LookupProducerDescriptor to perform checks associated with the super class



137
138
139
140
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 137

def check_HashLookupProducerDescriptor(p)
  acceptor.accept(Issues::MISSING_KEY, p, {:binding => binding_parent(p)}) unless has_chars?(p.key)
  check_LookupProducerDescriptor(p)
end

#check_HashMultibindProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that the type declared in the binder is a PHashType



151
152
153
154
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 151

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

#check_InstanceProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that a class name has been declared in the producer



119
120
121
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 119

def check_InstanceProducerDescriptor(p)
  acceptor.accept(Issues::MISSING_CLASS_NAME, p, {:binding => binding_parent(p)}) unless has_chars?(p.class_name)
end

#check_LayeredBindings(b) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that the binding has layers and that each layer has a name and at least one binding



82
83
84
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 82

def check_LayeredBindings(b)
  acceptor.accept(Issues::MISSING_LAYERS, b) unless has_entries?(b.layers)
end

#check_LookupProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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’



126
127
128
129
130
131
132
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 126

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

#check_Multibinding(b) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that the producer is a Multibind producer and that the type is a PCollectionType



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 49

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

#check_NamedBindings(b) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that a name has been associated with the bindings



69
70
71
72
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 69

def check_NamedBindings(b)
  acceptor.accept(Issues::MISSING_BINDINGS_NAME, b) unless has_chars?(b.name)
  check_Bindings(b)
end

#check_NamedLayer(l) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check layer has a name



76
77
78
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 76

def check_NamedLayer(l)
  acceptor.accept(Issues::MISSING_LAYER_NAME, binding_parent(l)) unless has_chars?(l.name)
end

#check_NonCachingProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that the non caching producer has a producer to delegate to



88
89
90
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 88

def check_NonCachingProducerDescriptor(p)
  acceptor.accept(Issues::PRODUCER_MISSING_PRODUCER, p) unless p.producer.is_a?(Bindings::ProducerDescriptor)
end

#check_PAnyType(t) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



170
171
172
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 170

def check_PAnyType(t)
  # Do nothing
end

#check_ProducerProducerDescriptor(p) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks that the producer that this producer delegates to is declared



158
159
160
161
162
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 158

def check_ProducerProducerDescriptor(p)
  unless p.producer.is_a?(Bindings::ProducerDescriptor)
    acceptor.accept(Issues::PRODUCER_MISSING_PRODUCER, p, {:binding => binding_parent(p)})
  end
end

#has_chars?(s) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns true if the argument is a non empty string

Returns:

  • (Boolean)


176
177
178
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 176

def has_chars?(s)
  s.is_a?(String) && !s.empty?
end

#has_entries?(s) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


181
182
183
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 181

def has_entries?(s)
  !(s.nil? || s.empty?)
end

#validate(b) ⇒ Object

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.



26
27
28
29
# File 'lib/puppet/pops/binder/bindings_checker.rb', line 26

def validate(b)
  check(b)
  b.eAllContents.each {|c| check(c) }
end