Class: PuppetLint::Data

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

Overview

Public: 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)

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


12
13
14
# File 'lib/puppet-lint/data.rb', line 12

def filename
  @filename
end

.fullpathObject (readonly)

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


12
13
14
# File 'lib/puppet-lint/data.rb', line 12

def fullpath
  @fullpath
end

.manifest_linesObject

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


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

def manifest_lines
  @manifest_lines
end

.pathObject

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


12
13
14
# File 'lib/puppet-lint/data.rb', line 12

def path
  @path
end

Class Method Details

.array_indexesObject

Internal: 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.

317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/puppet-lint/data.rb', line 317

def array_indexes
  @array_indexes ||= Proc.new do
    arrays = []
    tokens.each_with_index do |token, token_idx|
      if token.type == :LBRACK
        real_idx = 0
        tokens[token_idx+1..-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
    end
    arrays
  end.call
end

.class_indexesObject

Internal: 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.

174
175
176
# File 'lib/puppet-lint/data.rb', line 174

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

.defaults_indexesObject

Internal: 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.

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/puppet-lint/data.rb', line 390

def defaults_indexes
  @defaults_indexes ||= Proc.new do
    defaults = []
    tokens.each_with_index do |token, token_idx|
      if token.type == :CLASSREF && token.next_code_token && \
        token.next_code_token.type == :LBRACE
        real_idx = 0

        tokens[token_idx+1..-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
    end
    defaults
  end.call
end

.defined_type_indexesObject

Internal: 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.

188
189
190
# File 'lib/puppet-lint/data.rb', line 188

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

.definition_indexes(type) ⇒ Object

Internal: 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.

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/puppet-lint/data.rb', line 216

def definition_indexes(type)
  result = []
  tokens.each_with_index do |token, i|
    if token.type == type
      brace_depth = 0
      paren_depth = 0
      in_params = false
      inherited_class = nil
      tokens[i+1..-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 == 0
          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 == 0 && !in_params
            if 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
    end
  end
  result
end

.find_resource_param_tokens(resource_tokens) ⇒ Object

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

resource_tokens - An Array of Token objects that comprise the resource

definition.

Returns an Array of Token objects.


158
159
160
161
162
# File 'lib/puppet-lint/data.rb', line 158

def find_resource_param_tokens(resource_tokens)
  resource_tokens.select { |token|
    token.type == :NAME && token.next_code_token.type == :FARROW
  }
end

.find_resource_type_token(index) ⇒ Object

Internal: Find the Token representing the type of a resource definition.

index - The Integer pointing to the start of the resource in the `tokens`

array.

Returns a Token object.


147
148
149
# File 'lib/puppet-lint/data.rb', line 147

def find_resource_type_token(index)
  tokens[tokens[0..index].rindex { |token| token.type == :LBRACE }].prev_code_token
end

.formatting_tokensObject

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

Returns an Array of Symbols.


454
455
456
# File 'lib/puppet-lint/data.rb', line 454

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

.function_indexesObject

Internal: 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.

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/puppet-lint/data.rb', line 269

def function_indexes
  @function_indexes ||= Proc.new do
    functions = []
    tokens.each_with_index do |token, token_idx|
      if token.type == :NAME && \
        (token_idx == 0 || (token_idx == 1 && tokens[0].type == :WHITESPACE) || token.prev_token.type == :NEWLINE || token.prev_token.type == :INDENT || \
          # 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..-1].each_with_index do |cur_token, cur_token_idx|
            break if level == 0 && in_paren
            break if level == 0 && 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
    end
    functions
  end.call
end

.hash_indexesObject

Internal: 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.

352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/puppet-lint/data.rb', line 352

def hash_indexes
  @hash_indexes ||= Proc.new do
    hashes = []
    tokens.each_with_index do |token, token_idx|
      next unless token.prev_code_token
      next unless [:EQUALS, :ISEQUAL, :FARROW, :LPAREN].include? token.prev_code_token.type
      if token.type == :LBRACE
        level = 0
        real_idx = 0
        tokens[token_idx+1..-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 < 0
        end

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

.ignore_overridesObject

Internal: 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 a Hash of Sets of Integers.


463
464
465
# File 'lib/puppet-lint/data.rb', line 463

def ignore_overrides
  @ignore_overrides ||= {}
end

.node_indexesObject

Internal: 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.

202
203
204
# File 'lib/puppet-lint/data.rb', line 202

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

.param_tokens(these_tokens) ⇒ Object

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

these_tokens - An Array of PuppetLint::Lexer::Token objects that make up

the defined type or class definition.

Returns an Array of PuppetLint::Lexer::Token objects or nil if it takes no parameters.


422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
# File 'lib/puppet-lint/data.rb', line 422

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 == 0
        rparen_idx = i
        break
      end
    elsif token.type == :LBRACE && depth == 0
      # no parameters
      break
    end
  end

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

.parse_control_commentsObject

Internal: 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 nothing.


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
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
# File 'lib/puppet-lint/data.rb', line 472

def parse_control_comments
  @ignore_overrides.each_key { |check| @ignore_overrides[check].clear }
  control_re = /\A(lint:\S+)(\s+lint:\S+)*(.*)/

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

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

  stack = []
  control_comment_tokens.each do |token|
    comment_data = control_re.match(token.value.strip).to_a[1..-1].compact.map(&:strip)
    if comment_data.last =~ /\Alint:(ignore|endignore)/
      comment_data << ''
    end
    reason = comment_data.pop
    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
        else
          stack_add << [token.line, reason, check]
        end
      else
        stack.pop.each do |start|
          unless 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
end

.resource_indexesObject

Internal: 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 an Array of Hashes, each containing:

:start - An Integer position in the `tokens` Array pointing to the
         first Token of a resource declaration.
:end   - An Integer position in the `tokens` Array pointing to the last
         Token of a resource declaration.

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/puppet-lint/data.rb', line 106

def resource_indexes
  @resource_indexes ||= Proc.new do
    result = []
    tokens.each_index do |token_idx|
      if tokens[token_idx].type == :COLON
        next_token = tokens[token_idx].next_code_token
        depth = 1
        if next_token && next_token.type != :LBRACE
          tokens[(token_idx + 1)..-1].each_index do |idx|
            real_idx = token_idx + idx + 1
            if tokens[real_idx].type == :LBRACE
              depth += 1
            elsif {:SEMIC => true, :RBRACE => true}.include? tokens[real_idx].type
              unless tokens[real_idx].type == :SEMIC && depth > 1
                depth -= 1
                if depth == 0
                  result << {
                    :start        => token_idx + 1,
                    :end          => real_idx,
                    :tokens       => tokens[(token_idx + 1)..real_idx],
                    :type         => find_resource_type_token(token_idx),
                    :param_tokens => find_resource_param_tokens(tokens[(token_idx + 1)..real_idx]),
                  }
                  break
                end
              end
            end
          end
        end
      end
    end
    result
  end.call
end

.title_tokensObject

Internal: Retrieve a list of tokens that represent resource titles

Returns an Array of PuppetLint::Lexer::Token objects.


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/puppet-lint/data.rb', line 71

def title_tokens
  @title_tokens ||= Proc.new do
    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 { |r|
            r.type == :LBRACK
          }
          title_array_tokens = tokens[(array_start_idx + 1)..(token_idx - 2)]
          result += title_array_tokens.select { |token|
            {:STRING => true, :NAME => true}.include? token.type
          }
        else
          next_token = tokens[token_idx].next_code_token
          if next_token.type != :LBRACE
            result << tokens[token_idx - 1]
          end
        end
      end
    end
    result
  end.call
end

.tokensObject

Public: Get the tokenised manifest.

Returns an Array of PuppetLint::Lexer::Token objects.


37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/puppet-lint/data.rb', line 37

def tokens
  calling_method = begin
    caller[0][/`.*'/][1..-2]
  rescue NoMethodError
    caller[1][/`.*'/][1..-2]
  end

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

.tokens=(tokens) ⇒ Object

Internal: Store the tokenised manifest.

tokens - The Array of PuppetLint::Lexer::Token objects to store.

Returns nothing.


22
23
24
25
26
27
28
29
30
31
32
# File 'lib/puppet-lint/data.rb', line 22

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