Class: PuppetLint::Data

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/puppet-lint/data.rb

Overview

A singleton class storing all the information about the manifest being analysed.

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.filenameObject (readonly)

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

Get/Set the full expanded path to the manifest file being checked.



15
16
17
# File 'lib/puppet-lint/data.rb', line 15

def filename
  @filename
end

.fullpathObject (readonly)

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

Get/Set the full expanded path to the manifest file being checked.



15
16
17
# File 'lib/puppet-lint/data.rb', line 15

def fullpath
  @fullpath
end

.manifest_linesObject

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

Get/Set the raw manifest data, split by n.



20
21
22
# File 'lib/puppet-lint/data.rb', line 20

def manifest_lines
  @manifest_lines
end

.pathObject

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

Get/Set the full expanded path to the manifest file being checked.



15
16
17
# File 'lib/puppet-lint/data.rb', line 15

def path
  @path
end

Class Method Details

.array_indexesObject

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

Calculate the positions of all array values within ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of an array value
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of an array value
:tokens - An Array consisting of all the Token objects that make up the
          array value.


435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/puppet-lint/data.rb', line 435

def array_indexes
  @array_indexes ||= begin
    arrays = []
    tokens.each_with_index do |token, token_idx|
      next unless token.type == :LBRACK

      real_idx = 0
      tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx|
        real_idx = token_idx + 1 + cur_token_idx
        break if cur_token.type == :RBRACK
      end

      # Ignore resource references
      next if token.prev_code_token &&
              token.prev_code_token.type == :CLASSREF

      arrays << {
        start: token_idx,
        end: real_idx,
        tokens: tokens[token_idx..real_idx]
      }
    end
    arrays
  end
end

.class_indexesObject

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

Calculate the positions of all class definitions within the ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of a class definition.
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of a class definition.
:tokens - An Array consisting of all the Token objects that make up the
          class definition.


285
286
287
# File 'lib/puppet-lint/data.rb', line 285

def class_indexes
  @class_indexes ||= definition_indexes(:CLASS)
end

.classref?(token) ⇒ Boolean

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

Determine if the given token contains a CLASSREF in the token chain..

Parameters:

Returns:

  • (Boolean)


182
183
184
185
186
187
188
# File 'lib/puppet-lint/data.rb', line 182

def classref?(token)
  current_token = token
  while (current_token = current_token.prev_code_token)
    return true if current_token.type == :CLASSREF
    return false if current_token.type == :NAME
  end
end

.defaults_indexesObject

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

Calculate the positions of all defaults declarations within ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of the defaults declaration
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of the defaults declaration
:tokens - An Array consisting of all the Token objects that make up the
          defaults declaration.


512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
# File 'lib/puppet-lint/data.rb', line 512

def defaults_indexes
  @defaults_indexes ||= begin
    defaults = []
    tokens.each_with_index do |token, token_idx|
      next unless token.type == :CLASSREF
      next unless token.next_code_token && token.next_code_token.type == :LBRACE

      real_idx = 0

      tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx|
        real_idx = token_idx + 1 + cur_token_idx
        break if cur_token.type == :RBRACE
      end

      defaults << {
        start: token_idx,
        end: real_idx,
        tokens: tokens[token_idx..real_idx]
      }
    end
    defaults
  end
end

.defined_type_indexesObject

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

Calculate the positions of all defined type definitions within the ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of a defined type definition.
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of a defined type definition.
:tokens - An Array consisting of all the Token objects that make up the
          defined type.


301
302
303
# File 'lib/puppet-lint/data.rb', line 301

def defined_type_indexes
  @defined_type_indexes ||= definition_indexes(:DEFINE)
end

.definition_indexes(type) ⇒ Object

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

Calculate the positions of all the specified defintion types within the ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of a definition.
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of a definition.
:tokens - An Array consisting of all the Token objects that make up the
          definition.


333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/puppet-lint/data.rb', line 333

def definition_indexes(type)
  result = []
  tokens.each_with_index do |token, i|
    next unless token.type == type

    brace_depth = 0
    paren_depth = 0
    in_params = false
    inherited_class = nil
    tokens[i + 1..].each_with_index do |definition_token, j|
      case definition_token.type
      when :INHERITS
        inherited_class = definition_token.next_code_token
      when :LPAREN
        in_params = true if paren_depth.zero?
        paren_depth += 1
      when :RPAREN
        in_params = false if paren_depth == 1
        paren_depth -= 1
      when :LBRACE
        brace_depth += 1
      when :RBRACE
        brace_depth -= 1
        if brace_depth.zero? && !in_params && (token.next_code_token.type != :LBRACE)
          result << {
            start: i,
            end: i + j + 1,
            tokens: tokens[i..(i + j + 1)],
            param_tokens: param_tokens(tokens[i..(i + j + 1)]),
            type: type,
            name_token: token.next_code_token,
            inherited_token: inherited_class
          }
          break
        end
      end
    end
  end
  result
