class Object

Public Instance Methods

check() click to toggle source
# File lib/puppet-lint/plugins/check_optional_default.rb, line 4
def check
  class_indexes.concat(defined_type_indexes).each do |idx|
    params = extract_params(idx)
    params.each do |param|
      default_value = extract_default_value_tokens(param)
      type = extract_type_tokens(param)

      if type.size.positive? &&                                  # The parameter has a type
         type[0].type == :TYPE && type[0].value == 'Optional' && # That type is Optional
         default_value.size.positive? &&                         # There is a default set
         (default_value.map(&:type) & %i[DOT LPAREN]).none? &&   # That default doesn't contain a call to a function
         default_value[0].type != :UNDEF &&                      # It isn't undef
         default_value[0].type != :VARIABLE                      # and it isn't a variable

        notify(
          :warning,
          message: 'Optional parameter defaults to something other than undef',
          line: param.line,
          column: param.column
        )
      end

      # If a defined type has an Optional parameter without a default, this is definately an issue as, unlike classes,
      # the default can't actually be coming from hiera.
      next unless idx[:type] == :DEFINE &&
                  type.size.positive? &&
                  type[0].type == :TYPE && type[0].value == 'Optional' &&
                  default_value.size.zero?

      notify(
        :warning,
        message: 'Optional defined type parameter doesn\'t have a default',
        line: param.line,
        column: param.column
      )
    end
  end
end
extract_default_value_tokens(ptok) click to toggle source

Returns array of tokens that cover the value that the parameter token has as its default Search forward to find value assigned to this parameter We want to find the thing after `=` and before `,`

# File lib/puppet-lint/plugins/check_optional_default.rb, line 77
def extract_default_value_tokens(ptok)
  value_tokens = []
  token = ptok.next_code_token
  nesting = 0
  while token
    case token.type
    when :LPAREN, :LBRACK
      nesting += 1
    when :RBRACK
      nesting -= 1
    when :RPAREN
      nesting -= 1
      if nesting.negative?
        # This is the RPAREN at the end of the parameters. There wasn't a COMMA
        last_token = token.prev_code_token
        break
      end
    when :EQUALS
      first_token = token.next_code_token
    when :COMMA
      unless nesting.positive?
        last_token = token.prev_code_token
        break
      end
    end
    token = token.next_token
  end
  value_tokens = tokens[tokens.find_index(first_token)..tokens.find_index(last_token)] if first_token && last_token
  value_tokens
end
extract_params(idx) click to toggle source

Returns an array of parameter tokens

# File lib/puppet-lint/plugins/check_optional_default.rb, line 46
def extract_params(idx)
  params = []
  return params if idx[:param_tokens].nil?

  e = idx[:param_tokens].each
  begin
    while (ptok = e.next)
      next unless ptok.type == :VARIABLE

      params << ptok
      nesting = 0
      # skip to the next parameter to avoid finding default values of variables
      loop do
        ptok = e.next
        case ptok.type
        when :LPAREN, :LBRACK
          nesting += 1
        when :RPAREN, :RBRACK
          nesting -= 1
        when :COMMA
          break unless nesting.positive?
        end
      end
    end
  rescue StopIteration; end # rubocop:disable Lint/SuppressedException
  params
end
extract_type_tokens(ptok) click to toggle source

Returns an array of tokens that cover the data type of the parameter ptok Search backwards until we either bump into a comma (whilst not nested), or reach the opening LPAREN

# File lib/puppet-lint/plugins/check_optional_default.rb, line 110
def extract_type_tokens(ptok)
  type_tokens = []
  token = ptok.prev_code_token
  nesting = 0
  while token
    case token.type
    when :LBRACK
      nesting += 1
    when :LPAREN
      nesting += 1
      if nesting.positive?
        # This is the LPAREN at the start of the parameter list
        first_token = token.next_code_token
        last_token = ptok.prev_code_token
        break
      end
    when :RBRACK, :RPAREN
      nesting -= 1
    when :COMMA
      if nesting.zero?
        first_token = token.next_code_token
        last_token = ptok.prev_code_token
        break
      end
    end

    token = token.prev_code_token
  end
  type_tokens = tokens[tokens.find_index(first_token)..tokens.find_index(last_token)] if first_token && last_token
  type_tokens
end