puppet-lint 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|