halyard-puppet-lint 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +20 -0
  6. data/README.md +210 -0
  7. data/Rakefile +7 -0
  8. data/bin/puppet-lint +7 -0
  9. data/lib/puppet-lint.rb +214 -0
  10. data/lib/puppet-lint/bin.rb +79 -0
  11. data/lib/puppet-lint/checkplugin.rb +176 -0
  12. data/lib/puppet-lint/checks.rb +91 -0
  13. data/lib/puppet-lint/configuration.rb +153 -0
  14. data/lib/puppet-lint/data.rb +521 -0
  15. data/lib/puppet-lint/lexer.rb +373 -0
  16. data/lib/puppet-lint/lexer/token.rb +101 -0
  17. data/lib/puppet-lint/monkeypatches.rb +2 -0
  18. data/lib/puppet-lint/monkeypatches/string_percent.rb +52 -0
  19. data/lib/puppet-lint/monkeypatches/string_prepend.rb +13 -0
  20. data/lib/puppet-lint/optparser.rb +118 -0
  21. data/lib/puppet-lint/plugins.rb +74 -0
  22. data/lib/puppet-lint/plugins/check_classes.rb +285 -0
  23. data/lib/puppet-lint/plugins/check_comments.rb +55 -0
  24. data/lib/puppet-lint/plugins/check_conditionals.rb +65 -0
  25. data/lib/puppet-lint/plugins/check_documentation.rb +31 -0
  26. data/lib/puppet-lint/plugins/check_nodes.rb +29 -0
  27. data/lib/puppet-lint/plugins/check_resources.rb +194 -0
  28. data/lib/puppet-lint/plugins/check_strings.rb +174 -0
  29. data/lib/puppet-lint/plugins/check_variables.rb +19 -0
  30. data/lib/puppet-lint/plugins/check_whitespace.rb +170 -0
  31. data/lib/puppet-lint/tasks/puppet-lint.rb +91 -0
  32. data/lib/puppet-lint/version.rb +3 -0
  33. data/puppet-lint.gemspec +24 -0
  34. data/spec/fixtures/test/manifests/fail.pp +2 -0
  35. data/spec/fixtures/test/manifests/ignore.pp +1 -0
  36. data/spec/fixtures/test/manifests/ignore_multiple_block.pp +6 -0
  37. data/spec/fixtures/test/manifests/ignore_multiple_line.pp +2 -0
  38. data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
  39. data/spec/fixtures/test/manifests/init.pp +3 -0
  40. data/spec/fixtures/test/manifests/malformed.pp +1 -0
  41. data/spec/fixtures/test/manifests/url_interpolation.pp +12 -0
  42. data/spec/fixtures/test/manifests/warning.pp +2 -0
  43. data/spec/puppet-lint/bin_spec.rb +326 -0
  44. data/spec/puppet-lint/configuration_spec.rb +56 -0
  45. data/spec/puppet-lint/ignore_overrides_spec.rb +109 -0
  46. data/spec/puppet-lint/lexer/token_spec.rb +18 -0
  47. data/spec/puppet-lint/lexer_spec.rb +783 -0
  48. data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +105 -0
  49. data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +35 -0
  50. data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +33 -0
  51. data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +45 -0
  52. data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +76 -0
  53. data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +73 -0
  54. data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +25 -0
  55. data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +196 -0
  56. data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +45 -0
  57. data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +84 -0
  58. data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +98 -0
  59. data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +36 -0
  60. data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +52 -0
  61. data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +146 -0
  62. data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +100 -0
  63. data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +55 -0
  64. data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +89 -0
  65. data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +113 -0
  66. data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +45 -0
  67. data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +216 -0
  68. data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +199 -0
  69. data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +114 -0
  70. data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +62 -0
  71. data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +129 -0
  72. data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +17 -0
  73. data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +73 -0
  74. data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +37 -0
  75. data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +21 -0
  76. data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +54 -0
  77. data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +524 -0
  78. data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +45 -0
  79. data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +101 -0
  80. data/spec/puppet-lint_spec.rb +20 -0
  81. data/spec/spec_helper.rb +129 -0
  82. metadata +229 -0