end

.delete(token) ⇒ Object

Remove a token

Parameters:



119
120
121
122
123
124
125
126
127
128
# File 'lib/puppet-lint/data.rb', line 119

def delete(token)
  token.next_token.prev_token = token.prev_token unless token.next_token.nil?
  token.prev_token.next_token = token.next_token unless token.prev_token.nil?
  unless formatting_tokens.include?(token.type)
    token.prev_code_token.next_code_token = token.next_code_token unless token.prev_code_token.nil?
    token.next_code_token.prev_code_token = token.prev_code_token unless token.next_code_token.nil?
  end

  tokens.delete(token)
end

.find_resource_param_tokens(resource_tokens) ⇒ Array[PuppetLint::Lexer::Token]

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

Find all the Token objects representing the parameter names in a resource definition.

Parameters:

  • resource_tokens (Array[PuppetLint::Lexer::Token])

    An Array of Token objects that comprise the resource definition.

Returns:



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/puppet-lint/data.rb', line 257

def find_resource_param_tokens(resource_tokens)
  param_tokens = []

  iter_token = resource_tokens.first.prev_token

  until iter_token.nil?
    iter_token = iter_token.next_token_of(:NAME)

    break unless resource_tokens.include?(iter_token)

    param_tokens << iter_token if iter_token && iter_token.next_code_token.type == :FARROW
  end

  param_tokens
end

.find_resource_type_token(index) ⇒ PuppetLint::Lexer::Token

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

Find the Token representing the type of a resource definition.

Parameters:

  • index (Integer)

    The Integer pointing to the start of the resource in the ‘tokens` array.

Returns:

Raises:



238
239
240
241
242
243
244
245
246
# File 'lib/puppet-lint/data.rb', line 238

def find_resource_type_token(index)
  lbrace_idx = tokens[0..index].rindex do |token|
    token.type == :LBRACE && token.prev_code_token.type != :QMARK
  end

  raise PuppetLint::SyntaxError, tokens[index] if lbrace_idx.nil?

  tokens[lbrace_idx].prev_code_token
end

.formatting_tokensArray[Symbol]

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

Retrieves a list of token types that are considered to be formatting tokens (whitespace, newlines, etc).

Returns:

  • (Array[Symbol])


581
582
583
# File 'lib/puppet-lint/data.rb', line 581

def formatting_tokens
  @formatting_tokens ||= PuppetLint::Lexer::FORMATTING_TOKENS
end

.function_indexesObject

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

Calculate the positions of all function calls within ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of a function call
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of a function call
:tokens - An Array consisting of all the Token objects that make up the
          function call.


385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'lib/puppet-lint/data.rb', line 385

def function_indexes
  @function_indexes ||= begin
    functions = []
    tokens.each_with_index do |token, token_idx|
      next unless token.type == :NAME
      next unless token_idx.zero? ||
                  (token_idx == 1 && tokens[0].type == :WHITESPACE) ||
                  [:NEWLINE, :INDENT].include?(token.prev_token.type) ||
                  # function in a function
                  (token.prev_code_token && token.prev_code_token.type == :LPAREN)

      # Hash key
      next if token.next_code_token && token.next_code_token.type == :FARROW

      level = 0
      real_idx = 0
      in_paren = false
      tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx|
        break if level.zero? && in_paren
        break if level.zero? && cur_token.type == :NEWLINE

        if cur_token.type == :LPAREN
          level += 1
          in_paren = true
        end
        level -= 1 if cur_token.type == :RPAREN
        real_idx = token_idx + 1 + cur_token_idx
      end

      functions << {
        start: token_idx,
        end: real_idx,
        tokens: tokens[token_idx..real_idx]
      }
    end
    functions
  end
end

.hash_indexesObject

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

Calculate the positions of all hash values within ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of an hash value
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of an hash value
:tokens - An Array consisting of all the Token objects that make up the
          hash value.


472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
# File 'lib/puppet-lint/data.rb', line 472

def hash_indexes
  @hash_indexes ||= begin
    hashes = []
    tokens.each_with_index do |token, token_idx|
      next unless token.type == :LBRACE
      next unless token.prev_code_token
      next unless [:EQUALS, :ISEQUAL, :FARROW, :LPAREN].include?(token.prev_code_token.type)

      level = 0
      real_idx = 0
      tokens[token_idx + 1..].each_with_index do |cur_token, cur_token_idx|
        real_idx = token_idx + 1 + cur_token_idx

        level += 1 if cur_token.type == :LBRACE
        level -= 1 if cur_token.type == :RBRACE
        break if level.negative?
      end

      hashes << {
        start: token_idx,
        end: real_idx,
        tokens: tokens[token_idx..real_idx]
      }
    end
    hashes
  end
end

.ignore_overridesHash[Symbol, Set[Integer]]

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

Retrieves a Hash of Sets. Each key is a check name Symbol and the Set of Integers returned lists all the lines that the check results should be ignored on.

Returns:

  • (Hash[Symbol, Set[Integer]])


592
593
594
# File 'lib/puppet-lint/data.rb', line 592

def ignore_overrides
  @ignore_overrides ||= {}
end

.insert(index, token) ⇒ Object

Add new token.

Parameters:



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/puppet-lint/data.rb', line 80

def insert(index, token)
  current_token = tokens[index - 1]
  token.next_token = current_token.next_token
  token.prev_token = current_token

  current_token.next_token.prev_token = token unless current_token.next_token.nil?

  unless formatting_tokens.include?(token.type)
    current_token.next_token.prev_code_token = token unless current_token.next_token.nil?
    next_nf_idx = tokens[index..].index { |r| !formatting_tokens.include?(r.type) }
    unless next_nf_idx.nil?
      next_nf_token = tokens[index + next_nf_idx]
      token.next_code_token = next_nf_token
      next_nf_token.prev_code_token = token
    end
  end

  if formatting_tokens.include?(current_token.type)
    prev_nf_idx = tokens[0..index - 1].rindex { |r| !formatting_tokens.include?(r.type) }
    unless prev_nf_idx.nil?
      prev_nf_token = tokens[prev_nf_idx]
      token.prev_code_token = prev_nf_token
      prev_nf_token.next_code_token = token
    end
  else
    token.prev_code_token = current_token
  end

  current_token.next_token = token
  current_token.next_code_token = token unless formatting_tokens.include?(token.type)

  tokens.insert(index, token)
end

.node_indexesObject

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

Calculate the positions of all node definitions within the ‘tokens` Array.

