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 . (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, }
- FUTURE_RESERVED_WORDS =
{ 'application' => true, 'produces' => true, 'consumes' => 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
327 328 329 330 331 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 327 def check_HostClassDefinition(o) check_NamedDefinition(o) internal_check_no_capture(o) internal_check_reserved_params(o) end |
#check_IfExpression(o) ⇒ Object
369 370 371 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 369 def check_IfExpression(o) rvalue(o.test) end |
#check_KeyedEntry(o) ⇒ Object
373 374 375 376 377 378 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 373 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
380 381 382 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 380 def check_LambdaExpression(o) internal_check_capture_last(o) end |
#check_LiteralFloat(o) ⇒ Object
388 389 390 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 388 def check_LiteralFloat(o) migration_checker.report_ambiguous_float(o) end |
#check_LiteralInteger(o) ⇒ Object
392 393 394 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 392 def check_LiteralInteger(o) migration_checker.report_ambiguous_integer(o) end |
#check_LiteralList(o) ⇒ Object
384 385 386 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 384 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
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 306 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 # This is perhaps not ideal but it's very difficult to pass a ReservedWord through # the mechanism that creates qualified names (namestack, namepop etc.) if FUTURE_RESERVED_WORDS[o.name] acceptor.accept(Issues::FUTURE_RESERVED_WORD, o, {:word => 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
396 397 398 399 400 401 402 403 404 405 406 407 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 396 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
438 439 440 441 442 443 444 445 446 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 438 def check_Parameter(o) if o.name =~ /^(?:0x)?[0-9]+$/ acceptor.accept(Issues::ILLEGAL_NUMERIC_PARAMETER, o, :name => o.name) end unless o.name =~ Puppet::Pops::Patterns::PARAM_NAME acceptor.accept(Issues::ILLEGAL_PARAM_NAME, 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.
414 415 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 414 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
419 420 421 422 423 424 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 419 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
426 427 428 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 426 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
457 458 459 460 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 457 def check_RelationshipExpression(o) relation(o.left_expr) relation(o.right_expr) end |
#check_ReservedWord(o) ⇒ Object
494 495 496 497 498 499 500 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 494 def check_ReservedWord(o) if o.future acceptor.accept(Issues::FUTURE_RESERVED_WORD, o, :word => o.word) else acceptor.accept(Issues::RESERVED_WORD, o, :word => o.word) end end |
#check_ResourceBody(o) ⇒ Object
469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 469 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
482 483 484 485 486 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 482 def check_ResourceDefaultsExpression(o) if o.form && o.form != :regular acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o) end end |
#check_ResourceExpression(o) ⇒ Object
462 463 464 465 466 467 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 462 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
488 489 490 491 492 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 488 def check_ResourceOverrideExpression(o) if o.form && o.form != :regular acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o) end end |
#check_ResourceTypeDefinition(o) ⇒ Object
333 334 335 336 337 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 333 def check_ResourceTypeDefinition(o) check_NamedDefinition(o) internal_check_no_capture(o) internal_check_reserved_params(o) end |
#check_SelectorEntry(o) ⇒ Object
506 507 508 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 506 def check_SelectorEntry(o) rvalue(o.matching_expr) end |
#check_SelectorExpression(o) ⇒ Object
502 503 504 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 502 def check_SelectorExpression(o) rvalue(o.left_expr) end |
#check_UnaryExpression(o) ⇒ Object
510 511 512 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 510 def check_UnaryExpression(o) rvalue(o.expr) end |
#check_UnlessExpression(o) ⇒ Object
514 515 516 517 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 514 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
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 520 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
544 545 546 547 548 549 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 544 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
565 566 567 568 569 570 571 572 573 574 575 576 577 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 565 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
591 592 593 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 591 def hostname_LiteralDefault(o, semantic, single_feature_name) # always ok end |
#hostname_LiteralNumber(o, semantic, single_feature_name) ⇒ Object
587 588 589 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 587 def hostname_LiteralNumber(o, semantic, single_feature_name) # always ok end |
#hostname_LiteralRegularExpression(o, semantic, single_feature_name) ⇒ Object
595 596 597 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 595 def hostname_LiteralRegularExpression(o, semantic, single_feature_name) # always ok end |
#hostname_LiteralValue(o, semantic, single_feature_name) ⇒ Object
561 562 563 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 561 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
599 600 601 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 599 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
579 580 581 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 579 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
583 584 585 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 583 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
551 552 553 554 555 556 557 558 559 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 551 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
713 714 715 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 713 def idem_AccessExpression(o) true end |
#idem_AssignmentExpression(o) ⇒ Object
726 727 728 729 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 726 def idem_AssignmentExpression(o) # Always side effect false end |
#idem_BinaryExpression(o) ⇒ Object
717 718 719 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 717 def idem_BinaryExpression(o) true end |
#idem_BlockExpression(o) ⇒ Object
749 750 751 752 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 749 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
777 778 779 780 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 777 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
783 784 785 786 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 783 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.
757 758 759 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 757 def idem_ConcatenatedString(o) true end |
#idem_Factory(o) ⇒ Object
709 710 711 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 709 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.
763 764 765 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 763 def idem_HeredocExpression(o) true end |
#idem_IfExpression(o) ⇒ Object
772 773 774 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 772 def idem_IfExpression(o) [o.test, o.then_expr, o.else_expr].all? {|e| idem(e) } end |
#idem_Literal(o) ⇒ Object
697 698 699 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 697 def idem_Literal(o) true end |
#idem_LiteralHash(o) ⇒ Object
705 706 707 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 705 def idem_LiteralHash(o) true end |
#idem_LiteralList(o) ⇒ Object
701 702 703 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 701 def idem_LiteralList(o) true end |
#idem_NilClass(o) ⇒ Object
693 694 695 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 693 def idem_NilClass(o) true end |
#idem_Nop(o) ⇒ Object
689 690 691 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 689 def idem_Nop(o) true end |
#idem_Object(o) ⇒ Object
–IDEM CHECK
685 686 687 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 685 def idem_Object(o) false end |
#idem_ParenthesizedExpression(o) ⇒ Object
Allow (no-effect parentheses) to be used around a productive expression
737 738 739 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 737 def idem_ParenthesizedExpression(o) idem(o.expr) end |
#idem_RelationshipExpression(o) ⇒ Object
721 722 723 724 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 721 def idem_RelationshipExpression(o) # Always side effect false end |
#idem_RenderExpression(o) ⇒ Object
741 742 743 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 741 def idem_RenderExpression(o) false end |
#idem_RenderStringExpression(o) ⇒ Object
745 746 747 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 745 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
768 769 770 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 768 def idem_SelectorExpression(o) true end |
#idem_UnaryExpression(o) ⇒ Object
Handles UnaryMinusExpression, NotExpression, VariableExpression
732 733 734 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 732 def idem_UnaryExpression(o) true end |
#internal_check_capture_last(o) ⇒ Object
339 340 341 342 343 344 345 346 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 339 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
348 349 350 351 352 353 354 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 348 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
361 362 363 364 365 366 367 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 361 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.
617 618 619 620 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 617 def query_BooleanExpression(o) query o.left_expr query o.right_expr end |
#query_ComparisonExpression(o) ⇒ Object
Puppet AST only allows == and !=
612 613 614 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 612 def query_ComparisonExpression(o) acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o) unless [:'==', :'!='].include? o.operator end |
#query_LiteralBoolean(o) ⇒ Object
634 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 634 def query_LiteralBoolean(o); end |
#query_LiteralNumber(o) ⇒ Object
630 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 630 def query_LiteralNumber(o); end |
#query_LiteralString(o) ⇒ Object
632 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 632 def query_LiteralString(o); end |
#query_Object(o) ⇒ Object
Anything not explicitly allowed is flagged as error.
606 607 608 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 606 def query_Object(o) acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o) end |
#query_ParenthesizedExpression(o) ⇒ Object
622 623 624 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 622 def query_ParenthesizedExpression(o) query(o.expr) end |
#query_QualifiedName(o) ⇒ Object
628 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 628 def query_QualifiedName(o); end |
#query_VariableExpression(o) ⇒ Object
626 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 626 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
434 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 434 def relation_CollectExpression(o); end |
#relation_Object(o) ⇒ Object
430 431 432 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 430 def relation_Object(o) rvalue(o) end |
#relation_RelationshipExpression(o) ⇒ Object
436 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 436 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
643 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 643 def rvalue_CollectExpression(o) ; acceptor.accept(Issues::NOT_RVALUE, o) ; end |
#rvalue_Definition(o) ⇒ Object
645 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 645 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.
641 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 641 def rvalue_Expression(o); end |
#rvalue_NodeDefinition(o) ⇒ Object
647 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 647 def rvalue_NodeDefinition(o) ; acceptor.accept(Issues::NOT_RVALUE, o) ; end |
#rvalue_UnaryExpression(o) ⇒ Object
649 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 649 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
662 663 664 665 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 662 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
667 668 669 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 667 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.
679 680 681 682 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 679 def top_LambdaExpression(o, definition) # fail, stop scanning parents acceptor.accept(Issues::NOT_TOP_LEVEL, definition) end |
#top_NilClass(o, definition) ⇒ Object
—TOP CHECK
653 654 655 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 653 def top_NilClass(o, definition) # ok, reached the top, no more parents end |
#top_Object(o, definition) ⇒ Object
657 658 659 660 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 657 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
671 672 673 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 671 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
792 793 794 795 796 797 798 799 800 801 |
# File 'lib/puppet/pops/validation/checker4_0.rb', line 792 def varname_to_s(o) case o when Model::QualifiedName o.value when Model::QualifiedReference o.value else nil end end |