class PuppetLint::Data

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

@api public

Attributes

filename[R]

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

@api private

fullpath[R]

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

@api private

manifest_lines[RW]

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

@api private

path[R]

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

@api private

Public Class Methods

array_indexes() click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 412
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_indexes() click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 262
def class_indexes
  @class_indexes ||= definition_indexes(:CLASS)
end
classref?(token) click to toggle source

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

@param [PuppetLint::Lexer::Token] token

@api private

# File lib/puppet-lint/data.rb, line 159
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_indexes() click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 489
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_indexes() click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 278
def defined_type_indexes
  @defined_type_indexes ||= definition_indexes(:DEFINE)
end
definition_indexes(type) click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 310
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:,
            name_token: token.next_code_token,
            inherited_token: inherited_class
          }
          break
        end
      end
    end
  end
  result
end
delete(token) click to toggle source

Remove a token

@param [PuppetLint::Lexer::Token] token

@api public

# File lib/puppet-lint/data.rb, line 96
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) click to toggle source

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

@param [Array] resource_tokens

An Array of Token objects that comprise the resource definition.

@return [Array]

@api private

# File lib/puppet-lint/data.rb, line 234
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) click to toggle source

Find the Token representing the type of a resource definition.

@param [Integer] index

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

@return [PuppetLint::Lexer::Token]

@api private

# File lib/puppet-lint/data.rb, line 215
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_tokens() click to toggle source

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

@return [Array]

@api private

# File lib/puppet-lint/data.rb, line 558
def formatting_tokens
  @formatting_tokens ||= PuppetLint::Lexer::FORMATTING_TOKENS
end
function_indexes() click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 362
def function_indexes
  @function_indexes ||= begin
    functions = []
    tokens.each_with_index do |token, token_idx|
      next unless token.type == :FUNCTION_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_indexes() click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 449
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_overrides() click to toggle source

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.

@return [Hash[Symbol, Set]]

@api private

# File lib/puppet-lint/data.rb, line 569
def ignore_overrides
  @ignore_overrides ||= {}
end
insert(index, token) click to toggle source

Add new token.

@param [Integer] index @param [PuppetLint::Lexer::Token] token

@api public

# File lib/puppet-lint/data.rb, line 57
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_indexes() click to toggle source

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.

@api private

# File lib/puppet-lint/data.rb, line 294
def node_indexes
  @node_indexes ||= definition_indexes(:NODE)
end
param_tokens(these_tokens) click to toggle source

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

@param [Array] these_tokens

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

@return [Array, nil] objects or nil if it takes

no parameters.

@api private

# File lib/puppet-lint/data.rb, line 524
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_comments() click to toggle source

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.

@return [nil]

@api private

# File lib/puppet-lint/data.rb, line 580
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
path=(val) click to toggle source

Store the path to the manifest file and populate fullpath and filename.

@param [String] val The path to the file

@return [nil]

@api private

# File lib/puppet-lint/data.rb, line 114
def path=(val)
  @path = val
  if val.nil?
    @fullpath = nil
    @filename = nil
  else
    @fullpath = File.expand_path(val, ENV.fetch('PWD', nil))
    @filename = File.basename(val)
  end
end
resource_indexes() click to toggle source

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.

@return [Array[Hash[Symbol, Integer]]] each hash contains :start and

:end pointing to the first and last {PuppetLint::Lexer::Token} of a
resource declaration

@api private

# File lib/puppet-lint/data.rb, line 176
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
title_tokens() click to toggle source

Retrieve a list of tokens that represent resource titles

@return [Array]

@api private

# File lib/puppet-lint/data.rb, line 130
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
tokens(duplicate: false) click to toggle source

Get the tokenised manifest.

@param duplicate [Boolean] if true, returns a duplicate of the token array. @return [Array]

@api public

# File lib/puppet-lint/data.rb, line 47
def tokens(duplicate: false)
  duplicate ? @tokens.dup : @tokens
end
tokens=(tokens) click to toggle source

Store the tokenised manifest.

@param [Array] tokens The Array of PuppetLint::Lexer::Token objects to store. @return [nil]

@api private

# 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