Class: Puppet::Pops::Validation::Checker4_0

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

Constructor Details

#initialize(diagnostics_producer) ⇒ Checker4_0

Initializes the validator with a diagnostics producer. This object must respond to ‘:will_accept?` and `:accept`.



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/puppet/pops/validation/checker4_0.rb', line 20

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
end

Instance Attribute Details

#acceptorObject (readonly)



16
17
18
# File 'lib/puppet/pops/validation/checker4_0.rb', line 16

def acceptor
  @acceptor
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.



77
78
79
# File 'lib/puppet/pops/validation/checker4_0.rb', line 77

def assign(o, via_index = false)
  @@assignment_visitor.visit_this_1(self, o, via_index)
end

#assign_AccessExpression(o, via_index) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/puppet/pops/validation/checker4_0.rb', line 118

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



128
129
130
131
132
133
# File 'lib/puppet/pops/validation/checker4_0.rb', line 128

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



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/puppet/pops/validation/checker4_0.rb', line 102

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



44
45
46
# File 'lib/puppet/pops/validation/checker4_0.rb', line 44

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

#check_AccessExpression(o) ⇒ Object



144
145
146
147
148
149
150
# File 'lib/puppet/pops/validation/checker4_0.rb', line 144

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



152
153
154
155
156
157
158
159
160
161
162
# File 'lib/puppet/pops/validation/checker4_0.rb', line 152

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)



172
173
174
175
176
177
178
179
180
181
# File 'lib/puppet/pops/validation/checker4_0.rb', line 172

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



183
184
185
186
187
188
189
190
191
192
# File 'lib/puppet/pops/validation/checker4_0.rb', line 183

def check_AttributesOperation(o)
  # Append operator use is constrained
  parent = o.eContainer
  parent = parent.eContainer unless parent.nil?
  unless parent.is_a?(Model::ResourceExpression)
    acceptor.accept(Issues::UNSUPPORTED_OPERATOR_IN_CONTEXT, o, :operator=>'* =>')
  end

  rvalue(o.expr)
end

#check_BinaryExpression(o) ⇒ Object



194
195
196
197
# File 'lib/puppet/pops/validation/checker4_0.rb', line 194

def check_BinaryExpression(o)
  rvalue(o.left_expr)
  rvalue(o.right_expr)
end

#check_BlockExpression(o) ⇒ Object



199
200
201
202
203
204
205
206
# File 'lib/puppet/pops/validation/checker4_0.rb', line 199

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



208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/puppet/pops/validation/checker4_0.rb', line 208

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



233
234
235
236
237
# File 'lib/puppet/pops/validation/checker4_0.rb', line 233

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



239
240
241
# File 'lib/puppet/pops/validation/checker4_0.rb', line 239

def check_CaseOption(o)
  o.values.each { |v| rvalue(v) }
end

#check_CollectExpression(o) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/puppet/pops/validation/checker4_0.rb', line 243

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



221
222
223
224
225
# File 'lib/puppet/pops/validation/checker4_0.rb', line 221

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



140
141
142
# File 'lib/puppet/pops/validation/checker4_0.rb', line 140

def check_Factory(o)
  check(o.current)
end

#check_HostClassDefinition(o) ⇒ Object



303
304
305
306
307
# File 'lib/puppet/pops/validation/checker4_0.rb', line 303

def check_HostClassDefinition(o)
  check_NamedDefinition(o)
  internal_check_no_capture(o)
  internal_check_reserved_params(o)
end

#check_IfExpression(o) ⇒ Object



345
346
347
# File 'lib/puppet/pops/validation/checker4_0.rb', line 345

def check_IfExpression(o)
  rvalue(o.test)
end

#check_KeyedEntry(o) ⇒ Object



349
350
351
352
353
354
# File 'lib/puppet/pops/validation/checker4_0.rb', line 349

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



356
357
358
# File 'lib/puppet/pops/validation/checker4_0.rb', line 356

def check_LambdaExpression(o)
  internal_check_capture_last(o)
end

#check_LiteralList(o) ⇒ Object



360
361
362
# File 'lib/puppet/pops/validation/checker4_0.rb', line 360

def check_LiteralList(o)
  o.values.each {|v| rvalue(v) }
end

#check_MethodCallExpression(o) ⇒ Object



227
228
229
230
231
# File 'lib/puppet/pops/validation/checker4_0.rb', line 227

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).



258
259
260
261
262
263
# File 'lib/puppet/pops/validation/checker4_0.rb', line 258

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



288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/puppet/pops/validation/checker4_0.rb', line 288

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



364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/puppet/pops/validation/checker4_0.rb', line 364

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



137
138
# File 'lib/puppet/pops/validation/checker4_0.rb', line 137

def check_Object(o)
end

#check_Parameter(o) ⇒ Object



406
407
408
409
410
# File 'lib/puppet/pops/validation/checker4_0.rb', line 406

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.



382
383
# File 'lib/puppet/pops/validation/checker4_0.rb', line 382

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



387
388
389
390
391
392
# File 'lib/puppet/pops/validation/checker4_0.rb', line 387

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



394
395
396
# File 'lib/puppet/pops/validation/checker4_0.rb', line 394

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


421
422
423
424
# File 'lib/puppet/pops/validation/checker4_0.rb', line 421

def check_RelationshipExpression(o)
  relation(o.left_expr)
  relation(o.right_expr)
end

#check_ReservedWord(o) ⇒ Object



458
459
460
# File 'lib/puppet/pops/validation/checker4_0.rb', line 458

def check_ReservedWord(o)
  acceptor.accept(Issues::RESERVED_WORD, o, :word => o.word)
end

#check_ResourceBody(o) ⇒ Object



433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/puppet/pops/validation/checker4_0.rb', line 433

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



446
447
448
449
450
# File 'lib/puppet/pops/validation/checker4_0.rb', line 446

def check_ResourceDefaultsExpression(o)
  if o.form && o.form != :regular
    acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o)
  end
end

#check_ResourceExpression(o) ⇒ Object



426
427
428
429
430
431
# File 'lib/puppet/pops/validation/checker4_0.rb', line 426

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



452
453
454
455
456
# File 'lib/puppet/pops/validation/checker4_0.rb', line 452

def check_ResourceOverrideExpression(o)
  if o.form && o.form != :regular
    acceptor.accept(Issues::NOT_VIRTUALIZEABLE, o)
  end
end

#check_ResourceTypeDefinition(o) ⇒ Object



309
310
311
312
313
# File 'lib/puppet/pops/validation/checker4_0.rb', line 309

def check_ResourceTypeDefinition(o)
  check_NamedDefinition(o)
  internal_check_no_capture(o)
  internal_check_reserved_params(o)
end

#check_SelectorEntry(o) ⇒ Object



466
467
468
# File 'lib/puppet/pops/validation/checker4_0.rb', line 466

def check_SelectorEntry(o)
  rvalue(o.matching_expr)
end

#check_SelectorExpression(o) ⇒ Object



462
463
464
# File 'lib/puppet/pops/validation/checker4_0.rb', line 462

def check_SelectorExpression(o)
  rvalue(o.left_expr)
end

#check_UnaryExpression(o) ⇒ Object



470
471
472
# File 'lib/puppet/pops/validation/checker4_0.rb', line 470

def check_UnaryExpression(o)
  rvalue(o.expr)
end

#check_UnlessExpression(o) ⇒ Object



474
475
476
477
# File 'lib/puppet/pops/validation/checker4_0.rb', line 474

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



480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/puppet/pops/validation/checker4_0.rb', line 480

def check_VariableExpression(o)
  # The expression must be a qualified name
  if !o.expr.is_a?(Model::QualifiedName)
    acceptor.accept(Issues::ILLEGAL_EXPRESSION, o, :feature => 'name', :container => o)
  else
    # name must be either a decimal 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



91
92
93
94
95
96
97
98
# File 'lib/puppet/pops/validation/checker4_0.rb', line 91

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

Parameters:

  • single_feature_name (String, nil) (defaults to: nil)

    the name of a single valued hostname feature of the value’s container. e.g. ‘parent’



50
51
52
# File 'lib/puppet/pops/validation/checker4_0.rb', line 50

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



502
503
504
505
506
507
# File 'lib/puppet/pops/validation/checker4_0.rb', line 502

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



523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/puppet/pops/validation/checker4_0.rb', line 523

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



549
550
551
# File 'lib/puppet/pops/validation/checker4_0.rb', line 549

def hostname_LiteralDefault(o, semantic, single_feature_name)
  # always ok
end

#hostname_LiteralNumber(o, semantic, single_feature_name) ⇒ Object



545
546
547
# File 'lib/puppet/pops/validation/checker4_0.rb', line 545

def hostname_LiteralNumber(o, semantic, single_feature_name)
  # always ok
end

#hostname_LiteralRegularExpression(o, semantic, single_feature_name) ⇒ Object



553
554
555
# File 'lib/puppet/pops/validation/checker4_0.rb', line 553

def hostname_LiteralRegularExpression(o, semantic, single_feature_name)
  # always ok
end

#hostname_LiteralValue(o, semantic, single_feature_name) ⇒ Object



519
520
521
# File 'lib/puppet/pops/validation/checker4_0.rb', line 519

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



557
558
559
# File 'lib/puppet/pops/validation/checker4_0.rb', line 557

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



537
538
539
# File 'lib/puppet/pops/validation/checker4_0.rb', line 537

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



541
542
543
# File 'lib/puppet/pops/validation/checker4_0.rb', line 541

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



509
510
511
512
513
514
515
516
517
# File 'lib/puppet/pops/validation/checker4_0.rb', line 509

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.

Returns:

  • (Boolean)

    true if expression is known to have no effect on evaluation state



86
87
88
# File 'lib/puppet/pops/validation/checker4_0.rb', line 86

def idem(o)
  @@idem_visitor.visit_this_0(self, o)
end

#idem_AccessExpression(o) ⇒ Object



671
672
673
# File 'lib/puppet/pops/validation/checker4_0.rb', line 671

def idem_AccessExpression(o)
  true
end

#idem_AssignmentExpression(o) ⇒ Object



684
685
686
687
# File 'lib/puppet/pops/validation/checker4_0.rb', line 684

def idem_AssignmentExpression(o)
  # Always side effect
  false
end

#idem_BinaryExpression(o) ⇒ Object



675
676
677
# File 'lib/puppet/pops/validation/checker4_0.rb', line 675

def idem_BinaryExpression(o)
  true
end

#idem_BlockExpression(o) ⇒ Object



707
708
709
710
# File 'lib/puppet/pops/validation/checker4_0.rb', line 707

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



735
736
737
738
# File 'lib/puppet/pops/validation/checker4_0.rb', line 735

def idem_CaseExpression(o)
  return false if !idem(o.test)
  ! o.options.any? {|opt| !idem(opt) }
end

#idem_CaseOption(o) ⇒ Object

An option is idem if values and the then_expression are idem



741
742
743
744
# File 'lib/puppet/pops/validation/checker4_0.rb', line 741

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.



715
716
717
# File 'lib/puppet/pops/validation/checker4_0.rb', line 715

def idem_ConcatenatedString(o)
  true
end

#idem_Factory(o) ⇒ Object



667
668
669
# File 'lib/puppet/pops/validation/checker4_0.rb', line 667

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.



721
722
723
# File 'lib/puppet/pops/validation/checker4_0.rb', line 721

def idem_HeredocExpression(o)
  true
end

#idem_IfExpression(o) ⇒ Object



730
731
732
# File 'lib/puppet/pops/validation/checker4_0.rb', line 730

def idem_IfExpression(o)
  [o.test, o.then_expr, o.else_expr].all? {|e| idem(e) }
end

#idem_Literal(o) ⇒ Object



655
656
657
# File 'lib/puppet/pops/validation/checker4_0.rb', line 655

def idem_Literal(o)
  true
end

#idem_LiteralHash(o) ⇒ Object



663
664
665
# File 'lib/puppet/pops/validation/checker4_0.rb', line 663

def idem_LiteralHash(o)
  true
end

#idem_LiteralList(o) ⇒ Object



659
660
661
# File 'lib/puppet/pops/validation/checker4_0.rb', line 659

def idem_LiteralList(o)
  true
end

#idem_NilClass(o) ⇒ Object



651
652
653
# File 'lib/puppet/pops/validation/checker4_0.rb', line 651

def idem_NilClass(o)
  true
end

#idem_Nop(o) ⇒ Object



647
648
649
# File 'lib/puppet/pops/validation/checker4_0.rb', line 647

def idem_Nop(o)
  true
end

#idem_Object(o) ⇒ Object

–IDEM CHECK



643
644
645
# File 'lib/puppet/pops/validation/checker4_0.rb', line 643

def idem_Object(o)
  false
end

#idem_ParenthesizedExpression(o) ⇒ Object

Allow (no-effect parentheses) to be used around a productive expression



695
696
697
# File 'lib/puppet/pops/validation/checker4_0.rb', line 695

def idem_ParenthesizedExpression(o)
  idem(o.expr)
end

#idem_RelationshipExpression(o) ⇒ Object



679
680
681
682
# File 'lib/puppet/pops/validation/checker4_0.rb', line 679

def idem_RelationshipExpression(o)
  # Always side effect
  false
end

#idem_RenderExpression(o) ⇒ Object



699
700
701
# File 'lib/puppet/pops/validation/checker4_0.rb', line 699

def idem_RenderExpression(o)
  false
end

#idem_RenderStringExpression(o) ⇒ Object



703
704
705
# File 'lib/puppet/pops/validation/checker4_0.rb', line 703

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



726
727
728
# File 'lib/puppet/pops/validation/checker4_0.rb', line 726

def idem_SelectorExpression(o)
  true
end

#idem_UnaryExpression(o) ⇒ Object

Handles UnaryMinusExpression, NotExpression, VariableExpression



690
691
692
# File 'lib/puppet/pops/validation/checker4_0.rb', line 690

def idem_UnaryExpression(o)
  true
end

#internal_check_capture_last(o) ⇒ Object



315
316
317
318
319
320
321
322
# File 'lib/puppet/pops/validation/checker4_0.rb', line 315

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



324
325
326
327
328
329
330
# File 'lib/puppet/pops/validation/checker4_0.rb', line 324

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



337
338
339
340
341
342
343
# File 'lib/puppet/pops/validation/checker4_0.rb', line 337

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



55
56
57
# File 'lib/puppet/pops/validation/checker4_0.rb', line 55

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.



575
576
577
578
# File 'lib/puppet/pops/validation/checker4_0.rb', line 575

def query_BooleanExpression(o)
  query o.left_expr
  query o.right_expr
end

#query_ComparisonExpression(o) ⇒ Object

Puppet AST only allows == and !=



570
571
572
# File 'lib/puppet/pops/validation/checker4_0.rb', line 570

def query_ComparisonExpression(o)
  acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o) unless [:'==', :'!='].include? o.operator
end

#query_LiteralBoolean(o) ⇒ Object



592
# File 'lib/puppet/pops/validation/checker4_0.rb', line 592

def query_LiteralBoolean(o); end

#query_LiteralNumber(o) ⇒ Object



588
# File 'lib/puppet/pops/validation/checker4_0.rb', line 588

def query_LiteralNumber(o); end

#query_LiteralString(o) ⇒ Object



590
# File 'lib/puppet/pops/validation/checker4_0.rb', line 590

def query_LiteralString(o); end

#query_Object(o) ⇒ Object

Anything not explicitly allowed is flagged as error.



564
565
566
# File 'lib/puppet/pops/validation/checker4_0.rb', line 564

def query_Object(o)
  acceptor.accept(Issues::ILLEGAL_QUERY_EXPRESSION, o)
end

#query_ParenthesizedExpression(o) ⇒ Object



580
581
582
# File 'lib/puppet/pops/validation/checker4_0.rb', line 580

def query_ParenthesizedExpression(o)
  query(o.expr)
end

#query_QualifiedName(o) ⇒ Object



586
# File 'lib/puppet/pops/validation/checker4_0.rb', line 586

def query_QualifiedName(o); end

#query_VariableExpression(o) ⇒ Object



584
# File 'lib/puppet/pops/validation/checker4_0.rb', line 584

def query_VariableExpression(o); end

#relation(o) ⇒ Object

Performs check if this is valid as a relationship side



60
61
62
# File 'lib/puppet/pops/validation/checker4_0.rb', line 60

def relation(o)
  @@relation_visitor.visit_this_0(self, o)
end

#relation_CollectExpression(o) ⇒ Object



402
# File 'lib/puppet/pops/validation/checker4_0.rb', line 402

def relation_CollectExpression(o); end

#relation_Object(o) ⇒ Object



398
399
400
# File 'lib/puppet/pops/validation/checker4_0.rb', line 398

def relation_Object(o)
  rvalue(o)
end

#relation_RelationshipExpression(o) ⇒ Object



404
# File 'lib/puppet/pops/validation/checker4_0.rb', line 404

def relation_RelationshipExpression(o); end

#rvalue(o) ⇒ Object

Performs check if this is valid as a rvalue



65
66
67
# File 'lib/puppet/pops/validation/checker4_0.rb', line 65

def rvalue(o)
  @@rvalue_visitor.visit_this_0(self, o)
end

#rvalue_CollectExpression(o) ⇒ Object



601
# File 'lib/puppet/pops/validation/checker4_0.rb', line 601

def rvalue_CollectExpression(o)         ; acceptor.accept(Issues::NOT_RVALUE, o) ; end

#rvalue_Definition(o) ⇒ Object



603
# File 'lib/puppet/pops/validation/checker4_0.rb', line 603

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.



599
# File 'lib/puppet/pops/validation/checker4_0.rb', line 599

def rvalue_Expression(o); end

#rvalue_NodeDefinition(o) ⇒ Object



605
# File 'lib/puppet/pops/validation/checker4_0.rb', line 605

def rvalue_NodeDefinition(o)            ; acceptor.accept(Issues::NOT_RVALUE, o) ; end

#rvalue_UnaryExpression(o) ⇒ Object



607
# File 'lib/puppet/pops/validation/checker4_0.rb', line 607

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)



70
71
72
# File 'lib/puppet/pops/validation/checker4_0.rb', line 70

def top(o, definition)
  @@top_visitor.visit_this_1(self, o, definition)
end

#top_BlockExpression(o, definition) ⇒ Object



620
621
622
623
# File 'lib/puppet/pops/validation/checker4_0.rb', line 620

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



625
626
627
# File 'lib/puppet/pops/validation/checker4_0.rb', line 625

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.



637
638
639
640
# File 'lib/puppet/pops/validation/checker4_0.rb', line 637

def top_LambdaExpression(o, definition)
  # fail, stop scanning parents
  acceptor.accept(Issues::NOT_TOP_LEVEL, definition)
end

#top_NilClass(o, definition) ⇒ Object

—TOP CHECK



611
612
613
# File 'lib/puppet/pops/validation/checker4_0.rb', line 611

def top_NilClass(o, definition)
  # ok, reached the top, no more parents
end

#top_Object(o, definition) ⇒ Object



615
616
617
618
# File 'lib/puppet/pops/validation/checker4_0.rb', line 615

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



629
630
631
# File 'lib/puppet/pops/validation/checker4_0.rb', line 629

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.



37
38
39
40
41
# File 'lib/puppet/pops/validation/checker4_0.rb', line 37

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



750
751
752
753
754
755
756
757
758
759
# File 'lib/puppet/pops/validation/checker4_0.rb', line 750

def varname_to_s(o)
  case o
  when Model::QualifiedName
    o.value
  when Model::QualifiedReference
    o.value
  else
    nil
  end
end