@@ -0,0 +1,2 @@
1
+ require 'puppet-lint/monkeypatches/string_prepend'
2
+ require 'puppet-lint/monkeypatches/string_percent'
@@ -0,0 +1,52 @@
1
+ # If we are using an older ruby version, we back-port the basic functionality
2
+ # we need for formatting output: 'somestring' % <hash>
3
+ begin
4
+ if ('%{test}' % {:test => 'replaced'} == 'replaced')
5
+ # If this works, we are all good to go.
6
+ end
7
+ rescue
8
+ # If the test failed (threw a error), monkeypatch String.
9
+ # Most of this code came from http://www.ruby-forum.com/topic/144310 but was
10
+ # simplified for our use.
11
+
12
+ # Basic implementation of 'string' % { } like we need it. needs work.
13
+ class String
14
+ Percent = instance_method '%' unless defined? Percent
15
+ def % *a, &b
16
+ a.flatten!
17
+
18
+ string = case a.last
19
+ when Hash
20
+ expand a.pop
21
+ else
22
+ self
23
+ end
24
+
25
+ if a.empty?
26
+ string
27
+ else
28
+ Percent.bind(string).call(a, &b)
29
+ end
30
+
31
+ end
32
+ def expand! vars = {}
33
+ loop do
34
+ changed = false
35
+ vars.each do |var, value|
36
+ var = var.to_s
37
+ var.gsub! %r/[^a-zA-Z0-9_]/, ''
38
+ [
39
+ %r/\%\{#{ var }\}/,
40
+ ].each do |pat|
41
+ changed = gsub! pat, "#{ value }"
42
+ end
43
+ end
44
+ break unless changed
45
+ end
46
+ self
47
+ end
48
+ def expand opts = {}
49
+ dup.expand! opts
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,13 @@
1
+ unless String.respond_to?('prepend')
2
+ # Internal: Monkey patching String.
3
+ class String
4
+ # Internal: Prepends a String to self.
5
+ #
6
+ # lead - The String to prepend self with.
7
+ #
8
+ # Returns a String which is lead and self concatenated.
9
+ def prepend(lead)
10
+ self.replace "#{lead}#{self}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,118 @@
1
+ require 'optparse'
2
+
3
+ # Public: Contains the puppet-lint option parser so that it can be used easily
4
+ # in multiple places.
5
+ class PuppetLint::OptParser
6
+ HELP_TEXT = <<-EOF
7
+ puppet-lint
8
+
9
+ Basic Command Line Usage:
10
+ puppet-lint [OPTIONS] PATH
11
+
12
+ PATH The path to the Puppet manifest.
13
+
14
+ Option:
15
+ EOF
16
+
17
+ # Public: Initialise a new puppet-lint OptionParser.
18
+ #
19
+ # Returns an OptionParser object.
20
+ def self.build
21
+ OptionParser.new do |opts|
22
+ opts.banner = HELP_TEXT
23
+
24
+ opts.on('--version', 'Display the current version.') do
25
+ PuppetLint.configuration.display_version = true
26
+ end
27
+
28
+ opts.on('-c', '--config FILE', 'Load puppet-lint options from file.') do |file|
29
+ opts.load(file)
30
+ end
31
+
32
+ opts.on('--with-context', 'Show where in the manifest the problem is.') do
33
+ PuppetLint.configuration.with_context = true
34
+ end
35
+
36
+ opts.on('--with-filename', 'Display the filename before the warning.') do
37
+ PuppetLint.configuration.with_filename = true
38
+ end
39
+
40
+ opts.on('--fail-on-warnings', 'Return a non-zero exit status for warnings') do
41
+ PuppetLint.configuration.fail_on_warnings = true
42
+ end
43
+
44
+ opts.on('--error-level LEVEL', [:all, :warning, :error],
45
+ 'The level of error to return (warning, error or all).') do |el|
46
+ PuppetLint.configuration.error_level = el
47
+ end
48
+
49
+ opts.on('--show-ignored', 'Show problems that have been ignored by control comments') do
50
+ PuppetLint.configuration.show_ignored = true
51
+ end
52
+
53
+ opts.on('--relative', 'Compare module layout relative to the module root') do
54
+ PuppetLint.configuration.relative = true
55
+ end
56
+
57
+ opts.on('-l', '--load FILE', 'Load a file containing custom puppet-lint checks.') do |f|
58
+ load f
59
+ end
60
+
61
+ opts.on('--load-from-puppet MODULEPATH', 'Load plugins from the given Puppet module path.') do |path|
62
+ path.split(':').each do |p|
63
+ Dir["#{p}/*/lib/puppet-lint/plugins/*.rb"].each do |file|
64
+ load file
65
+ end
66
+ end
67
+ end
68
+
69
+ opts.on('-f', '--fix', 'Attempt to automatically fix errors') do
70
+ PuppetLint.configuration.fix = true
71
+ end
72
+
73
+ opts.on('--log-format FORMAT',
74
+ 'Change the log format.', 'Overrides --with-filename.',
75
+ 'The following placeholders can be used:',
76
+ '%{filename} - Filename without path.',
77
+ '%{path} - Path as provided to puppet-lint.',
78
+ '%{fullpath} - Expanded path to the file.',
79
+ '%{line} - Line number.',
80
+ '%{column} - Column number.',
81
+ '%{kind} - The kind of message (warning, error).',
82
+ '%{KIND} - Uppercase version of %{kind}.',
83
+ '%{check} - The name of the check.',
84
+ '%{message} - The message.'
85
+ ) do |format|
86
+ if format.include?('%{linenumber}')
87
+ $stderr.puts "DEPRECATION: Please use %{line} instead of %{linenumber}"
88
+ end
89
+ PuppetLint.configuration.log_format = format
90
+ end
91
+
92
+ opts.separator ''
93
+ opts.separator ' Checks:'
94
+
95
+ opts.on('--only-checks CHECKS', 'A comma separated list of checks that should be run') do |checks|
96
+ enable_checks = checks.split(',').map(&:to_sym)
97
+ (PuppetLint.configuration.checks - enable_checks).each do |check|
98
+ PuppetLint.configuration.send("disable_#{check}")
99
+ end
100
+ end
101
+
102
+ PuppetLint.configuration.checks.each do |check|
103
+ opts.on("--no-#{check}-check", "Skip the #{check} check.") do
104
+ PuppetLint.configuration.send("disable_#{check}")
105
+ end
106
+ end
107
+
108
+ opts.load('/etc/puppet-lint.rc')
109
+ begin
110
+ opts.load(File.expand_path('~/.puppet-lint.rc')) if ENV['HOME']
111
+ rescue Errno::EACCES
112
+ # silently skip loading this file if HOME is set to a directory that
113
+ # the user doesn't have read access to.
114
+ end
115
+ opts.load('.puppet-lint.rc')
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,74 @@
1
+ require 'pathname'
2
+
3
+ class PuppetLint
4
+ # Public: Various methods that implement puppet-lint's plugin system
5
+ #
6
+ # Examples
7
+ #
8
+ # PuppetLint::Plugins.load_spec_helper
9
+ class Plugins
10
+ # Internal: Find any gems containing puppet-lint plugins and load them.
11
+ #
12
+ # Returns nothing.
13
+ def self.load_from_gems
14
+ gem_directories.select { |path|
15
+ (path + 'puppet-lint/plugins').directory?
16
+ }.each do |gem_path|
17
+ Dir["#{(gem_path + 'puppet-lint/plugins').to_s}/*.rb"].each do |file|
18
+ load file
19
+ end
20
+ end
21
+ end
22
+
23
+ # Public: Load the puppet-lint spec_helper.rb
24
+ #
25
+ # Returns nothings.
26
+ def self.load_spec_helper
27
+ gemspec = gemspecs.select { |spec| spec.name == 'puppet-lint' }.first
28
+ load Pathname.new(gemspec.full_gem_path) + 'spec/spec_helper.rb'
29
+ end
30
+ private
31
+ # Internal: Check if RubyGems is loaded and available.
32
+ #
33
+ # Returns true if RubyGems is available, false if not.
34
+ def self.has_rubygems?
35
+ defined? ::Gem
36
+ end
37
+
38
+ # Internal: Retrieve a list of avaliable gemspecs.
39
+ #
40
+ # Returns an Array of Gem::Specification objects.
41
+ def self.gemspecs
42
+ @gemspecs ||= if Gem::Specification.respond_to?(:latest_specs)
43
+ Gem::Specification.latest_specs
44
+ else
45
+ Gem.searcher.init_gemspecs
46
+ end
47
+ end
48
+
49
+ # Internal: Retrieve a list of available gem paths from RubyGems.
50
+ #
51
+ # Returns an Array of Pathname objects.
52
+ def self.gem_directories
53
+ if has_rubygems?
54
+ gemspecs.reject { |spec| spec.name == 'puppet-lint' }.map do |spec|
55
+ Pathname.new(spec.full_gem_path) + 'lib'
56
+ end
57
+ else
58
+ []
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ require 'puppet-lint/plugins/check_classes'
65
+ require 'puppet-lint/plugins/check_comments'
66
+ require 'puppet-lint/plugins/check_conditionals'
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'
73
+
74
+ PuppetLint::Plugins.load_from_gems
@@ -0,0 +1,285 @@
1
+ # Public: Test the manifest tokens for any right-to-left (<-) chaining
2
+ # operators and record a warning for each instance found.
3
+ PuppetLint.new_check(:right_to_left_relationship) do
4
+ def check
5
+ tokens.select { |r| r.type == :OUT_EDGE }.each do |token|
6
+ notify :warning, {
7
+ :message => 'right-to-left (<-) relationship',
8
+ :line => token.line,
9
+ :column => token.column,
10
+ }
11
+ end
12
+ end
13
+ end
14
+
15
+ # Public: Test the manifest tokens for any classes or defined types that are
16
+ # not in an appropriately named file for the autoloader to detect and record
17
+ # an error of each instance found.
18
+ PuppetLint.new_check(:autoloader_layout) do
19
+ def check
20
+ unless fullpath.nil? || fullpath == ''
21
+ (class_indexes + defined_type_indexes).each do |class_idx|
22
+ title_token = class_idx[:name_token]
23
+ split_title = title_token.value.split('::')
24
+ mod = split_title.first
25
+ if split_title.length > 1
26
+ expected_path = "/#{mod}/manifests/#{split_title[1..-1].join('/')}.pp"
27
+ else
28
+ expected_path = "/#{title_token.value}/manifests/init.pp"
29
+ end
30
+
31
+ if PuppetLint.configuration.relative
32
+ expected_path = expected_path.gsub(/^\//,'').split('/')[1..-1].join('/')
33
+ end
34
+
35
+ unless fullpath.end_with? expected_path
36
+ notify :error, {
37
+ :message => "#{title_token.value} not in autoload module layout",
38
+ :line => title_token.line,
39
+ :column => title_token.column,
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ # Public: Check the manifest tokens for any classes or defined types that
48
+ # have a dash in their name and record an error for each instance found.
49
+ PuppetLint.new_check(:names_containing_dash) do
50
+ def check
51
+ (class_indexes + defined_type_indexes).each do |class_idx|
52
+ if class_idx[:name_token].value.include? '-'
53
+ if class_idx[:type] == :CLASS
54
+ obj_type = 'class'
55
+ else
56
+ obj_type = 'defined type'
57
+ end
58
+
59
+ notify :error, {
60
+ :message => "#{obj_type} name containing a dash",
61
+ :line => class_idx[:name_token].line,
62
+ :column => class_idx[:name_token].column,
63
+ }
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # Public: Check the manifest tokens for any classes that inherit a params
70
+ # subclass and record a warning for each instance found.
71
+ PuppetLint.new_check(:class_inherits_from_params_class) do
72
+ def check
73
+ class_indexes.each do |class_idx|
74
+ unless class_idx[:inherited_token].nil?
75
+ if class_idx[:inherited_token].value.end_with? '::params'
76
+ notify :warning, {
77
+ :message => 'class inheriting from params class',
78
+ :line => class_idx[:inherited_token].line,
79
+ :column => class_idx[:inherited_token].column,
80
+ }
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ # Public: Test the manifest tokens for any parameterised classes or defined
88
+ # types that take parameters and record a warning if there are any optional
89
+ # parameters listed before required parameters.
90
+ PuppetLint.new_check(:parameter_order) do
91
+ def check
92
+ defined_type_indexes.each do |class_idx|
93
+ unless class_idx[:param_tokens].nil?
94
+ paren_stack = []
95
+ class_idx[:param_tokens].each_with_index do |token, i|
96
+ if token.type == :LPAREN
97
+ paren_stack.push(true)
98
+ elsif token.type == :RPAREN
99
+ paren_stack.pop
100
+ end
101
+ next unless paren_stack.empty?
102
+
103
+ if token.type == :VARIABLE
104
+ if token.next_code_token.nil? || [:COMMA, :RPAREN].include?(token.next_code_token.type)
105
+ prev_tokens = class_idx[:param_tokens][0..i]
106
+ unless prev_tokens.rindex { |r| r.type == :EQUALS }.nil?
107
+ unless token.prev_code_token.nil? or token.prev_code_token.type == :EQUALS
108
+ msg = 'optional parameter listed before required parameter'
109
+ notify :warning, {
110
+ :message => msg,
111
+ :line => token.line,
112
+ :column => token.column,
113
+ }
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ # Public: Test the manifest tokens for any classes that inherit across
125
+ # namespaces and record a warning for each instance found.
126
+ PuppetLint.new_check(:inherits_across_namespaces) do
127
+ def check
128
+ class_indexes.each do |class_idx|
129
+ unless class_idx[:inherited_token].nil?
130
+ inherited_module_name = class_idx[:inherited_token].value.split('::').reject { |r| r.empty? }.first
131
+ class_module_name = class_idx[:name_token].value.split('::').reject { |r| r.empty? }.first
132
+
133
+ unless class_module_name == inherited_module_name
134
+ notify :warning, {
135
+ :message => "class inherits across module namespaces",
136
+ :line => class_idx[:inherited_token].line,
137
+ :column => class_idx[:inherited_token].column,
138
+ }
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ # Public: Test the manifest tokens for any classes or defined types that are
146
+ # defined inside another class.
147
+ PuppetLint.new_check(:nested_classes_or_defines) do
148
+ TOKENS = Set[:CLASS, :DEFINE]
149
+
150
+ def check
151
+ class_indexes.each do |class_idx|
152
+ # Skip the first token so that we don't pick up the first :CLASS
153
+ class_tokens = class_idx[:tokens][1..-1]
154
+
155
+ class_tokens.each do |token|
156
+ if TOKENS.include?(token.type)
157
+ if token.next_code_token.type != :LBRACE
158
+ type = token.type == :CLASS ? 'class' : 'defined type'
159
+
160
+ notify :warning, {
161
+ :message => "#{type} defined inside a class",
162
+ :line => token.line,
163
+ :column => token.column,
164
+ }
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ # Public: Test the manifest tokens for any variables that are referenced in
173
+ # the manifest. If the variables are not fully qualified or one of the
174
+ # variables automatically created in the scope, check that they have been
175
+ # defined in the local scope and record a warning for each variable that has
176
+ # not.
177
+ PuppetLint.new_check(:variable_scope) do
178
+ DEFAULT_SCOPE_VARS = Set[
179
+ 'name',
180
+ 'title',
181
+ 'module_name',
182
+ 'environment',
183
+ 'clientcert',
184
+ 'clientversion',
185
+ 'servername',
186
+ 'serverip',
187
+ 'serverversion',
188
+ 'caller_module_name',
189
+ 'alias',
190
+ 'audit',
191
+ 'before',
192
+ 'loglevel',
193
+ 'noop',
194
+ 'notify',
195
+ 'require',
196
+ 'schedule',
197
+ 'stage',
198
+ 'subscribe',
199
+ 'tag',
200
+ ]
201
+ POST_VAR_TOKENS = Set[:COMMA, :EQUALS, :RPAREN]
202
+
203
+ def check
204
+ variables_in_scope = DEFAULT_SCOPE_VARS.clone
205
+
206
+ (class_indexes + defined_type_indexes).each do |idx|
207
+ referenced_variables = Set[]
208
+ object_tokens = idx[:tokens]
209
+
210
+ unless idx[:param_tokens].nil?
211
+ idx[:param_tokens].each do |token|
212
+ if token.type == :VARIABLE
213
+ if POST_VAR_TOKENS.include? token.next_code_token.type
214
+ variables_in_scope << token.value
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ future_parser_scopes = {}
221
+ in_pipe = false
222
+ temp_scope_vars = []
223
+
224
+ object_tokens.each do |token|
225
+ if token.type == :VARIABLE
226
+ if in_pipe
227
+ temp_scope_vars << token.value
228
+ else
229
+ if token.next_code_token.type == :EQUALS
230
+ variables_in_scope << token.value
231
+ else
232
+ referenced_variables << token
233
+ end
234
+ end
235
+ elsif token.type == :PIPE
236
+ in_pipe = !in_pipe
237
+
238
+ if in_pipe
239
+ temp_scope_vars = []
240
+ else
241
+ start_idx = tokens.find_index(token)
242
+ end_token = nil
243
+ brace_depth = 0
244
+
245
+ tokens[start_idx..-1].each do |sub_token|
246
+ case sub_token.type
247
+ when :LBRACE
248
+ brace_depth += 1
249
+ when :RBRACE
250
+ brace_depth -= 1
251
+ if brace_depth == 0
252
+ end_token = sub_token
253
+ break
254
+ end
255
+ end
256
+ end
257
+
258
+ future_parser_scopes.merge!(Hash[(token.line..end_token.line).to_a.map { |i| [i, temp_scope_vars] }])
259
+ end
260
+ end
261
+ end
262
+
263
+ msg = "top-scope variable being used without an explicit namespace"
264
+ referenced_variables.each do |token|
265
+ unless future_parser_scopes[token.line].nil?
266
+ next if future_parser_scopes[token.line].include?(token.value)
267
+ end
268
+
269
+ unless token.value.include? '::'
270
+ unless token.value =~ /^(facts|trusted)\[.+\]/
271
+ unless variables_in_scope.include? token.value.gsub(/\[.+\]\Z/, '')
272
+ unless token.value =~ /\A\d+\Z/
273
+ notify :warning, {
274
+ :message => msg,
275
+ :line => token.line,
276
+ :column => token.column,
277
+ }
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end
283
+ end
284
+ end
285
+ end