Returns an Array of Hashes, each containing:

:start  - An Integer position in the `tokens` Array pointing to the
          first Token of a defined type definition.
:end    - An Integer position in the `tokens` Array pointing to the last
          Token of a defined type definition.
:tokens - An Array consisting of all the Token objects that make up the
          defined type.


317
318
319
# File 'lib/puppet-lint/data.rb', line 317

def node_indexes
  @node_indexes ||= definition_indexes(:NODE)
end

.param_tokens(these_tokens) ⇒ Array[PuppetLint::Lexer::Token]?

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

Finds all the tokens that make up the defined type or class definition parameters.

Parameters:

  • these_tokens (Array[PuppetLint::Lexer::Token])

    An Array of PuppetLint::Lexer::Token objects that make up the defined type or class definition.

Returns:



547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
# File 'lib/puppet-lint/data.rb', line 547

def param_tokens(these_tokens)
  depth = 0
  lparen_idx = nil
  rparen_idx = nil

  these_tokens.each_with_index do |token, i|
    if token.type == :LPAREN
      depth += 1
      lparen_idx = i if depth == 1
    elsif token.type == :RPAREN
      depth -= 1
      if depth.zero?
        rparen_idx = i
        break
      end
    elsif token.type == :LBRACE && depth.zero?
      # no parameters
      break
    end
  end

  if lparen_idx.nil? || rparen_idx.nil?
    nil
  else
    these_tokens[(lparen_idx + 1)..(rparen_idx - 1)]
  end
end

.parse_control_commentsnil

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

