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_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_HostClassDefinition(o) ⇒ Object
- #check_IfExpression(o) ⇒ Object
- #check_KeyedEntry(o) ⇒ Object
- #check_LambdaExpression(o) ⇒ Object
- #check_LiteralFloat(o) ⇒ Object
- #check_LiteralInteger(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, single_feature_name = nil) ⇒ Object
Performs check if this is a vaid hostname expression.
-
#hostname_Array(o, semantic, single_feature_name) ⇒ Object
Transforms Array of host matching expressions into a (Ruby) array of AST::HostName.
- #hostname_ConcatenatedString(o, semantic, single_feature_name) ⇒ Object
- #hostname_LiteralDefault(o, semantic, single_feature_name) ⇒ Object
- #hostname_LiteralNumber(o, semantic, single_feature_name) ⇒ Object
- #hostname_LiteralRegularExpression(o, semantic, single_feature_name) ⇒ Object
- #hostname_LiteralValue(o, semantic, single_feature_name) ⇒ Object
- #hostname_Object(o, semantic, single_feature_name) ⇒ Object
- #hostname_QualifiedName(o, semantic, single_feature_name) ⇒ Object
- #hostname_QualifiedReference(o, semantic, single_feature_name) ⇒ Object
- #hostname_String(o, semantic, single_feature_name) ⇒ 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_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_Object(o, via_index) ⇒ Object
133 134 135 136 137 138 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 133 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). # TODO: Investigate if there are invalid cases for += assignment 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
149 150 151 152 153 154 155 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 149 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
157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 157 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)
177 178 179 180 181 182 183 184 185 186 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 177 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
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 188 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
205 206 207 208 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 205 def check_BinaryExpression(o) rvalue(o.left_expr) rvalue(o.right_expr) end |
#check_BlockExpression(o) ⇒ Object
210 211 212 213 214 215 216 217 218 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 210 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 migration_checker.report_array_last_in_block(o.statements[-1]) end |
#check_CallNamedFunctionExpression(o) ⇒ Object
220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 220 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
245 246 247 248 249 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 245 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
251 252 253 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 251 def check_CaseOption(o) o.values.each { |v| rvalue(v) } end |
#check_CollectExpression(o) ⇒ Object
255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 255 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
233 234 235 236 237 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 233 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
145 146 147 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 145 def check_Factory(o) check(o.current) end |
#check_HostClassDefinition(o) ⇒ Object
315 316 317 318 319 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 315 def check_HostClassDefinition(o) check_NamedDefinition(o) internal_check_no_capture(o) internal_check_reserved_params(o) end |
#check_IfExpression(o) ⇒ Object
357 358 359 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 357 def check_IfExpression(o) rvalue(o.test) end |
#check_KeyedEntry(o) ⇒ Object
361 362 363 364 365 366 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 361 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
368 369 370 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 368 def check_LambdaExpression(o) internal_check_capture_last(o) end |
#check_LiteralFloat(o) ⇒ Object
376 377 378 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 376 def check_LiteralFloat(o) migration_checker.report_ambiguous_float(o) end |
#check_LiteralInteger(o) ⇒ Object
380 381 382 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 380 def check_LiteralInteger(o) migration_checker.report_ambiguous_integer(o) end |
#check_LiteralList(o) ⇒ Object
372 373 374 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 372 def check_LiteralList(o) o.values.each {|v| rvalue(v) } end |
#check_MethodCallExpression(o) ⇒ Object
239 240 241 242 243 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 239 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).
270 271 272 273 274 275 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 270 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
300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 300 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 if violator = ends_with_idem(o.body) acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o}) end end |
#check_NodeDefinition(o) ⇒ Object
384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 384 def check_NodeDefinition(o) # Check that hostnames are valid hostnames (or regular expressions) hostname(o.host_matches, o) hostname(o.parent, o, 'parent') unless o.parent.nil? 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
142 143 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 142 def check_Object(o) end |
#check_Parameter(o) ⇒ Object
426 427 428 429 430 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 426 def check_Parameter(o) if o.name =~ /^(?:0x)?[0-9]+$/ acceptor.accept(Issues::ILLEGAL_NUMERIC_PARAMETER, o, :name => o.name) 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.
402 403 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 402 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
407 408 409 410 411 412 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 407 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
414 415 416 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 414 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
441 442 443 444 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 441 def check_RelationshipExpression(o) relation(o.left_expr) relation(o.right_expr) end |
#check_ReservedWord(o) ⇒ Object
478 479 480 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 478 def check_ReservedWord(o) acceptor.accept(Issues::RESERVED_WORD, o, :word => o.word) end |
#check_ResourceBody(o) ⇒ Object
453 454 455 456 457 458 459 460 461 462 463 464 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 453 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
466 467 468 469 470 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 466 def check_ResourceDefaultsExpression(o) if o.form && o.form != :regular acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o) end end |
#check_ResourceExpression(o) ⇒ Object
446 447 448 449 450 451 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 446 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
472 473 474 475 476 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 472 def check_ResourceOverrideExpression(o) if o.form && o.form != :regular acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o) end end |
#check_ResourceTypeDefinition(o) ⇒ Object
321 322 323 324 325 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 321 def check_ResourceTypeDefinition(o) check_NamedDefinition(o) internal_check_no_capture(o) internal_check_reserved_params(o) end |
#check_SelectorEntry(o) ⇒ Object
486 487 488 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 486 def check_SelectorEntry(o) rvalue(o.matching_expr) end |
#check_SelectorExpression(o) ⇒ Object
482 483 484 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 482 def check_SelectorExpression(o) rvalue(o.left_expr) end |
#check_UnaryExpression(o) ⇒ Object
490 491 492 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 490 def check_UnaryExpression(o) rvalue(o.expr) end |
#check_UnlessExpression(o) ⇒ Object
494 495 496 497 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 494 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
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 500 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, single_feature_name = nil) ⇒ 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, single_feature_name = nil) @@hostname_visitor.visit_this_2(self, o, semantic, single_feature_name) end |
#hostname_Array(o, semantic, single_feature_name) ⇒ Object
Transforms Array of host matching expressions into a (Ruby) array of AST::HostName
524 525 526 527 528 529 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 524 def hostname_Array(o, semantic, single_feature_name) if single_feature_name acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, {:feature=>single_feature_name, :container=>semantic}) end o.each {|x| hostname(x, semantic, false) } end |
#hostname_ConcatenatedString(o, semantic, single_feature_name) ⇒ Object
545 546 547 548 549 550 551 552 553 554 555 556 557 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 545 def hostname_ConcatenatedString(o, semantic, single_feature_name) # 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], false) end end |
#hostname_LiteralDefault(o, semantic, single_feature_name) ⇒ Object
571 572 573 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 571 def hostname_LiteralDefault(o, semantic, single_feature_name) # always ok end |
#hostname_LiteralNumber(o, semantic, single_feature_name) ⇒ Object
567 568 569 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 567 def hostname_LiteralNumber(o, semantic, single_feature_name) # always ok end |
#hostname_LiteralRegularExpression(o, semantic, single_feature_name) ⇒ Object
575 576 577 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 575 def hostname_LiteralRegularExpression(o, semantic, single_feature_name) # always ok end |
#hostname_LiteralValue(o, semantic, single_feature_name) ⇒ Object
541 542 543 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 541 def hostname_LiteralValue(o, semantic, single_feature_name) hostname_String(o.value.to_s, o, single_feature_name) end |
#hostname_Object(o, semantic, single_feature_name) ⇒ Object
579 580 581 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 579 def hostname_Object(o, semantic, single_feature_name) acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, {:feature=> single_feature_name || 'hostname', :container=>semantic}) end |
#hostname_QualifiedName(o, semantic, single_feature_name) ⇒ Object
559 560 561 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 559 def hostname_QualifiedName(o, semantic, single_feature_name) hostname_String(o.value.to_s, o, single_feature_name) end |
#hostname_QualifiedReference(o, semantic, single_feature_name) ⇒ Object
563 564 565 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 563 def hostname_QualifiedReference(o, semantic, single_feature_name) hostname_String(o.value.to_s, o, single_feature_name) end |
#hostname_String(o, semantic, single_feature_name) ⇒ Object
531 532 533 534 535 536 537 538 539 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 531 def hostname_String(o, semantic, single_feature_name) # 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
693 694 695 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 693 def idem_AccessExpression(o) true end |
#idem_AssignmentExpression(o) ⇒ Object
706 707 708 709 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 706 def idem_AssignmentExpression(o) # Always side effect false end |
#idem_BinaryExpression(o) ⇒ Object
697 698 699 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 697 def idem_BinaryExpression(o) true end |
#idem_BlockExpression(o) ⇒ Object
729 730 731 732 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 729 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
757 758 759 760 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 757 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
763 764 765 766 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 763 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.
737 738 739 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 737 def idem_ConcatenatedString(o) true end |
#idem_Factory(o) ⇒ Object
689 690 691 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 689 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.
743 744 745 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 743 def idem_HeredocExpression(o) true end |
#idem_IfExpression(o) ⇒ Object
752 753 754 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 752 def idem_IfExpression(o) [o.test, o.then_expr, o.else_expr].all? {|e| idem(e) } end |
#idem_Literal(o) ⇒ Object
677 678 679 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 677 def idem_Literal(o) true end |
#idem_LiteralHash(o) ⇒ Object
685 686 687 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 685 def idem_LiteralHash(o) true end |
#idem_LiteralList(o) ⇒ Object
681 682 683 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 681 def idem_LiteralList(o) true end |
#idem_NilClass(o) ⇒ Object
673 674 675 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 673 def idem_NilClass(o) true end |
#idem_Nop(o) ⇒ Object
669 670 671 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 669 def idem_Nop(o) true end |
#idem_Object(o) ⇒ Object
–IDEM CHECK
665 666 667 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 665 def idem_Object(o) false end |
#idem_ParenthesizedExpression(o) ⇒ Object
Allow (no-effect parentheses) to be used around a productive expression
717 718 719 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 717 def idem_ParenthesizedExpression(o) idem(o.expr) end |
#idem_RelationshipExpression(o) ⇒ Object
701 702 703 704 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 701 def idem_RelationshipExpression(o) # Always side effect false end |
#idem_RenderExpression(o) ⇒ Object
721 722 723 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 721 def idem_RenderExpression(o) false end |
#idem_RenderStringExpression(o) ⇒ Object
725 726 727 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 725 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
748 749 750 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 748 def idem_SelectorExpression(o) true end |
#idem_UnaryExpression(o) ⇒ Object
Handles UnaryMinusExpression, NotExpression, VariableExpression
712 713 714 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 712 def idem_UnaryExpression(o) true end |
#internal_check_capture_last(o) ⇒ Object
327 328 329 330 331 332 333 334 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 327 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
336 337 338 339 340 341 342 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 336 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_reserved_params(o) ⇒ Object
349 350 351 352 353 354 355 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 349 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.
597 598 599 600 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 597 def query_BooleanExpression(o) query o.left_expr query o.right_expr end |
#query_ComparisonExpression(o) ⇒ Object
Puppet AST only allows == and !=
592 593 594 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 592 def query_ComparisonExpression(o) acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o) unless [:'==', :'!='].include? o.operator end |
#query_LiteralBoolean(o) ⇒ Object
614 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 614 def query_LiteralBoolean(o); end |
#query_LiteralNumber(o) ⇒ Object
610 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 610 def query_LiteralNumber(o); end |
#query_LiteralString(o) ⇒ Object
612 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 612 def query_LiteralString(o); end |
#query_Object(o) ⇒ Object
Anything not explicitly allowed is flagged as error.
586 587 588 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 586 def query_Object(o) acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o) end |
#query_ParenthesizedExpression(o) ⇒ Object
602 603 604 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 602 def query_ParenthesizedExpression(o) query(o.expr) end |
#query_QualifiedName(o) ⇒ Object
608 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 608 def query_QualifiedName(o); end |
#query_VariableExpression(o) ⇒ Object
606 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 606 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
422 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 422 def relation_CollectExpression(o); end |
#relation_Object(o) ⇒ Object
418 419 420 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 418 def relation_Object(o) rvalue(o) end |
#relation_RelationshipExpression(o) ⇒ Object
424 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 424 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
623 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 623 def rvalue_CollectExpression(o) ; acceptor.accept(Issues::NOT_RVALUE, o) ; end |
#rvalue_Definition(o) ⇒ Object
625 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 625 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.
621 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 621 def rvalue_Expression(o); end |
#rvalue_NodeDefinition(o) ⇒ Object
627 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 627 def rvalue_NodeDefinition(o) ; acceptor.accept(Issues::NOT_RVALUE, o) ; end |
#rvalue_UnaryExpression(o) ⇒ Object
629 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 629 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
642 643 644 645 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 642 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
647 648 649 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 647 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.
659 660 661 662 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 659 def top_LambdaExpression(o, definition) # fail, stop scanning parents acceptor.accept(Issues::NOT_TOP_LEVEL, definition) end |
#top_NilClass(o, definition) ⇒ Object
—TOP CHECK
633 634 635 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 633 def top_NilClass(o, definition) # ok, reached the top, no more parents end |
#top_Object(o, definition) ⇒ Object
637 638 639 640 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 637 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
651 652 653 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 651 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
772 773 774 775 776 777 778 779 780 781 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 772 def varname_to_s(o) case o when Model::QualifiedName o.value when Model::QualifiedReference o.value else nil end end |