class PuppetLint::Data
A singleton class storing all the information about the manifest being analysed.
@api public
Attributes
Get/Set the full expanded path to the manifest file being checked.
@api private
Get/Set the full expanded path to the manifest file being checked.
@api private
Get/Set the raw manifest data, split by n.
@api private
Get/Set the full expanded path to the manifest file being checked.
@api private
Public Class Methods
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
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
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
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
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
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
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 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 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
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
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
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
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
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
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
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
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
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
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
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
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
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