Class: Puppet::Pops::Validation::Checker4_0
- Defined in:
- lib/puppet/pops/validation/checker4_0.rb
Overview
A Validator validates a model.
Validation is performed on each model element in isolation. Each method should validate the model element’s state but not validate its referenced/contained elements except to check their validity in their respective role. The intent is to drive the validation with a tree iterator that visits all elements in a model.
TODO: Add validation of multiplicities - this is a general validation that can be checked for all
Model objects via their metamodel. (I.e an extra call to multiplicity check in polymorph check).
This is however mostly valuable when validating model to model transformations, and is therefore T.B.D
Constant Summary collapse
- Issues =
Puppet::Pops::Issues
- Model =
Puppet::Pops::Model
- RESERVED_TYPE_NAMES =
{ 'type' => true, 'any' => true, 'unit' => true, 'scalar' => true, 'boolean' => true, 'numeric' => true, 'integer' => true, 'float' => true, 'collection' => true, 'array' => true, 'hash' => true, 'tuple' => true, 'struct' => true, 'variant' => true, 'optional' => true, 'enum' => true, 'regexp' => true, 'pattern' => true, 'runtime' => true, }
- RESERVED_PARAMETERS =
{ 'name' => true, 'title' => true, }
Instance Attribute Summary collapse
- #acceptor ⇒ Object readonly
- #migration_checker ⇒ Object readonly
Instance Method Summary collapse
-
#assign(o, via_index = false) ⇒ Object
Checks the LHS of an assignment (is it assignable?).
- #assign_AccessExpression(o, via_index) ⇒ Object
- #assign_LiteralList(o, via_index) ⇒ Object
- #assign_Object(o, via_index) ⇒ Object
-
#assign_VariableExpression(o, via_index) ⇒ Object
—ASSIGNMENT CHECKS.
-
#check(o) ⇒ Object
Performs regular validity check.
- #check_AccessExpression(o) ⇒ Object
- #check_AssignmentExpression(o) ⇒ Object
-
#check_AttributeOperation(o) ⇒ Object
Checks that operation with :+> is contained in a ResourceOverride or Collector.
- #check_AttributesOperation(o) ⇒ Object
- #check_BinaryExpression(o) ⇒ Object
- #check_BlockExpression(o) ⇒ Object
- #check_CallNamedFunctionExpression(o) ⇒ Object
- #check_CaseExpression(o) ⇒ Object
- #check_CaseOption(o) ⇒ Object
- #check_CollectExpression(o) ⇒ Object
- #check_EppExpression(o) ⇒ Object
- #check_Factory(o) ⇒ Object
- #check_FunctionDefinition(o) ⇒ Object
- #check_HostClassDefinition(o) ⇒ Object
- #check_IfExpression(o) ⇒ Object
- #check_KeyedEntry(o) ⇒ Object
- #check_LambdaExpression(o) ⇒ Object
- #check_LiteralList(o) ⇒ Object
- #check_MethodCallExpression(o) ⇒ Object
-
#check_NamedAccessExpression(o) ⇒ Object
Only used for function names, grammar should not be able to produce something faulty, but check anyway if model is created programatically (it will fail in transformation to AST for sure).
-
#check_NamedDefinition(o) ⇒ Object
for ‘class’, ‘define’, and function.
- #check_NodeDefinition(o) ⇒ Object
-
#check_Object(o) ⇒ Object
—CHECKS.
- #check_Parameter(o) ⇒ Object
-
#check_QualifiedName(o) ⇒ Object
No checking takes place - all expressions using a QualifiedName need to check.
-
#check_QualifiedReference(o) ⇒ Object
Checks that the value is a valid UpperCaseWord (a CLASSREF), and optionally if it contains a hypen.
- #check_QueryExpression(o) ⇒ Object
-
#check_RelationshipExpression(o) ⇒ Object
relationship_side: resource | resourceref | collection | variable | quotedtext | selector | casestatement | hasharrayaccesses.
- #check_ReservedWord(o) ⇒ Object
- #check_ResourceBody(o) ⇒ Object
- #check_ResourceDefaultsExpression(o) ⇒ Object
- #check_ResourceExpression(o) ⇒ Object
- #check_ResourceOverrideExpression(o) ⇒ Object
- #check_ResourceTypeDefinition(o) ⇒ Object
- #check_SelectorEntry(o) ⇒ Object
- #check_SelectorExpression(o) ⇒ Object
- #check_UnaryExpression(o) ⇒ Object
- #check_UnlessExpression(o) ⇒ Object
-
#check_VariableExpression(o) ⇒ Object
Checks that variable is either strictly 0, or a non 0 starting decimal number, or a valid VAR_NAME.
-
#ends_with_idem(o) ⇒ Object
Returns the last expression in a block, or the expression, if that expression is idem.
-
#hostname(o, semantic) ⇒ Object
Performs check if this is a vaid hostname expression.
-
#hostname_Array(o, semantic) ⇒ Object
Transforms Array of host matching expressions into a (Ruby) array of AST::HostName.
- #hostname_ConcatenatedString(o, semantic) ⇒ Object
- #hostname_LiteralDefault(o, semantic) ⇒ Object
- #hostname_LiteralNumber(o, semantic) ⇒ Object
- #hostname_LiteralRegularExpression(o, semantic) ⇒ Object
- #hostname_LiteralValue(o, semantic) ⇒ Object
- #hostname_Object(o, semantic) ⇒ Object
- #hostname_QualifiedName(o, semantic) ⇒ Object
- #hostname_QualifiedReference(o, semantic) ⇒ Object
- #hostname_String(o, semantic) ⇒ Object
-
#idem(o) ⇒ Boolean
Checks if the expression has side effect (‘idem’ is latin for ‘the same’, here meaning that the evaluation state is known to be unchanged after the expression has been evaluated).
- #idem_AccessExpression(o) ⇒ Object
- #idem_AssignmentExpression(o) ⇒ Object
- #idem_BinaryExpression(o) ⇒ Object
- #idem_BlockExpression(o) ⇒ Object
-
#idem_CaseExpression(o) ⇒ Object
Case expression is idem, if test, and all options are idem.
-
#idem_CaseOption(o) ⇒ Object
An option is idem if values and the then_expression are idem.
-
#idem_ConcatenatedString(o) ⇒ Object
Returns true even though there may be interpolated expressions that have side effect.
- #idem_Factory(o) ⇒ Object
-
#idem_HeredocExpression(o) ⇒ Object
Heredoc is just a string, but may contain interpolated string (which may have side effects).
- #idem_IfExpression(o) ⇒ Object
- #idem_Literal(o) ⇒ Object
- #idem_LiteralHash(o) ⇒ Object
- #idem_LiteralList(o) ⇒ Object
- #idem_NilClass(o) ⇒ Object
- #idem_Nop(o) ⇒ Object
-
#idem_Object(o) ⇒ Object
–IDEM CHECK.
-
#idem_ParenthesizedExpression(o) ⇒ Object
Allow (no-effect parentheses) to be used around a productive expression.
- #idem_RelationshipExpression(o) ⇒ Object
- #idem_RenderExpression(o) ⇒ Object
- #idem_RenderStringExpression(o) ⇒ Object
-
#idem_SelectorExpression(o) ⇒ Object
May technically have side effects inside the Selector, but this is bad design - treat as idem.
-
#idem_UnaryExpression(o) ⇒ Object
Handles UnaryMinusExpression, NotExpression, VariableExpression.
-
#initialize(diagnostics_producer) ⇒ Checker4_0
constructor
Initializes the validator with a diagnostics producer.
- #internal_check_capture_last(o) ⇒ Object
- #internal_check_no_capture(o, container = o) ⇒ Object
- #internal_check_no_idem_last(o) ⇒ Object
- #internal_check_reserved_params(o) ⇒ Object
-
#query(o) ⇒ Object
Performs check if this is valid as a query.
-
#query_BooleanExpression(o) ⇒ Object
Allows AND, OR, and checks if left/right are allowed in query.
-
#query_ComparisonExpression(o) ⇒ Object
Puppet AST only allows == and !=.
- #query_LiteralBoolean(o) ⇒ Object
- #query_LiteralNumber(o) ⇒ Object
- #query_LiteralString(o) ⇒ Object
-
#query_Object(o) ⇒ Object
Anything not explicitly allowed is flagged as error.
- #query_ParenthesizedExpression(o) ⇒ Object
- #query_QualifiedName(o) ⇒ Object
- #query_VariableExpression(o) ⇒ Object
-
#relation(o) ⇒ Object
Performs check if this is valid as a relationship side.
- #relation_CollectExpression(o) ⇒ Object
- #relation_Object(o) ⇒ Object
- #relation_RelationshipExpression(o) ⇒ Object
-
#rvalue(o) ⇒ Object
Performs check if this is valid as a rvalue.
- #rvalue_CollectExpression(o) ⇒ Object
- #rvalue_Definition(o) ⇒ Object
-
#rvalue_Expression(o) ⇒ Object
By default, all expressions are reported as being rvalues Implement specific rvalue checks for those that are not.
- #rvalue_NodeDefinition(o) ⇒ Object
- #rvalue_UnaryExpression(o) ⇒ Object
-
#top(o, definition) ⇒ Object
Performs check if this is valid as a container of a definition (class, define, node).
- #top_BlockExpression(o, definition) ⇒ Object
- #top_HostClassDefinition(o, definition) ⇒ Object
-
#top_LambdaExpression(o, definition) ⇒ Object
A LambdaExpression is a BlockExpression, and this method is needed to prevent the polymorph method for BlockExpression to accept a lambda.
-
#top_NilClass(o, definition) ⇒ Object
—TOP CHECK.
- #top_Object(o, definition) ⇒ Object
- #top_Program(o, definition) ⇒ Object
-
#validate(model) ⇒ Object
Validates the entire model by visiting each model element and calling ‘check`.
-
#varname_to_s(o) ⇒ Object
Produces string part of something named, or nil if not a QualifiedName or QualifiedReference.
Constructor Details
#initialize(diagnostics_producer) ⇒ Checker4_0
Initializes the validator with a diagnostics producer. This object must respond to ‘:will_accept?` and `:accept`.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 22 def initialize(diagnostics_producer) @@check_visitor ||= Puppet::Pops::Visitor.new(nil, "check", 0, 0) @@rvalue_visitor ||= Puppet::Pops::Visitor.new(nil, "rvalue", 0, 0) @@hostname_visitor ||= Puppet::Pops::Visitor.new(nil, "hostname", 1, 2) @@assignment_visitor ||= Puppet::Pops::Visitor.new(nil, "assign", 0, 1) @@query_visitor ||= Puppet::Pops::Visitor.new(nil, "query", 0, 0) @@top_visitor ||= Puppet::Pops::Visitor.new(nil, "top", 1, 1) @@relation_visitor ||= Puppet::Pops::Visitor.new(nil, "relation", 0, 0) @@idem_visitor ||= Puppet::Pops::Visitor.new(self, "idem", 0, 0) @acceptor = diagnostics_producer # Use null migration checker unless given in context @migration_checker = (Puppet.lookup(:migration_checker) { Puppet::Pops::Migration::MigrationChecker.new() }) end |
Instance Attribute Details
#acceptor ⇒ Object (readonly)
16 17 18 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 16 def acceptor @acceptor end |
#migration_checker ⇒ Object (readonly)
17 18 19 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 17 def migration_checker @migration_checker end |
Instance Method Details
#assign(o, via_index = false) ⇒ Object
Checks the LHS of an assignment (is it assignable?). If args is true, assignment via index is checked.
82 83 84 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 82 def assign(o, via_index = false) @@assignment_visitor.visit_this_1(self, o, via_index) end |
#assign_AccessExpression(o, via_index) ⇒ Object
123 124 125 126 127 128 129 130 131 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 123 def assign_AccessExpression(o, via_index) # Are indexed assignments allowed at all ? $x[x] = '...' if acceptor.will_accept? Issues::ILLEGAL_INDEXED_ASSIGNMENT acceptor.accept(Issues::ILLEGAL_INDEXED_ASSIGNMENT, o) else # Then the left expression must be assignable-via-index assign(o.left_expr, true) end end |
#assign_LiteralList(o, via_index) ⇒ Object
133 134 135 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 133 def assign_LiteralList(o, via_index) o.values.each {|x| assign(x) } end |
#assign_Object(o, via_index) ⇒ Object
137 138 139 140 141 142 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 137 def assign_Object(o, via_index) # Can not assign to anything else (differentiate if this is via index or not) # i.e. 10 = 'hello' vs. 10['x'] = 'hello' (the root is reported as being in error in both cases) # acceptor.accept(via_index ? Issues::ILLEGAL_ASSIGNMENT_VIA_INDEX : Issues::ILLEGAL_ASSIGNMENT, o) end |
#assign_VariableExpression(o, via_index) ⇒ Object
—ASSIGNMENT CHECKS
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 107 def assign_VariableExpression(o, via_index) varname_string = varname_to_s(o.expr) if varname_string =~ Puppet::Pops::Patterns::NUMERIC_VAR_NAME acceptor.accept(Issues::ILLEGAL_NUMERIC_ASSIGNMENT, o, :varname => varname_string) end # Can not assign to something in another namespace (i.e. a '::' in the name is not legal) if acceptor.will_accept? Issues::CROSS_SCOPE_ASSIGNMENT if varname_string =~ /::/ acceptor.accept(Issues::CROSS_SCOPE_ASSIGNMENT, o, :name => varname_string) end end # TODO: Could scan for reassignment of the same variable if done earlier in the same container # Or if assigning to a parameter (more work). end |
#check(o) ⇒ Object
Performs regular validity check
49 50 51 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 49 def check(o) @@check_visitor.visit_this_0(self, o) end |
#check_AccessExpression(o) ⇒ Object
153 154 155 156 157 158 159 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 153 def check_AccessExpression(o) # Only min range is checked, all other checks are RT checks as they depend on the resulting type # of the LHS. if o.keys.size < 1 acceptor.accept(Issues::MISSING_INDEX, o) end end |
#check_AssignmentExpression(o) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 161 def check_AssignmentExpression(o) case o.operator when :'=' assign(o.left_expr) rvalue(o.right_expr) when :'+=', :'-=' acceptor.accept(Issues::APPENDS_DELETES_NO_LONGER_SUPPORTED, o, {:operator => o.operator}) else acceptor.accept(Issues::UNSUPPORTED_OPERATOR, o, {:operator => o.operator}) end end |
#check_AttributeOperation(o) ⇒ Object
Checks that operation with :+> is contained in a ResourceOverride or Collector.
Parent of an AttributeOperation can be one of:
-
CollectExpression
-
ResourceOverride
-
ResourceBody (ILLEGAL this is a regular resource expression)
-
ResourceDefaults (ILLEGAL)
181 182 183 184 185 186 187 188 189 190 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 181 def check_AttributeOperation(o) if o.operator == :'+>' # Append operator use is constrained parent = o.eContainer unless parent.is_a?(Model::CollectExpression) || parent.is_a?(Model::ResourceOverrideExpression) acceptor.accept(Issues::ILLEGAL_ATTRIBUTE_APPEND, o, {:name=>o.attribute_name, :parent=>parent}) end end rvalue(o.value_expr) end |
#check_AttributesOperation(o) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 192 def check_AttributesOperation(o) # Append operator use is constrained parent1 = o.eContainer case parent1 when Model::AbstractResource when Model::CollectExpression else # protect against just testing a snippet that has no parent, error message will be a bit strange # but it is not for a real program. parent2 = parent1.nil? ? o : parent1.eContainer unless parent2.is_a?(Model::AbstractResource) acceptor.accept(Issues::UNSUPPORTED_OPERATOR_IN_CONTEXT, parent2, :operator=>'* =>') end end rvalue(o.expr) end |
#check_BinaryExpression(o) ⇒ Object
209 210 211 212 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 209 def check_BinaryExpression(o) rvalue(o.left_expr) rvalue(o.right_expr) end |
#check_BlockExpression(o) ⇒ Object
214 215 216 217 218 219 220 221 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 214 def check_BlockExpression(o) o.statements[0..-2].each do |statement| if idem(statement) acceptor.accept(Issues::IDEM_EXPRESSION_NOT_LAST, statement) break # only flag the first end end end |
#check_CallNamedFunctionExpression(o) ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 223 def check_CallNamedFunctionExpression(o) case o.functor_expr when Puppet::Pops::Model::QualifiedName # ok nil when Puppet::Pops::Model::RenderStringExpression # helpful to point out this easy to make Epp error acceptor.accept(Issues::ILLEGAL_EPP_PARAMETERS, o) else acceptor.accept(Issues::ILLEGAL_EXPRESSION, o.functor_expr, {:feature=>'function name', :container => o}) end end |
#check_CaseExpression(o) ⇒ Object
248 249 250 251 252 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 248 def check_CaseExpression(o) rvalue(o.test) # There should only be one LiteralDefault case option value # TODO: Implement this check end |
#check_CaseOption(o) ⇒ Object
254 255 256 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 254 def check_CaseOption(o) o.values.each { |v| rvalue(v) } end |
#check_CollectExpression(o) ⇒ Object
258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 258 def check_CollectExpression(o) unless o.type_expr.is_a? Model::QualifiedReference acceptor.accept(Issues::ILLEGAL_EXPRESSION, o.type_expr, :feature=> 'type name', :container => o) end # If a collect expression tries to collect exported resources and storeconfigs is not on # then it will not work... This was checked in the parser previously. This is a runtime checking # thing as opposed to a language thing. if acceptor.will_accept?(Issues::RT_NO_STORECONFIGS) && o.query.is_a?(Model::ExportedQuery) acceptor.accept(Issues::RT_NO_STORECONFIGS, o) end end |
#check_EppExpression(o) ⇒ Object
236 237 238 239 240 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 236 def check_EppExpression(o) if o.eContainer.is_a?(Puppet::Pops::Model::LambdaExpression) internal_check_no_capture(o.eContainer, o) end end |
#check_Factory(o) ⇒ Object
149 150 151 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 149 def check_Factory(o) check(o.current) end |
#check_FunctionDefinition(o) ⇒ Object
314 315 316 317 318 319 320 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 314 def check_FunctionDefinition(o) # TODO PUP-2080: more strict rule for top - can only be contained in Program (for now) # sticking functions in classes would create functions in the class name space # but not be special in any other way # check_NamedDefinition(o) end |
#check_HostClassDefinition(o) ⇒ Object
322 323 324 325 326 327 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 322 def check_HostClassDefinition(o) check_NamedDefinition(o) internal_check_no_capture(o) internal_check_reserved_params(o) internal_check_no_idem_last(o) end |
#check_IfExpression(o) ⇒ Object
372 373 374 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 372 def check_IfExpression(o) rvalue(o.test) end |
#check_KeyedEntry(o) ⇒ Object
376 377 378 379 380 381 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 376 def check_KeyedEntry(o) rvalue(o.key) rvalue(o.value) # In case there are additional things to forbid than non-rvalues # acceptor.accept(Issues::ILLEGAL_EXPRESSION, o.key, :feature => 'hash key', :container => o.eContainer) end |
#check_LambdaExpression(o) ⇒ Object
383 384 385 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 383 def check_LambdaExpression(o) internal_check_capture_last(o) end |
#check_LiteralList(o) ⇒ Object
387 388 389 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 387 def check_LiteralList(o) o.values.each {|v| rvalue(v) } end |
#check_MethodCallExpression(o) ⇒ Object
242 243 244 245 246 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 242 def check_MethodCallExpression(o) unless o.functor_expr.is_a? Model::QualifiedName acceptor.accept(Issues::ILLEGAL_EXPRESSION, o.functor_expr, :feature => 'function name', :container => o) end end |
#check_NamedAccessExpression(o) ⇒ Object
Only used for function names, grammar should not be able to produce something faulty, but check anyway if model is created programatically (it will fail in transformation to AST for sure).
273 274 275 276 277 278 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 273 def check_NamedAccessExpression(o) name = o.right_expr unless name.is_a? Model::QualifiedName acceptor.accept(Issues::ILLEGAL_EXPRESSION, name, :feature=> 'function name', :container => o.eContainer) end end |
#check_NamedDefinition(o) ⇒ Object
for ‘class’, ‘define’, and function
303 304 305 306 307 308 309 310 311 312 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 303 def check_NamedDefinition(o) top(o.eContainer, o) if o.name !~ Puppet::Pops::Patterns::CLASSREF acceptor.accept(Issues::ILLEGAL_DEFINITION_NAME, o, {:name=>o.name}) end if RESERVED_TYPE_NAMES[o.name()] acceptor.accept(Issues::RESERVED_TYPE_NAME, o, {:name => o.name}) end end |
#check_NodeDefinition(o) ⇒ Object
391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 391 def check_NodeDefinition(o) # Check that hostnames are valid hostnames (or regular expressions) hostname(o.host_matches, o) top(o.eContainer, o) if violator = ends_with_idem(o.body) acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o}) end unless o.parent.nil? acceptor.accept(Issues::ILLEGAL_NODE_INHERITANCE, o.parent) end end |
#check_Object(o) ⇒ Object
—CHECKS
146 147 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 146 def check_Object(o) end |
#check_Parameter(o) ⇒ Object
432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 432 def check_Parameter(o) if o.name =~ /^(?:0x)?[0-9]+$/ acceptor.accept(Issues::ILLEGAL_NUMERIC_PARAMETER, o, :name => o.name) end return unless o.value if o.value.is_a?(Puppet::Pops::Model::AssignmentExpression) [o.value] else o.value.eAllContents.select {|model| model.is_a? Puppet::Pops::Model::AssignmentExpression } end.each do |assignment| acceptor.accept(Issues::ILLEGAL_ASSIGNMENT_CONTEXT, assignment) end end |
#check_QualifiedName(o) ⇒ Object
No checking takes place - all expressions using a QualifiedName need to check. This because the rules are slightly different depending on the container (A variable allows a numeric start, but not other names). This means that (if the lexer/parser so chooses) a QualifiedName can be anything when it represents a Bare Word and evaluates to a String.
408 409 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 408 def check_QualifiedName(o) end |
#check_QualifiedReference(o) ⇒ Object
Checks that the value is a valid UpperCaseWord (a CLASSREF), and optionally if it contains a hypen. DOH: QualifiedReferences are created with LOWER CASE NAMES at parse time
413 414 415 416 417 418 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 413 def check_QualifiedReference(o) # Is this a valid qualified name? if o.value !~ Puppet::Pops::Patterns::CLASSREF acceptor.accept(Issues::ILLEGAL_CLASSREF, o, {:name=>o.value}) end end |
#check_QueryExpression(o) ⇒ Object
420 421 422 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 420 def check_QueryExpression(o) query(o.expr) if o.expr # is optional end |
#check_RelationshipExpression(o) ⇒ Object
relationship_side: resource
| resourceref
| collection
| variable
| quotedtext
| selector
| casestatement
| hasharrayaccesses
456 457 458 459 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 456 def check_RelationshipExpression(o) relation(o.left_expr) relation(o.right_expr) end |
#check_ReservedWord(o) ⇒ Object
493 494 495 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 493 def check_ReservedWord(o) acceptor.accept(Issues::RESERVED_WORD, o, :word => o.word) end |
#check_ResourceBody(o) ⇒ Object
468 469 470 471 472 473 474 475 476 477 478 479 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 468 def check_ResourceBody(o) seenUnfolding = false o.operations.each do |ao| if ao.is_a?(Puppet::Pops::Model::AttributesOperation) if seenUnfolding acceptor.accept(Issues::MULTIPLE_ATTRIBUTES_UNFOLD, ao) else seenUnfolding = true end end end end |
#check_ResourceDefaultsExpression(o) ⇒ Object
481 482 483 484 485 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 481 def check_ResourceDefaultsExpression(o) if o.form && o.form != :regular acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o) end end |
#check_ResourceExpression(o) ⇒ Object
461 462 463 464 465 466 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 461 def check_ResourceExpression(o) # The expression for type name cannot be statically checked - this is instead done at runtime # to enable better error message of the result of the expression rather than the static instruction. # (This can be revised as there are static constructs that are illegal, but require updating many # tests that expect the detailed reporting). end |
#check_ResourceOverrideExpression(o) ⇒ Object
487 488 489 490 491 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 487 def check_ResourceOverrideExpression(o) if o.form && o.form != :regular acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o) end end |
#check_ResourceTypeDefinition(o) ⇒ Object
329 330 331 332 333 334 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 329 def check_ResourceTypeDefinition(o) check_NamedDefinition(o) internal_check_no_capture(o) internal_check_reserved_params(o) internal_check_no_idem_last(o) end |
#check_SelectorEntry(o) ⇒ Object
501 502 503 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 501 def check_SelectorEntry(o) rvalue(o.matching_expr) end |
#check_SelectorExpression(o) ⇒ Object
497 498 499 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 497 def check_SelectorExpression(o) rvalue(o.left_expr) end |
#check_UnaryExpression(o) ⇒ Object
505 506 507 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 505 def check_UnaryExpression(o) rvalue(o.expr) end |
#check_UnlessExpression(o) ⇒ Object
509 510 511 512 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 509 def check_UnlessExpression(o) rvalue(o.test) # TODO: Unless may not have an else part that is an IfExpression (grammar denies this though) end |
#check_VariableExpression(o) ⇒ Object
Checks that variable is either strictly 0, or a non 0 starting decimal number, or a valid VAR_NAME
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 515 def check_VariableExpression(o) # The expression must be a qualified name or an integer name_expr = o.expr return if name_expr.is_a?(Model::LiteralInteger) if !name_expr.is_a?(Model::QualifiedName) acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, :feature => 'name', :container => o) else # name must be either a decimal string value, or a valid NAME name = o.expr.value if name[0,1] =~ /[0-9]/ unless name =~ Puppet::Pops::Patterns::NUMERIC_VAR_NAME acceptor.accept(Issues::ILLEGAL_NUMERIC_VAR_NAME, o, :name => name) end else unless name =~ Puppet::Pops::Patterns::VAR_NAME acceptor.accept(Issues::ILLEGAL_VAR_NAME, o, :name => name) end end end end |
#ends_with_idem(o) ⇒ Object
Returns the last expression in a block, or the expression, if that expression is idem
96 97 98 99 100 101 102 103 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 96 def ends_with_idem(o) if o.is_a?(Puppet::Pops::Model::BlockExpression) last = o.statements[-1] idem(last) ? last : nil else idem(o) ? o : nil end end |
#hostname(o, semantic) ⇒ Object
Performs check if this is a vaid hostname expression
55 56 57 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 55 def hostname(o, semantic) @@hostname_visitor.visit_this_1(self, o, semantic) end |
#hostname_Array(o, semantic) ⇒ Object
Transforms Array of host matching expressions into a (Ruby) array of AST::HostName
539 540 541 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 539 def hostname_Array(o, semantic) o.each {|x| hostname(x, semantic) } end |
#hostname_ConcatenatedString(o, semantic) ⇒ Object
557 558 559 560 561 562 563 564 565 566 567 568 569 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 557 def hostname_ConcatenatedString(o, semantic) # Puppet 3.1. only accepts a concatenated string without interpolated expressions if the_expr = o.segments.index {|s| s.is_a?(Model::TextExpression) } acceptor.accept(Issues::ILLEGAL_HOSTNAME_INTERPOLATION, o.segments[the_expr].expr) elsif o.segments.size() != 1 # corner case, bad model, concatenation of several plain strings acceptor.accept(Issues::ILLEGAL_HOSTNAME_INTERPOLATION, o) else # corner case, may be ok, but lexer may have replaced with plain string, this is # here if it does not hostname_String(o.segments[0], o.segments[0]) end end |
#hostname_LiteralDefault(o, semantic) ⇒ Object
583 584 585 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 583 def hostname_LiteralDefault(o, semantic) # always ok end |
#hostname_LiteralNumber(o, semantic) ⇒ Object
579 580 581 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 579 def hostname_LiteralNumber(o, semantic) # always ok end |
#hostname_LiteralRegularExpression(o, semantic) ⇒ Object
587 588 589 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 587 def hostname_LiteralRegularExpression(o, semantic) # always ok end |
#hostname_LiteralValue(o, semantic) ⇒ Object
553 554 555 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 553 def hostname_LiteralValue(o, semantic) hostname_String(o.value.to_s, o) end |
#hostname_Object(o, semantic) ⇒ Object
591 592 593 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 591 def hostname_Object(o, semantic) acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, {:feature => 'hostname', :container => semantic}) end |
#hostname_QualifiedName(o, semantic) ⇒ Object
571 572 573 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 571 def hostname_QualifiedName(o, semantic) hostname_String(o.value.to_s, o) end |
#hostname_QualifiedReference(o, semantic) ⇒ Object
575 576 577 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 575 def hostname_QualifiedReference(o, semantic) hostname_String(o.value.to_s, o) end |
#hostname_String(o, semantic) ⇒ Object
543 544 545 546 547 548 549 550 551 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 543 def hostname_String(o, semantic) # The 3.x checker only checks for illegal characters - if matching /[^-\w.]/ the name is invalid, # but this allows pathological names like "a..b......c", "----" # TODO: Investigate if more illegal hostnames should be flagged. # if o =~ Puppet::Pops::Patterns::ILLEGAL_HOSTNAME_CHARS acceptor.accept(Issues::ILLEGAL_HOSTNAME_CHARS, semantic, :hostname => o) end end |
#idem(o) ⇒ Boolean
Checks if the expression has side effect (‘idem’ is latin for ‘the same’, here meaning that the evaluation state is known to be unchanged after the expression has been evaluated). The result is not 100% authoritative for negative answers since analysis of function behavior is not possible.
91 92 93 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 91 def idem(o) @@idem_visitor.visit_this_0(self, o) end |
#idem_AccessExpression(o) ⇒ Object
705 706 707 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 705 def idem_AccessExpression(o) true end |
#idem_AssignmentExpression(o) ⇒ Object
718 719 720 721 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 718 def idem_AssignmentExpression(o) # Always side effect false end |
#idem_BinaryExpression(o) ⇒ Object
709 710 711 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 709 def idem_BinaryExpression(o) true end |
#idem_BlockExpression(o) ⇒ Object
741 742 743 744 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 741 def idem_BlockExpression(o) # productive if there is at least one productive expression ! o.statements.any? {|expr| !idem(expr) } end |
#idem_CaseExpression(o) ⇒ Object
Case expression is idem, if test, and all options are idem
769 770 771 772 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 769 def idem_CaseExpression(o) return false if !idem(o.test) ! o..any? {|opt| !idem(opt) } end |
#idem_CaseOption(o) ⇒ Object
An option is idem if values and the then_expression are idem
775 776 777 778 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 775 def idem_CaseOption(o) return false if o.values.any? { |value| !idem(value) } idem(o.then_expr) end |
#idem_ConcatenatedString(o) ⇒ Object
Returns true even though there may be interpolated expressions that have side effect. Report as idem anyway, as it is very bad design to evaluate an interpolated string for its side effect only.
749 750 751 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 749 def idem_ConcatenatedString(o) true end |
#idem_Factory(o) ⇒ Object
701 702 703 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 701 def idem_Factory(o) idem(o.current) end |
#idem_HeredocExpression(o) ⇒ Object
Heredoc is just a string, but may contain interpolated string (which may have side effects). This is still bad design and should be reported as idem.
755 756 757 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 755 def idem_HeredocExpression(o) true end |
#idem_IfExpression(o) ⇒ Object
764 765 766 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 764 def idem_IfExpression(o) [o.test, o.then_expr, o.else_expr].all? {|e| idem(e) } end |
#idem_Literal(o) ⇒ Object
689 690 691 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 689 def idem_Literal(o) true end |
#idem_LiteralHash(o) ⇒ Object
697 698 699 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 697 def idem_LiteralHash(o) true end |
#idem_LiteralList(o) ⇒ Object
693 694 695 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 693 def idem_LiteralList(o) true end |
#idem_NilClass(o) ⇒ Object
685 686 687 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 685 def idem_NilClass(o) true end |
#idem_Nop(o) ⇒ Object
681 682 683 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 681 def idem_Nop(o) true end |
#idem_Object(o) ⇒ Object
–IDEM CHECK
677 678 679 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 677 def idem_Object(o) false end |
#idem_ParenthesizedExpression(o) ⇒ Object
Allow (no-effect parentheses) to be used around a productive expression
729 730 731 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 729 def idem_ParenthesizedExpression(o) idem(o.expr) end |
#idem_RelationshipExpression(o) ⇒ Object
713 714 715 716 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 713 def idem_RelationshipExpression(o) # Always side effect false end |
#idem_RenderExpression(o) ⇒ Object
733 734 735 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 733 def idem_RenderExpression(o) false end |
#idem_RenderStringExpression(o) ⇒ Object
737 738 739 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 737 def idem_RenderStringExpression(o) false end |
#idem_SelectorExpression(o) ⇒ Object
May technically have side effects inside the Selector, but this is bad design - treat as idem
760 761 762 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 760 def idem_SelectorExpression(o) true end |
#idem_UnaryExpression(o) ⇒ Object
Handles UnaryMinusExpression, NotExpression, VariableExpression
724 725 726 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 724 def idem_UnaryExpression(o) true end |
#internal_check_capture_last(o) ⇒ Object
342 343 344 345 346 347 348 349 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 342 def internal_check_capture_last(o) accepted_index = o.parameters.size() -1 o.parameters.each_with_index do |p, index| if p.captures_rest && index != accepted_index acceptor.accept(Issues::CAPTURES_REST_NOT_LAST, p, {:param_name => p.name}) end end end |
#internal_check_no_capture(o, container = o) ⇒ Object
351 352 353 354 355 356 357 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 351 def internal_check_no_capture(o, container = o) o.parameters.each do |p| if p.captures_rest acceptor.accept(Issues::CAPTURES_REST_NOT_SUPPORTED, p, {:container => container, :param_name => p.name}) end end end |
#internal_check_no_idem_last(o) ⇒ Object
336 337 338 339 340 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 336 def internal_check_no_idem_last(o) if violator = ends_with_idem(o.body) acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o}) end end |
#internal_check_reserved_params(o) ⇒ Object
364 365 366 367 368 369 370 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 364 def internal_check_reserved_params(o) o.parameters.each do |p| if RESERVED_PARAMETERS[p.name] acceptor.accept(Issues::RESERVED_PARAMETER, p, {:container => o, :param_name => p.name}) end end end |
#query(o) ⇒ Object
Performs check if this is valid as a query
60 61 62 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 60 def query(o) @@query_visitor.visit_this_0(self, o) end |
#query_BooleanExpression(o) ⇒ Object
Allows AND, OR, and checks if left/right are allowed in query.
609 610 611 612 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 609 def query_BooleanExpression(o) query o.left_expr query o.right_expr end |
#query_ComparisonExpression(o) ⇒ Object
Puppet AST only allows == and !=
604 605 606 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 604 def query_ComparisonExpression(o) acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o) unless [:'==', :'!='].include? o.operator end |
#query_LiteralBoolean(o) ⇒ Object
626 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 626 def query_LiteralBoolean(o); end |
#query_LiteralNumber(o) ⇒ Object
622 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 622 def query_LiteralNumber(o); end |
#query_LiteralString(o) ⇒ Object
624 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 624 def query_LiteralString(o); end |
#query_Object(o) ⇒ Object
Anything not explicitly allowed is flagged as error.
598 599 600 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 598 def query_Object(o) acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o) end |
#query_ParenthesizedExpression(o) ⇒ Object
614 615 616 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 614 def query_ParenthesizedExpression(o) query(o.expr) end |
#query_QualifiedName(o) ⇒ Object
620 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 620 def query_QualifiedName(o); end |
#query_VariableExpression(o) ⇒ Object
618 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 618 def query_VariableExpression(o); end |
#relation(o) ⇒ Object
Performs check if this is valid as a relationship side
65 66 67 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 65 def relation(o) @@relation_visitor.visit_this_0(self, o) end |
#relation_CollectExpression(o) ⇒ Object
428 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 428 def relation_CollectExpression(o); end |
#relation_Object(o) ⇒ Object
424 425 426 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 424 def relation_Object(o) rvalue(o) end |
#relation_RelationshipExpression(o) ⇒ Object
430 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 430 def relation_RelationshipExpression(o); end |
#rvalue(o) ⇒ Object
Performs check if this is valid as a rvalue
70 71 72 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 70 def rvalue(o) @@rvalue_visitor.visit_this_0(self, o) end |
#rvalue_CollectExpression(o) ⇒ Object
635 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 635 def rvalue_CollectExpression(o) ; acceptor.accept(Issues::NOT_RVALUE, o) ; end |
#rvalue_Definition(o) ⇒ Object
637 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 637 def rvalue_Definition(o) ; acceptor.accept(Issues::NOT_RVALUE, o) ; end |
#rvalue_Expression(o) ⇒ Object
By default, all expressions are reported as being rvalues Implement specific rvalue checks for those that are not.
633 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 633 def rvalue_Expression(o); end |
#rvalue_NodeDefinition(o) ⇒ Object
639 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 639 def rvalue_NodeDefinition(o) ; acceptor.accept(Issues::NOT_RVALUE, o) ; end |
#rvalue_UnaryExpression(o) ⇒ Object
641 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 641 def rvalue_UnaryExpression(o) ; rvalue o.expr ; end |
#top(o, definition) ⇒ Object
Performs check if this is valid as a container of a definition (class, define, node)
75 76 77 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 75 def top(o, definition) @@top_visitor.visit_this_1(self, o, definition) end |
#top_BlockExpression(o, definition) ⇒ Object
654 655 656 657 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 654 def top_BlockExpression(o, definition) # ok, if this is a block representing the body of a class, or is top level top o.eContainer, definition end |
#top_HostClassDefinition(o, definition) ⇒ Object
659 660 661 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 659 def top_HostClassDefinition(o, definition) # ok, stop scanning parents end |
#top_LambdaExpression(o, definition) ⇒ Object
A LambdaExpression is a BlockExpression, and this method is needed to prevent the polymorph method for BlockExpression to accept a lambda. A lambda can not iteratively create classes, nodes or defines as the lambda does not have a closure.
671 672 673 674 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 671 def top_LambdaExpression(o, definition) # fail, stop scanning parents acceptor.accept(Issues::NOT_TOP_LEVEL, definition) end |
#top_NilClass(o, definition) ⇒ Object
—TOP CHECK
645 646 647 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 645 def top_NilClass(o, definition) # ok, reached the top, no more parents end |
#top_Object(o, definition) ⇒ Object
649 650 651 652 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 649 def top_Object(o, definition) # fail, reached a container that is not top level acceptor.accept(Issues::NOT_TOP_LEVEL, definition) end |
#top_Program(o, definition) ⇒ Object
663 664 665 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 663 def top_Program(o, definition) # ok end |
#validate(model) ⇒ 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.
42 43 44 45 46 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 42 def validate(model) # tree iterate the model, and call check for each element check(model) model.eAllContents.each {|m| check(m) } end |
#varname_to_s(o) ⇒ Object
Produces string part of something named, or nil if not a QualifiedName or QualifiedReference
784 785 786 787 788 789 790 791 792 793 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 784 def varname_to_s(o) case o when Model::QualifiedName o.value when Model::QualifiedReference o.value else nil end end |