puppet-lint 2.2.1 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -19
- data/README.md +181 -174
- data/Rakefile +1 -1
- data/lib/puppet-lint/bin.rb +6 -0
- data/lib/puppet-lint/lexer.rb +1 -1
- data/lib/puppet-lint/plugins.rb +16 -10
- data/lib/puppet-lint/plugins/check_classes/arrow_on_right_operand_line.rb +46 -0
- data/lib/puppet-lint/plugins/check_classes/autoloader_layout.rb +33 -0
- data/lib/puppet-lint/plugins/check_classes/class_inherits_from_params_class.rb +20 -0
- data/lib/puppet-lint/plugins/check_classes/code_on_top_scope.rb +20 -0
- data/lib/puppet-lint/plugins/check_classes/inherits_across_namespaces.rb +22 -0
- data/lib/puppet-lint/plugins/check_classes/names_containing_dash.rb +23 -0
- data/lib/puppet-lint/plugins/check_classes/names_containing_uppercase.rb +28 -0
- data/lib/puppet-lint/plugins/check_classes/nested_classes_or_defines.rb +28 -0
- data/lib/puppet-lint/plugins/check_classes/parameter_order.rb +44 -0
- data/lib/puppet-lint/plugins/check_classes/right_to_left_relationship.rb +15 -0
- data/lib/puppet-lint/plugins/check_classes/variable_scope.rb +143 -0
- data/lib/puppet-lint/plugins/check_comments/slash_comments.rb +22 -0
- data/lib/puppet-lint/plugins/{check_comments.rb → check_comments/star_comments.rb} +1 -24
- data/lib/puppet-lint/plugins/{check_conditionals.rb → check_conditionals/case_without_default.rb} +1 -27
- data/lib/puppet-lint/plugins/check_conditionals/selector_inside_resource.rb +25 -0
- data/lib/puppet-lint/plugins/{check_documentation.rb → check_documentation/documentation.rb} +0 -0
- data/lib/puppet-lint/plugins/{check_nodes.rb → check_nodes/unquoted_node_name.rb} +0 -0
- data/lib/puppet-lint/plugins/check_resources/duplicate_params.rb +37 -0
- data/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb +70 -0
- data/lib/puppet-lint/plugins/check_resources/ensure_not_symlink_target.rb +44 -0
- data/lib/puppet-lint/plugins/check_resources/file_mode.rb +42 -0
- data/lib/puppet-lint/plugins/check_resources/unquoted_file_mode.rb +31 -0
- data/lib/puppet-lint/plugins/check_resources/unquoted_resource_title.rb +22 -0
- data/lib/puppet-lint/plugins/check_strings/double_quoted_strings.rb +27 -0
- data/lib/puppet-lint/plugins/check_strings/only_variable_string.rb +63 -0
- data/lib/puppet-lint/plugins/check_strings/puppet_url_without_modules.rb +25 -0
- data/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb +26 -0
- data/lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb +17 -0
- data/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb +23 -0
- data/lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb +21 -0
- data/lib/puppet-lint/plugins/{check_variables.rb → check_variables/variable_is_lowercase.rb} +0 -22
- data/lib/puppet-lint/plugins/check_whitespace/140chars.rb +21 -0
- data/lib/puppet-lint/plugins/check_whitespace/2sp_soft_tabs.rb +19 -0
- data/lib/puppet-lint/plugins/check_whitespace/80chars.rb +21 -0
- data/lib/puppet-lint/plugins/{check_whitespace.rb → check_whitespace/arrow_alignment.rb} +0 -118
- data/lib/puppet-lint/plugins/check_whitespace/hard_tabs.rb +24 -0
- data/lib/puppet-lint/plugins/check_whitespace/trailing_whitespace.rb +28 -0
- data/lib/puppet-lint/tasks/puppet-lint.rb +4 -0
- data/lib/puppet-lint/version.rb +1 -1
- data/spec/puppet-lint/bin_spec.rb +18 -1
- data/spec/puppet-lint/lexer_spec.rb +19 -0
- metadata +41 -68
- data/lib/puppet-lint/plugins/check_classes.rb +0 -433
- data/lib/puppet-lint/plugins/check_resources.rb +0 -251
- data/lib/puppet-lint/plugins/check_strings.rb +0 -186
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ begin
|
|
11
11
|
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
12
12
|
version = PuppetLint::VERSION
|
13
13
|
config.future_release = "#{version}"
|
14
|
-
config.exclude_labels = %w{duplicate question invalid wontfix}
|
14
|
+
config.exclude_labels = %w{duplicate question invalid wontfix release-pr}
|
15
15
|
end
|
16
16
|
rescue LoadError
|
17
17
|
end
|
data/lib/puppet-lint/bin.rb
CHANGED
@@ -53,11 +53,15 @@ class PuppetLint::Bin
|
|
53
53
|
end
|
54
54
|
|
55
55
|
return_val = 0
|
56
|
+
|
57
|
+
puts '[' if PuppetLint.configuration.json
|
56
58
|
path.each do |f|
|
57
59
|
l = PuppetLint.new
|
58
60
|
l.file = f
|
59
61
|
l.run
|
60
62
|
l.print_problems
|
63
|
+
puts ',' if f != path.last and PuppetLint.configuration.json
|
64
|
+
|
61
65
|
if l.errors? or (l.warnings? and PuppetLint.configuration.fail_on_warnings)
|
62
66
|
return_val = 1
|
63
67
|
end
|
@@ -68,6 +72,8 @@ class PuppetLint::Bin
|
|
68
72
|
end
|
69
73
|
end
|
70
74
|
end
|
75
|
+
puts ']' if PuppetLint.configuration.json
|
76
|
+
|
71
77
|
return return_val
|
72
78
|
|
73
79
|
rescue PuppetLint::NoCodeError
|
data/lib/puppet-lint/lexer.rb
CHANGED
@@ -416,7 +416,7 @@ class PuppetLint
|
|
416
416
|
line += value.scan(/(\r\n|\r|\n)/).size
|
417
417
|
token_column = column + (ss.pos - value.size)
|
418
418
|
tokens << new_token(:DQPOST, value, :line => line, :column => token_column)
|
419
|
-
@column =
|
419
|
+
@column = column + ss.pos + 1
|
420
420
|
@line_no = line
|
421
421
|
end
|
422
422
|
else
|
data/lib/puppet-lint/plugins.rb
CHANGED
@@ -40,12 +40,24 @@ class PuppetLint
|
|
40
40
|
# Returns an Array of Gem::Specification objects.
|
41
41
|
def self.gemspecs
|
42
42
|
@gemspecs ||= if Gem::Specification.respond_to?(:latest_specs)
|
43
|
-
Gem::Specification.latest_specs
|
43
|
+
Gem::Specification.latest_specs(load_prerelease_plugins?)
|
44
44
|
else
|
45
45
|
Gem.searcher.init_gemspecs
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
# Internal: Determine whether to load plugins that contain a letter in their version number.
|
50
|
+
#
|
51
|
+
# Returns true if the configuration is set to load "prerelease" gems, false otherwise.
|
52
|
+
def self.load_prerelease_plugins?
|
53
|
+
# Load prerelease plugins (which ruby defines as any gem which has a letter in its version number).
|
54
|
+
# Can't use puppet-lint configuration object here because this code executes before the command line is parsed.
|
55
|
+
if ENV['PUPPET_LINT_LOAD_PRERELEASE_PLUGINS']
|
56
|
+
return %w(true yes).include?(ENV['PUPPET_LINT_LOAD_PRERELEASE_PLUGINS'].downcase)
|
57
|
+
end
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
49
61
|
# Internal: Retrieve a list of available gem paths from RubyGems.
|
50
62
|
#
|
51
63
|
# Returns an Array of Pathname objects.
|
@@ -61,14 +73,8 @@ class PuppetLint
|
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
64
|
-
|
65
|
-
require
|
66
|
-
|
67
|
-
require 'puppet-lint/plugins/check_documentation'
|
68
|
-
require 'puppet-lint/plugins/check_strings'
|
69
|
-
require 'puppet-lint/plugins/check_variables'
|
70
|
-
require 'puppet-lint/plugins/check_whitespace'
|
71
|
-
require 'puppet-lint/plugins/check_resources'
|
72
|
-
require 'puppet-lint/plugins/check_nodes'
|
76
|
+
Dir[File.expand_path('plugins/**/*.rb', File.dirname(__FILE__))].each do |file|
|
77
|
+
require file
|
78
|
+
end
|
73
79
|
|
74
80
|
PuppetLint::Plugins.load_from_gems
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Public: Test the manifest tokens for chaining arrow that is
|
2
|
+
# on the line of the left operand when the right operand is on another line.
|
3
|
+
#
|
4
|
+
# https://docs.puppet.com/guides/style_guide.html#chaining-arrow-syntax
|
5
|
+
PuppetLint.new_check(:arrow_on_right_operand_line) do
|
6
|
+
def check
|
7
|
+
tokens.select { |r| Set[:IN_EDGE, :IN_EDGE_SUB].include?(r.type) }.each do |token|
|
8
|
+
if token.next_code_token.line != token.line
|
9
|
+
notify :warning, {
|
10
|
+
:message => 'arrow should be on the right operand\'s line',
|
11
|
+
:line => token.line,
|
12
|
+
:column => token.column,
|
13
|
+
:token => token,
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def fix(problem)
|
20
|
+
token = problem[:token]
|
21
|
+
tokens.delete(token)
|
22
|
+
|
23
|
+
# remove any excessive whitespace on the line
|
24
|
+
temp_token = token.prev_code_token
|
25
|
+
while (temp_token = temp_token.next_token)
|
26
|
+
tokens.delete(temp_token) if whitespace?(temp_token)
|
27
|
+
break if temp_token.type == :NEWLINE
|
28
|
+
end
|
29
|
+
|
30
|
+
temp_token.next_token = token
|
31
|
+
token.prev_token = temp_token
|
32
|
+
index = tokens.index(token.next_code_token)
|
33
|
+
tokens.insert(index, token)
|
34
|
+
|
35
|
+
whitespace_token = PuppetLint::Lexer::Token.new(:WHITESPACE, ' ', temp_token.line + 1, 3)
|
36
|
+
whitespace_token.prev_token = token
|
37
|
+
token.next_token = whitespace_token
|
38
|
+
whitespace_token.next_token = tokens[index + 1]
|
39
|
+
tokens[index + 1].prev_token = whitespace_token
|
40
|
+
tokens.insert(index + 1, whitespace_token)
|
41
|
+
end
|
42
|
+
|
43
|
+
def whitespace?(token)
|
44
|
+
Set[:INDENT, :WHITESPACE].include?(token.type)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Public: Test the manifest tokens for any classes or defined types that are
|
2
|
+
# not in an appropriately named file for the autoloader to detect and record
|
3
|
+
# an error of each instance found.
|
4
|
+
#
|
5
|
+
# https://docs.puppet.com/guides/style_guide.html#separate-files
|
6
|
+
PuppetLint.new_check(:autoloader_layout) do
|
7
|
+
def check
|
8
|
+
unless fullpath.nil? || fullpath == ''
|
9
|
+
(class_indexes + defined_type_indexes).each do |class_idx|
|
10
|
+
title_token = class_idx[:name_token]
|
11
|
+
split_title = title_token.value.split('::')
|
12
|
+
mod = split_title.first
|
13
|
+
if split_title.length > 1
|
14
|
+
expected_path = "/#{mod}/manifests/#{split_title[1..-1].join('/')}.pp"
|
15
|
+
else
|
16
|
+
expected_path = "/#{title_token.value}/manifests/init.pp"
|
17
|
+
end
|
18
|
+
|
19
|
+
if PuppetLint.configuration.relative
|
20
|
+
expected_path = expected_path.gsub(/^\//,'').split('/')[1..-1].join('/')
|
21
|
+
end
|
22
|
+
|
23
|
+
unless fullpath.end_with? expected_path
|
24
|
+
notify :error, {
|
25
|
+
:message => "#{title_token.value} not in autoload module layout",
|
26
|
+
:line => title_token.line,
|
27
|
+
:column => title_token.column,
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Public: Check the manifest tokens for any classes that inherit a params
|
2
|
+
# subclass and record a warning for each instance found.
|
3
|
+
#
|
4
|
+
# No style guide reference
|
5
|
+
PuppetLint.new_check(:class_inherits_from_params_class) do
|
6
|
+
def check
|
7
|
+
class_indexes.each do |class_idx|
|
8
|
+
unless class_idx[:inherited_token].nil?
|
9
|
+
if class_idx[:inherited_token].value.end_with? '::params'
|
10
|
+
notify :warning, {
|
11
|
+
:message => 'class inheriting from params class',
|
12
|
+
:line => class_idx[:inherited_token].line,
|
13
|
+
:column => class_idx[:inherited_token].column,
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
PuppetLint.configuration.send('disable_class_inherits_from_params_class')
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Public: Test that no code is outside of a class or define scope.
|
2
|
+
#
|
3
|
+
# No style guide reference
|
4
|
+
PuppetLint.new_check(:code_on_top_scope) do
|
5
|
+
def check
|
6
|
+
class_scope = (class_indexes + defined_type_indexes).map { |e| tokens[e[:start]..e[:end]] }.flatten
|
7
|
+
top_scope = tokens - class_scope
|
8
|
+
|
9
|
+
top_scope.each do |token|
|
10
|
+
unless formatting_tokens.include? token.type
|
11
|
+
notify :warning, {
|
12
|
+
:message => "code outside of class or define block - #{token.value}",
|
13
|
+
:line => token.line,
|
14
|
+
:column => token.column
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
PuppetLint.configuration.send("disable_code_on_top_scope")
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Public: Test the manifest tokens for any classes that inherit across
|
2
|
+
# namespaces and record a warning for each instance found.
|
3
|
+
#
|
4
|
+
# https://docs.puppet.com/guides/style_guide.html#class-inheritance
|
5
|
+
PuppetLint.new_check(:inherits_across_namespaces) do
|
6
|
+
def check
|
7
|
+
class_indexes.each do |class_idx|
|
8
|
+
unless class_idx[:inherited_token].nil?
|
9
|
+
inherited_module_name = class_idx[:inherited_token].value.split('::').reject { |r| r.empty? }.first
|
10
|
+
class_module_name = class_idx[:name_token].value.split('::').reject { |r| r.empty? }.first
|
11
|
+
|
12
|
+
unless class_module_name == inherited_module_name
|
13
|
+
notify :warning, {
|
14
|
+
:message => "class inherits across module namespaces",
|
15
|
+
:line => class_idx[:inherited_token].line,
|
16
|
+
:column => class_idx[:inherited_token].column,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Public: Check the manifest tokens for any classes or defined types that
|
2
|
+
# have a dash in their name and record an error for each instance found.
|
3
|
+
#
|
4
|
+
# No style guide reference
|
5
|
+
PuppetLint.new_check(:names_containing_dash) do
|
6
|
+
def check
|
7
|
+
(class_indexes + defined_type_indexes).each do |class_idx|
|
8
|
+
if class_idx[:name_token].value.include? '-'
|
9
|
+
if class_idx[:type] == :CLASS
|
10
|
+
obj_type = 'class'
|
11
|
+
else
|
12
|
+
obj_type = 'defined type'
|
13
|
+
end
|
14
|
+
|
15
|
+
notify :error, {
|
16
|
+
:message => "#{obj_type} name containing a dash",
|
17
|
+
:line => class_idx[:name_token].line,
|
18
|
+
:column => class_idx[:name_token].column,
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Public: Find and warn about module names with illegal uppercase characters.
|
2
|
+
#
|
3
|
+
# https://docs.puppet.com/puppet/latest/reference/modules_fundamentals.html#allowed-module-names
|
4
|
+
# Provides a fix. [puppet-lint #554]
|
5
|
+
PuppetLint.new_check(:names_containing_uppercase) do
|
6
|
+
def check
|
7
|
+
(class_indexes + defined_type_indexes).each do |class_idx|
|
8
|
+
if class_idx[:name_token].value =~ /[A-Z]/
|
9
|
+
if class_idx[:type] == :CLASS
|
10
|
+
obj_type = 'class'
|
11
|
+
else
|
12
|
+
obj_type = 'defined type'
|
13
|
+
end
|
14
|
+
|
15
|
+
notify :error, {
|
16
|
+
:message => "#{obj_type} '#{class_idx[:name_token].value}' contains illegal uppercase",
|
17
|
+
:line => class_idx[:name_token].line,
|
18
|
+
:column => class_idx[:name_token].column,
|
19
|
+
:token => class_idx[:name_token],
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def fix(problem)
|
26
|
+
problem[:token].value.downcase!
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Public: Test the manifest tokens for any classes or defined types that are
|
2
|
+
# defined inside another class.
|
3
|
+
#
|
4
|
+
# https://docs.puppet.com/guides/style_guide.html#nested-classes-or-defined-types
|
5
|
+
PuppetLint.new_check(:nested_classes_or_defines) do
|
6
|
+
TOKENS = Set[:CLASS, :DEFINE]
|
7
|
+
|
8
|
+
def check
|
9
|
+
class_indexes.each do |class_idx|
|
10
|
+
# Skip the first token so that we don't pick up the first :CLASS
|
11
|
+
class_tokens = class_idx[:tokens][1..-1]
|
12
|
+
|
13
|
+
class_tokens.each do |token|
|
14
|
+
if TOKENS.include?(token.type)
|
15
|
+
if token.next_code_token.type != :LBRACE
|
16
|
+
type = token.type == :CLASS ? 'class' : 'defined type'
|
17
|
+
|
18
|
+
notify :warning, {
|
19
|
+
:message => "#{type} defined inside a class",
|
20
|
+
:line => token.line,
|
21
|
+
:column => token.column,
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Public: Test the manifest tokens for any parameterised classes or defined
|
2
|
+
# types that take parameters and record a warning if there are any optional
|
3
|
+
# parameters listed before required parameters.
|
4
|
+
#
|
5
|
+
# https://docs.puppet.com/guides/style_guide.html#display-order-of-parameters
|
6
|
+
PuppetLint.new_check(:parameter_order) do
|
7
|
+
def check
|
8
|
+
(class_indexes + defined_type_indexes).each do |class_idx|
|
9
|
+
unless class_idx[:param_tokens].nil?
|
10
|
+
paren_stack = []
|
11
|
+
hash_or_array_stack = []
|
12
|
+
class_idx[:param_tokens].each_with_index do |token, i|
|
13
|
+
if token.type == :LPAREN
|
14
|
+
paren_stack.push(true)
|
15
|
+
elsif token.type == :RPAREN
|
16
|
+
paren_stack.pop
|
17
|
+
elsif token.type == :LBRACE || token.type == :LBRACK
|
18
|
+
hash_or_array_stack.push(true)
|
19
|
+
elsif token.type == :RBRACE || token.type == :RBRACK
|
20
|
+
hash_or_array_stack.pop
|
21
|
+
end
|
22
|
+
next if (! hash_or_array_stack.empty?)
|
23
|
+
next unless paren_stack.empty?
|
24
|
+
|
25
|
+
if token.type == :VARIABLE
|
26
|
+
if token.next_code_token.nil? || [:COMMA, :RPAREN].include?(token.next_code_token.type)
|
27
|
+
prev_tokens = class_idx[:param_tokens][0..i]
|
28
|
+
unless prev_tokens.rindex { |r| r.type == :EQUALS }.nil?
|
29
|
+
unless token.prev_code_token.nil? or token.prev_code_token.type == :EQUALS
|
30
|
+
msg = 'optional parameter listed before required parameter'
|
31
|
+
notify :warning, {
|
32
|
+
:message => msg,
|
33
|
+
:line => token.line,
|
34
|
+
:column => token.column,
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Public: Test the manifest tokens for any right-to-left (<-) chaining
|
2
|
+
# operators and record a warning for each instance found.
|
3
|
+
#
|
4
|
+
# https://docs.puppet.com/guides/style_guide.html#chaining-arrow-syntax
|
5
|
+
PuppetLint.new_check(:right_to_left_relationship) do
|
6
|
+
def check
|
7
|
+
tokens.select { |r| r.type == :OUT_EDGE }.each do |token|
|
8
|
+
notify :warning, {
|
9
|
+
:message => 'right-to-left (<-) relationship',
|
10
|
+
:line => token.line,
|
11
|
+
:column => token.column,
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Public: Test the manifest tokens for any variables that are referenced in
|
2
|
+
# the manifest. If the variables are not fully qualified or one of the
|
3
|
+
# variables automatically created in the scope, check that they have been
|
4
|
+
# defined in the local scope and record a warning for each variable that has
|
5
|
+
# not.
|
6
|
+
#
|
7
|
+
# https://docs.puppet.com/guides/style_guide.html#namespacing-variables
|
8
|
+
PuppetLint.new_check(:variable_scope) do
|
9
|
+
DEFAULT_SCOPE_VARS = Set[
|
10
|
+
'name',
|
11
|
+
'title',
|
12
|
+
'module_name',
|
13
|
+
'environment',
|
14
|
+
'clientcert',
|
15
|
+
'clientversion',
|
16
|
+
'servername',
|
17
|
+
'serverip',
|
18
|
+
'serverversion',
|
19
|
+
'caller_module_name',
|
20
|
+
'alias',
|
21
|
+
'audit',
|
22
|
+
'before',
|
23
|
+
'loglevel',
|
24
|
+
'noop',
|
25
|
+
'notify',
|
26
|
+
'require',
|
27
|
+
'schedule',
|
28
|
+
'stage',
|
29
|
+
'subscribe',
|
30
|
+
'tag',
|
31
|
+
'facts',
|
32
|
+
'trusted',
|
33
|
+
'server_facts',
|
34
|
+
]
|
35
|
+
POST_VAR_TOKENS = Set[:COMMA, :EQUALS, :RPAREN]
|
36
|
+
|
37
|
+
def check
|
38
|
+
variables_in_scope = DEFAULT_SCOPE_VARS.clone
|
39
|
+
|
40
|
+
(class_indexes + defined_type_indexes).each do |idx|
|
41
|
+
referenced_variables = Set[]
|
42
|
+
object_tokens = idx[:tokens]
|
43
|
+
|
44
|
+
unless idx[:param_tokens].nil?
|
45
|
+
idx[:param_tokens].each do |token|
|
46
|
+
if token.type == :VARIABLE
|
47
|
+
if POST_VAR_TOKENS.include? token.next_code_token.type
|
48
|
+
variables_in_scope << token.value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
future_parser_scopes = {}
|
55
|
+
in_pipe = false
|
56
|
+
block_params_stack = []
|
57
|
+
|
58
|
+
object_tokens.each do |token|
|
59
|
+
case token.type
|
60
|
+
when :EQUALS
|
61
|
+
if token.prev_code_token.type == :VARIABLE
|
62
|
+
variables_in_scope << token.prev_code_token.value
|
63
|
+
elsif token.prev_code_token.type == :RBRACK
|
64
|
+
temp_token = token
|
65
|
+
|
66
|
+
brack_depth = 0
|
67
|
+
while temp_token = temp_token.prev_code_token
|
68
|
+
case temp_token.type
|
69
|
+
when :VARIABLE
|
70
|
+
variables_in_scope << temp_token.value
|
71
|
+
when :RBRACK
|
72
|
+
brack_depth += 1
|
73
|
+
when :LBRACK
|
74
|
+
brack_depth -= 1
|
75
|
+
break if brack_depth == 0
|
76
|
+
when :COMMA
|
77
|
+
# ignore
|
78
|
+
else # unexpected
|
79
|
+
break
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
when :VARIABLE
|
84
|
+
if in_pipe
|
85
|
+
block_params_stack[-1] << token.value
|
86
|
+
else
|
87
|
+
referenced_variables << token
|
88
|
+
end
|
89
|
+
when :PIPE
|
90
|
+
in_pipe = !in_pipe
|
91
|
+
|
92
|
+
if in_pipe
|
93
|
+
block_params_stack << []
|
94
|
+
else
|
95
|
+
start_idx = tokens.find_index(token)
|
96
|
+
end_token = nil
|
97
|
+
brace_depth = 0
|
98
|
+
|
99
|
+
tokens[start_idx..-1].each do |sub_token|
|
100
|
+
case sub_token.type
|
101
|
+
when :LBRACE
|
102
|
+
brace_depth += 1
|
103
|
+
when :RBRACE
|
104
|
+
brace_depth -= 1
|
105
|
+
if brace_depth == 0
|
106
|
+
end_token = sub_token
|
107
|
+
break
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
params = block_params_stack.pop
|
113
|
+
(token.line..end_token.line).each do |line|
|
114
|
+
future_parser_scopes[line] ||= []
|
115
|
+
future_parser_scopes[line].concat(params)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
msg = "top-scope variable being used without an explicit namespace"
|
122
|
+
referenced_variables.each do |token|
|
123
|
+
unless future_parser_scopes[token.line].nil?
|
124
|
+
next if future_parser_scopes[token.line].include?(token.value.gsub(/\[.+\]\Z/, ''))
|
125
|
+
end
|
126
|
+
|
127
|
+
unless token.value.include? '::'
|
128
|
+
unless token.value =~ /^(facts|trusted)\[.+\]/
|
129
|
+
unless variables_in_scope.include? token.value.gsub(/\[.+\]\Z/, '')
|
130
|
+
unless token.value =~ /\A\d+\Z/
|
131
|
+
notify :warning, {
|
132
|
+
:message => msg,
|
133
|
+
:line => token.line,
|
134
|
+
:column => token.column,
|
135
|
+
}
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|