Parses all COMMENT, MLCOMMENT and SLASH_COMMENT tokens looking for control comments (comments that enable or disable checks). Builds the contents of the ‘ignore_overrides` hash.

Returns:

  • (nil)


603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
# File 'lib/puppet-lint/data.rb', line 603

def parse_control_comments
  @ignore_overrides.each_key { |check| @ignore_overrides[check].clear }

  comment_token_types = Set[:COMMENT, :MLCOMMENT, :SLASH_COMMENT]

  comment_tokens = tokens.select do |token|
    comment_token_types.include?(token.type)
  end
  control_comment_tokens = comment_tokens.select do |token|
    token.value.strip =~ %r{\Alint:(ignore:[\w\d]+|endignore)}
  end

  stack = []
  control_comment_tokens.each do |token|
    comment_data = []
    reason = []

    comment_words = token.value.strip.split(%r{\s+})
    comment_words.each_with_index do |word, i|
      if %r{\Alint:(ignore|endignore)}.match?(word)
        comment_data << word
      else
        # Once we reach the first non-controlcomment word, assume the rest
        # of the words are the reason.
        reason = comment_words[i..]
        break
      end
    end

    stack_add = []

    comment_data.each do |control|
      split_control = control.split(':')
      command = split_control[1]

      if command == 'ignore'
        check = split_control[2].to_sym
        if token.prev_token && !Set[:NEWLINE, :INDENT].include?(token.prev_token.type)
          # control comment at the end of the line, override applies to
          # a single line only
          (ignore_overrides[check] ||= {})[token.line] = reason.join(' ')
        else
          stack_add << [token.line, reason.join(' '), check]
        end
      else
        top_override = stack.pop
        if top_override.nil?
          # TODO: refactor to provide a way to expose problems from
          # PuppetLint::Data via the normal problem reporting mechanism.
          warn "WARNING: lint:endignore comment with no opening lint:ignore:<check> comment found on line #{token.line}"
        else
          top_override.each do |start|
            next if start.nil?

            (start[0]..token.line).each do |i|
              (ignore_overrides[start[2]] ||= {})[i] = start[1]
            end
          end
        end
      end
    end
    stack << stack_add unless stack_add.empty?
  end

  stack.each do |control|
    warn "WARNING: lint:ignore:#{control[0][2]} comment on line #{control[0][0]} with no closing lint:endignore comment"
  end
end

.resource_indexesArray[Hash[Symbol, Integer]]

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

Calculate the positions of all resource declarations within the tokenised manifest. These positions only point to the content of the resource declarations, they do not include resource types or titles.

Returns:

  • (Array[Hash[Symbol, Integer]])

    each hash contains :start and :end pointing to the first and last Lexer::Token of a resource declaration



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/puppet-lint/data.rb', line 199

def resource_indexes
  @resource_indexes ||= begin
    marker = 0
    result = []
    tokens.select { |t| t.type == :COLON }.each do |colon_token|
      next unless colon_token.next_code_token && colon_token.next_code_token.type != :LBRACE
      next if classref?(colon_token)

      rel_start_idx = tokens[marker..].index(colon_token)
      break if rel_start_idx.nil?

      start_idx = rel_start_idx + marker
      end_token = colon_token.next_token_of([:SEMIC, :RBRACE])
      rel_end_idx = tokens[start_idx..].index(end_token)
      raise PuppetLint::SyntaxError, colon_token if rel_end_idx.nil?

      marker = rel_end_idx + start_idx

      result << {
        start: start_idx + 1,
        end: marker,
        tokens: tokens[start_idx..marker],
        type: find_resource_type_token(start_idx),
        param_tokens: find_resource_param_tokens(tokens[start_idx..marker])
      }
    end
    result
  end
end

.ruby1?Boolean

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

Returns:

  • (Boolean)


42
43
44
45
# File 'lib/puppet-lint/data.rb', line 42

def ruby1?
  @ruby1 = RbConfig::CONFIG['MAJOR'] == '1' if @ruby1.nil?
  @ruby1
end

.title_tokensArray[PuppetLint::Lexer::Token]

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

Retrieve a list of tokens that represent resource titles

Returns:



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/puppet-lint/data.rb', line 153

def title_tokens
  @title_tokens ||= begin
    result = []
    tokens.each_index do |token_idx|
      if tokens[token_idx].type == :COLON
        # gather a list of tokens that are resource titles
        if tokens[token_idx - 1].type == :RBRACK
          array_start_idx = tokens.rindex do |r|
            r.type == :LBRACK
          end
          title_array_tokens = tokens[(array_start_idx + 1)..(token_idx - 2)]
          result += title_array_tokens.select do |token|
            { STRING: true, NAME: true }.include?(token.type)
          end
        else
          next_token = tokens[token_idx].next_code_token
          result << tokens[token_idx - 1] unless next_token.type == :LBRACE
        end
      end
    end
    result
  end
end

.tokensArray[PuppetLint::Lexer::Token]

Get the tokenised manifest.

Returns:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/puppet-lint/data.rb', line 52

def tokens
  calling_method = if ruby1?
                     begin
                       caller[0][%r{`.*'}][1..-2] # rubocop:disable Performance/Caller
                     rescue NoMethodError
                       caller[1][%r{`.*'}][1..-2] # rubocop:disable Performance/Caller
                     end
                   else
                     begin
                       caller(0..0).first[%r{`.*'}][1..-2]
                     rescue NoMethodError
                       caller(1..1).first[%r{`.*'}][1..-2]
                     end
                   end

  if calling_method == 'check'
    @tokens.dup
  else
    @tokens
  end
end

.tokens=(tokens) ⇒ nil

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

Store the tokenised manifest.

Parameters:

Returns:

  • (nil)


28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/puppet-lint/data.rb', line 28

def tokens=(tokens)
  @tokens = tokens
  @title_tokens = nil
  @resource_indexes = nil
  @class_indexes = nil
  @defined_type_indexes = nil
  @node_indexes = nil
  @function_indexes = nil
  @array_indexes = nil
  @hash_indexes = nil
  @defaults_indexes = nil
end