diff --git a/lib/puppet-lint/plugins/check_parameter_types.rb b/lib/puppet-lint/plugins/check_parameter_types.rb new file mode 100644 index 0000000..04b4bef --- /dev/null +++ b/lib/puppet-lint/plugins/check_parameter_types.rb @@ -0,0 +1,53 @@ +PuppetLint.new_check(:parameter_types) do + def check + (class_indexes + defined_type_indexes).each do |idx| + next if idx[:param_tokens].nil? + # https://github.com/puppetlabs/puppet-specifications/blob/master/language/catalog_expressions.md + # Each individual parameter in the parameter list must start with + # either a datatype or a variable name, so testing whether the parameter is typed + # is easy. + state = :ST_BEGIN + paren_stack = [] + data_stack = [] + idx[:param_tokens].each do |token| + next if [ :NEWLINE, :WHITESPACE, :INDENT, :COMMENT, :MLCOMMENT, :SLASH_COMMENT].include?(token.type) + + case state + when :ST_BEGIN + paren_stack = [] + data_stack = [] + if (token.type == :TYPE) or (token.value =~ /^[A-Z]/) + state = :ST_SKIP_TYPE + elsif token.type == :VARIABLE + notify :warning, { + :message => "missing datatype for parameter #{idx[:name_token].value}::#{token.value}", + :line => token.line, + :column => token.column + } + state = :ST_SKIP + end + # skip over the parameter default which can contain complex data types with variable references + # so a simple comma check isn't enough, brackets must be counted. + when :ST_SKIP + if token.type == :LPAREN + paren_stack.push(true) + elsif token.type == :RPAREN + paren_stack.pop + elsif token.type == :LBRACE || token.type == :LBRACK + data_stack.push(true) + elsif token.type == :RBRACE || token.type == :RBRACK + data_stack.pop + elsif token.type == :COMMA && data_stack.empty? && paren_stack.empty? + state = :ST_BEGIN + end + # Datatypes cannot have variables so when a variable is found it must be + # end of the data type + when :ST_SKIP_TYPE + if token.type == :VARIABLE + state = :ST_SKIP + end + end + end + end + end +end