puppet-lint 0.4.0.pre1 → 1.0.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.
- data/.travis.yml +3 -4
- data/Gemfile +2 -5
- data/README.md +2 -149
- data/Rakefile +0 -5
- data/lib/puppet-lint.rb +74 -20
- data/lib/puppet-lint/bin.rb +20 -85
- data/lib/puppet-lint/checkplugin.rb +158 -12
- data/lib/puppet-lint/checks.rb +39 -222
- data/lib/puppet-lint/configuration.rb +12 -31
- data/lib/puppet-lint/data.rb +329 -0
- data/lib/puppet-lint/lexer.rb +37 -30
- data/lib/puppet-lint/lexer/token.rb +14 -16
- data/lib/puppet-lint/monkeypatches/string_prepend.rb +6 -0
- data/lib/puppet-lint/optparser.rb +105 -0
- data/lib/puppet-lint/plugins.rb +28 -9
- data/lib/puppet-lint/plugins/check_classes.rb +162 -238
- data/lib/puppet-lint/plugins/check_comments.rb +40 -25
- data/lib/puppet-lint/plugins/check_conditionals.rb +16 -20
- data/lib/puppet-lint/plugins/check_documentation.rb +14 -20
- data/lib/puppet-lint/plugins/check_nodes.rb +23 -0
- data/lib/puppet-lint/plugins/check_resources.rb +127 -141
- data/lib/puppet-lint/plugins/check_strings.rb +133 -107
- data/lib/puppet-lint/plugins/check_variables.rb +11 -11
- data/lib/puppet-lint/plugins/check_whitespace.rb +86 -92
- data/lib/puppet-lint/tasks/puppet-lint.rb +17 -1
- data/lib/puppet-lint/version.rb +1 -1
- data/puppet-lint.gemspec +4 -2
- data/spec/fixtures/test/manifests/ignore.pp +1 -0
- data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
- data/spec/puppet-lint/bin_spec.rb +104 -84
- data/spec/puppet-lint/configuration_spec.rb +19 -19
- data/spec/puppet-lint/ignore_overrides_spec.rb +97 -0
- data/spec/puppet-lint/lexer/token_spec.rb +9 -9
- data/spec/puppet-lint/lexer_spec.rb +352 -325
- data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +77 -23
- data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +14 -12
- data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +18 -14
- data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +30 -30
- data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +31 -26
- data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +34 -28
- data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +14 -12
- data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +74 -30
- data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +27 -20
- data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +78 -13
- data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +17 -12
- data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +13 -10
- data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +21 -16
- data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +69 -0
- data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +42 -38
- data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +22 -10
- data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +81 -18
- data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +69 -112
- data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +27 -20
- data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +177 -171
- data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +165 -88
- data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +97 -22
- data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +25 -0
- data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +97 -111
- data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +10 -9
- data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +53 -53
- data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +26 -14
- data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +10 -9
- data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +31 -15
- data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +340 -322
- data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +30 -23
- data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +42 -41
- data/spec/puppet-lint_spec.rb +3 -3
- data/spec/spec_helper.rb +109 -116
- metadata +109 -50
- data/spec/puppet-lint/plugins/check_classes/class_parameter_defaults_spec.rb +0 -60
@@ -1,4 +1,6 @@
|
|
1
1
|
class PuppetLint
|
2
|
+
# Public: A singleton class to store the running configuration of
|
3
|
+
# puppet-lint.
|
2
4
|
class Configuration
|
3
5
|
# Internal: Add helper methods for a new check to the
|
4
6
|
# PuppetLint::Configuration object.
|
@@ -38,7 +40,9 @@ class PuppetLint
|
|
38
40
|
# Public: Catch situations where options are being set for the first time
|
39
41
|
# and create the necessary methods to get & set the option in the future.
|
40
42
|
#
|
41
|
-
# args
|
43
|
+
# args - An Array of values to set the option to.
|
44
|
+
# method - The String name of the option.
|
45
|
+
# block - Unused.
|
42
46
|
#
|
43
47
|
# Returns nothing.
|
44
48
|
#
|
@@ -102,22 +106,12 @@ class PuppetLint
|
|
102
106
|
# Internal: Register a new check.
|
103
107
|
#
|
104
108
|
# check - The String name of the check
|
105
|
-
#
|
109
|
+
# klass - The Class containing the check logic.
|
106
110
|
#
|
107
111
|
# Returns nothing.
|
108
|
-
def add_check(check,
|
112
|
+
def add_check(check, klass)
|
109
113
|
self.class.add_check(check)
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
# Internal: Register a new check helper method.
|
114
|
-
#
|
115
|
-
# name - The String name of the method.
|
116
|
-
# b - The Block containing the logic of the helper.
|
117
|
-
#
|
118
|
-
# Returns nothing.
|
119
|
-
def add_helper(name, &b)
|
120
|
-
helper_method[name] = b
|
114
|
+
check_object[check] = klass
|
121
115
|
end
|
122
116
|
|
123
117
|
# Internal: Access the internal storage for settings.
|
@@ -130,29 +124,15 @@ class PuppetLint
|
|
130
124
|
# Internal: Access the internal storage for check method blocks.
|
131
125
|
#
|
132
126
|
# Returns a Hash containing all the check blocks.
|
133
|
-
def
|
134
|
-
@
|
127
|
+
def check_object
|
128
|
+
@check_object ||= {}
|
135
129
|
end
|
136
130
|
|
137
131
|
# Public: Get a list of all the defined checks.
|
138
132
|
#
|
139
133
|
# Returns an Array of String check names.
|
140
134
|
def checks
|
141
|
-
|
142
|
-
end
|
143
|
-
|
144
|
-
# Internal: Access the internal storage for helper method blocks.
|
145
|
-
#
|
146
|
-
# Returns a Hash containing all the helper blocks.
|
147
|
-
def helper_method
|
148
|
-
@helper_method ||= {}
|
149
|
-
end
|
150
|
-
|
151
|
-
# Public: Get a list of all the helper methods.
|
152
|
-
#
|
153
|
-
# Returns an Array of String method names.
|
154
|
-
def helpers
|
155
|
-
helper_method.keys
|
135
|
+
check_object.keys
|
156
136
|
end
|
157
137
|
|
158
138
|
# Public: Clear the PuppetLint::Configuration storage and set some sane
|
@@ -167,6 +147,7 @@ class PuppetLint
|
|
167
147
|
self.log_format = ''
|
168
148
|
self.with_context = false
|
169
149
|
self.fix = false
|
150
|
+
self.show_ignored = false
|
170
151
|
end
|
171
152
|
end
|
172
153
|
end
|
@@ -0,0 +1,329 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
# Public: A singleton class storing all the information about the manifest
|
5
|
+
# being analysed.
|
6
|
+
class PuppetLint::Data
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# Internal: Get/Set the full expanded path to the manifest file being
|
11
|
+
# checked.
|
12
|
+
attr_reader :path, :fullpath, :filename
|
13
|
+
|
14
|
+
# Internal: Get/Set the raw manifest data, split by \n.
|
15
|
+
attr_accessor :manifest_lines
|
16
|
+
|
17
|
+
# Internal: Store the tokenised manifest.
|
18
|
+
#
|
19
|
+
# tokens - The Array of PuppetLint::Lexer::Token objects to store.
|
20
|
+
#
|
21
|
+
# Returns nothing.
|
22
|
+
def tokens=(tokens)
|
23
|
+
@tokens = tokens
|
24
|
+
@title_tokens = nil
|
25
|
+
@resource_indexes = nil
|
26
|
+
@class_indexes = nil
|
27
|
+
@defined_type_indexes = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Public: Get the tokenised manifest.
|
31
|
+
#
|
32
|
+
# Returns an Array of PuppetLint::Lexer::Token objects.
|
33
|
+
def tokens
|
34
|
+
if caller[0][/`.*'/][1..-2] == 'check'
|
35
|
+
@tokens.dup
|
36
|
+
else
|
37
|
+
@tokens
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Internal: Store the path to the manifest file and populate fullpath and
|
42
|
+
# filename.
|
43
|
+
#
|
44
|
+
# val - The path to the file as a String.
|
45
|
+
#
|
46
|
+
# Returns nothing.
|
47
|
+
def path=(val)
|
48
|
+
@path = val
|
49
|
+
if val.nil?
|
50
|
+
@fullpath = nil
|
51
|
+
@filename = nil
|
52
|
+
else
|
53
|
+
@fullpath = File.expand_path(val, ENV['PWD'])
|
54
|
+
@filename = File.basename(val)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Internal: Retrieve a list of tokens that represent resource titles
|
59
|
+
#
|
60
|
+
# Returns an Array of PuppetLint::Lexer::Token objects.
|
61
|
+
def title_tokens
|
62
|
+
@title_tokens ||= Proc.new do
|
63
|
+
result = []
|
64
|
+
tokens.each_index do |token_idx|
|
65
|
+
if tokens[token_idx].type == :COLON
|
66
|
+
# gather a list of tokens that are resource titles
|
67
|
+
if tokens[token_idx-1].type == :RBRACK
|
68
|
+
array_start_idx = tokens.rindex { |r|
|
69
|
+
r.type == :LBRACK
|
70
|
+
}
|
71
|
+
title_array_tokens = tokens[(array_start_idx + 1)..(token_idx - 2)]
|
72
|
+
result += title_array_tokens.select { |token|
|
73
|
+
{:STRING => true, :NAME => true}.include? token.type
|
74
|
+
}
|
75
|
+
else
|
76
|
+
next_token = tokens[token_idx].next_code_token
|
77
|
+
if next_token.type != :LBRACE
|
78
|
+
result << tokens[token_idx - 1]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
result
|
84
|
+
end.call
|
85
|
+
end
|
86
|
+
|
87
|
+
# Internal: Calculate the positions of all resource declarations within the
|
88
|
+
# tokenised manifest. These positions only point to the content of the
|
89
|
+
# resource declarations, they do not include resource types or titles.
|
90
|
+
#
|
91
|
+
# Returns an Array of Hashes, each containing:
|
92
|
+
# :start - An Integer position in the `tokens` Array pointing to the
|
93
|
+
# first Token of a resource declaration.
|
94
|
+
# :end - An Integer position in the `tokens` Array pointing to the last
|
95
|
+
# Token of a resource declaration.
|
96
|
+
def resource_indexes
|
97
|
+
@resource_indexes ||= Proc.new do
|
98
|
+
result = []
|
99
|
+
tokens.each_index do |token_idx|
|
100
|
+
if tokens[token_idx].type == :COLON
|
101
|
+
next_token = tokens[token_idx].next_code_token
|
102
|
+
depth = 1
|
103
|
+
if next_token.type != :LBRACE
|
104
|
+
tokens[(token_idx + 1)..-1].each_index do |idx|
|
105
|
+
real_idx = token_idx + idx + 1
|
106
|
+
if tokens[real_idx].type == :LBRACE
|
107
|
+
depth += 1
|
108
|
+
elsif {:SEMIC => true, :RBRACE => true}.include? tokens[real_idx].type
|
109
|
+
unless tokens[real_idx].type == :SEMIC && depth > 1
|
110
|
+
depth -= 1
|
111
|
+
if depth == 0
|
112
|
+
result << {
|
113
|
+
:start => token_idx + 1,
|
114
|
+
:end => real_idx,
|
115
|
+
:tokens => tokens[(token_idx + 1)..real_idx],
|
116
|
+
:type => find_resource_type_token(token_idx),
|
117
|
+
:param_tokens => find_resource_param_tokens(tokens[(token_idx + 1)..real_idx]),
|
118
|
+
}
|
119
|
+
break
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
result
|
128
|
+
end.call
|
129
|
+
end
|
130
|
+
|
131
|
+
# Internal: Find the Token representing the type of a resource definition.
|
132
|
+
#
|
133
|
+
# index - The Integer pointing to the start of the resource in the `tokens`
|
134
|
+
# array.
|
135
|
+
#
|
136
|
+
# Returns a Token object.
|
137
|
+
def find_resource_type_token(index)
|
138
|
+
tokens[tokens[0..index].rindex { |token| token.type == :LBRACE }].prev_code_token
|
139
|
+
end
|
140
|
+
|
141
|
+
# Internal: Find all the Token objects representing the parameter names in
|
142
|
+
# a resource definition.
|
143
|
+
#
|
144
|
+
# resource_tokens - An Array of Token objects that comprise the resource
|
145
|
+
# definition.
|
146
|
+
#
|
147
|
+
# Returns an Array of Token objects.
|
148
|
+
def find_resource_param_tokens(resource_tokens)
|
149
|
+
resource_tokens.select { |token|
|
150
|
+
token.type == :NAME && token.next_code_token.type == :FARROW
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
# Internal: Calculate the positions of all class definitions within the
|
155
|
+
# `tokens` Array.
|
156
|
+
#
|
157
|
+
# Returns an Array of Hashes, each containing:
|
158
|
+
# :start - An Integer position in the `tokens` Array pointing to the
|
159
|
+
# first Token of a class definition.
|
160
|
+
# :end - An Integer position in the `tokens` Array pointing to the last
|
161
|
+
# Token of a class definition.
|
162
|
+
# :tokens - An Array consisting of all the Token objects that make up the
|
163
|
+
# class definition.
|
164
|
+
def class_indexes
|
165
|
+
@class_indexes ||= definition_indexes(:CLASS)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Internal: Calculate the positions of all defined type definitions within
|
169
|
+
# the `tokens` Array.
|
170
|
+
#
|
171
|
+
# Returns an Array of Hashes, each containing:
|
172
|
+
# :start - An Integer position in the `tokens` Array pointing to the
|
173
|
+
# first Token of a defined type definition.
|
174
|
+
# :end - An Integer position in the `tokens` Array pointing to the last
|
175
|
+
# Token of a defined type definition.
|
176
|
+
# :tokens - An Array consisting of all the Token objects that make up the
|
177
|
+
# defined type.
|
178
|
+
def defined_type_indexes
|
179
|
+
@defined_type_indexes ||= definition_indexes(:DEFINE)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Internal: Calculate the positions of all the specified defintion types
|
183
|
+
# within the `tokens` Array.
|
184
|
+
#
|
185
|
+
# Returns an Array of Hashes, each containing:
|
186
|
+
# :start - An Integer position in the `tokens` Array pointing to the
|
187
|
+
# first Token of a definition.
|
188
|
+
# :end - An Integer position in the `tokens` Array pointing to the last
|
189
|
+
# Token of a definition.
|
190
|
+
# :tokens - An Array consisting of all the Token objects that make up the
|
191
|
+
# definition.
|
192
|
+
def definition_indexes(type)
|
193
|
+
result = []
|
194
|
+
tokens.each_with_index do |token, i|
|
195
|
+
if token.type == type
|
196
|
+
brace_depth = 0
|
197
|
+
paren_depth = 0
|
198
|
+
in_params = false
|
199
|
+
inherited_class = nil
|
200
|
+
tokens[i+1..-1].each_with_index do |definition_token, j|
|
201
|
+
case definition_token.type
|
202
|
+
when :INHERITS
|
203
|
+
inherited_class = definition_token.next_code_token
|
204
|
+
when :LPAREN
|
205
|
+
in_params = true if paren_depth == 0
|
206
|
+
paren_depth += 1
|
207
|
+
when :RPAREN
|
208
|
+
in_params = false if paren_depth == 1
|
209
|
+
paren_depth -= 1
|
210
|
+
when :LBRACE
|
211
|
+
brace_depth += 1
|
212
|
+
when :RBRACE
|
213
|
+
brace_depth -= 1
|
214
|
+
if brace_depth == 0 && !in_params
|
215
|
+
if token.next_code_token.type != :LBRACE
|
216
|
+
result << {
|
217
|
+
:start => i,
|
218
|
+
:end => i + j + 1,
|
219
|
+
:tokens => tokens[i..(i + j + 1)],
|
220
|
+
:param_tokens => param_tokens(tokens[i..(i + j + 1)]),
|
221
|
+
:type => type,
|
222
|
+
:name_token => token.next_code_token,
|
223
|
+
:inherited_token => inherited_class,
|
224
|
+
}
|
225
|
+
break
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
result
|
233
|
+
end
|
234
|
+
|
235
|
+
# Internal: Finds all the tokens that make up the defined type or class
|
236
|
+
# definition parameters.
|
237
|
+
#
|
238
|
+
# these_tokens - An Array of PuppetLint::Lexer::Token objects that make up
|
239
|
+
# the defined type or class definition.
|
240
|
+
#
|
241
|
+
# Returns an Array of PuppetLint::Lexer::Token objects or nil if it takes
|
242
|
+
# no parameters.
|
243
|
+
def param_tokens(these_tokens)
|
244
|
+
depth = 0
|
245
|
+
lparen_idx = nil
|
246
|
+
rparen_idx = nil
|
247
|
+
|
248
|
+
these_tokens.each_with_index do |token, i|
|
249
|
+
if token.type == :LPAREN
|
250
|
+
depth += 1
|
251
|
+
lparen_idx = i if depth == 1
|
252
|
+
elsif token.type == :RPAREN
|
253
|
+
depth -= 1
|
254
|
+
if depth == 0
|
255
|
+
rparen_idx = i
|
256
|
+
break
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
if lparen_idx.nil? or rparen_idx.nil?
|
262
|
+
nil
|
263
|
+
else
|
264
|
+
these_tokens[(lparen_idx + 1)..(rparen_idx - 1)]
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# Internal: Retrieves a list of token types that are considered to be
|
269
|
+
# formatting tokens (whitespace, newlines, etc).
|
270
|
+
#
|
271
|
+
# Returns an Array of Symbols.
|
272
|
+
def formatting_tokens
|
273
|
+
@formatting_tokens ||= PuppetLint::Lexer::FORMATTING_TOKENS
|
274
|
+
end
|
275
|
+
|
276
|
+
# Internal: Retrieves a Hash of Sets. Each key is a check name Symbol and
|
277
|
+
# the Set of Integers returned lists all the lines that the check results
|
278
|
+
# should be ignored on.
|
279
|
+
#
|
280
|
+
# Returns a Hash of Sets of Integers.
|
281
|
+
def ignore_overrides
|
282
|
+
@ignore_overrides ||= {}
|
283
|
+
end
|
284
|
+
|
285
|
+
# Internal: Parses all COMMENT, MLCOMMENT and SLASH_COMMENT tokens looking
|
286
|
+
# for control comments (comments that enable or disable checks). Builds the
|
287
|
+
# contents of the `ignore_overrides` hash.
|
288
|
+
#
|
289
|
+
# Returns nothing.
|
290
|
+
def parse_control_comments
|
291
|
+
@ignore_overrides.each_key { |check| @ignore_overrides[check].clear }
|
292
|
+
|
293
|
+
comment_token_types = Set[:COMMENT, :MLCOMMENT, :SLASH_COMMENT]
|
294
|
+
|
295
|
+
comment_tokens = tokens.select { |token|
|
296
|
+
comment_token_types.include?(token.type)
|
297
|
+
}
|
298
|
+
control_comment_tokens = comment_tokens.select { |token|
|
299
|
+
token.value.strip =~ /\Alint:(ignore:[\w\d]+|endignore)/
|
300
|
+
}
|
301
|
+
|
302
|
+
stack = []
|
303
|
+
control_comment_tokens.each do |token|
|
304
|
+
control, reason = token.value.strip.split(' ', 2)
|
305
|
+
split_control = control.split(':')
|
306
|
+
command = split_control[1]
|
307
|
+
|
308
|
+
if command == 'ignore'
|
309
|
+
check = split_control[2].to_sym
|
310
|
+
|
311
|
+
if token.prev_token && !Set[:NEWLINE, :INDENT].include?(token.prev_token.type)
|
312
|
+
# control comment at the end of the line, override applies to
|
313
|
+
# a single line only
|
314
|
+
(ignore_overrides[check] ||= {})[token.line] = reason
|
315
|
+
else
|
316
|
+
stack << [token.line, reason, check]
|
317
|
+
end
|
318
|
+
else
|
319
|
+
start = stack.pop
|
320
|
+
unless start.nil?
|
321
|
+
(start[0]..token.line).each do |i|
|
322
|
+
(ignore_overrides[start[2]] ||= {})[i] = start[1]
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
data/lib/puppet-lint/lexer.rb
CHANGED
@@ -4,6 +4,8 @@ require 'puppet-lint/lexer/token'
|
|
4
4
|
require 'set'
|
5
5
|
|
6
6
|
class PuppetLint
|
7
|
+
# Internal: A generic error thrown by the lexer when it encounters something
|
8
|
+
# it can't handle.
|
7
9
|
class LexerError < StandardError
|
8
10
|
# Internal: Get the Integer line number of the location of the error.
|
9
11
|
attr_reader :line_no
|
@@ -18,16 +20,18 @@ class PuppetLint
|
|
18
20
|
# at when it encountered the error.
|
19
21
|
def initialize(code, offset)
|
20
22
|
chunk = code[0..offset]
|
21
|
-
@line_no = chunk.
|
23
|
+
@line_no = chunk.scan(/(\r\n|\r|\n)/).size + 1
|
22
24
|
if @line_no == 1
|
23
25
|
@column = chunk.length
|
24
26
|
else
|
25
|
-
@column = chunk.length - chunk.rindex(
|
27
|
+
@column = chunk.length - chunk.rindex(/(\r\n|\r|\n)/) - 1
|
26
28
|
end
|
27
29
|
@column = 1 if @column == 0
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
33
|
+
# Internal: The puppet-lint lexer. Converts your manifest into its tokenised
|
34
|
+
# form.
|
31
35
|
class Lexer
|
32
36
|
# Internal: A Hash whose keys are Strings representing reserved keywords in
|
33
37
|
# the Puppet DSL.
|
@@ -109,6 +113,8 @@ class PuppetLint
|
|
109
113
|
[:QMARK, /\A(\?)/],
|
110
114
|
[:BACKSLASH, /\A(\\)/],
|
111
115
|
[:TIMES, /\A(\*)/],
|
116
|
+
[:MODULO, /\A(%)/],
|
117
|
+
[:PIPE, /\A(\|)/],
|
112
118
|
]
|
113
119
|
|
114
120
|
# Internal: A Hash whose keys are Symbols representing token types which
|
@@ -138,8 +144,6 @@ class PuppetLint
|
|
138
144
|
# Raises PuppetLint::LexerError if it encounters unexpected characters
|
139
145
|
# (usually the result of syntax errors).
|
140
146
|
def tokenise(code)
|
141
|
-
code.chomp!
|
142
|
-
|
143
147
|
i = 0
|
144
148
|
|
145
149
|
while i < code.size
|
@@ -165,7 +169,7 @@ class PuppetLint
|
|
165
169
|
end
|
166
170
|
|
167
171
|
unless found
|
168
|
-
if var_name = chunk[/\A\$((::)?([\w-]+::)*[\w-]+)/, 1]
|
172
|
+
if var_name = chunk[/\A\$((::)?([\w-]+::)*[\w-]+(\[.+?\])*)/, 1]
|
169
173
|
tokens << new_token(:VARIABLE, var_name, :chunk => code[0..i])
|
170
174
|
i += var_name.size + 1
|
171
175
|
|
@@ -182,13 +186,13 @@ class PuppetLint
|
|
182
186
|
|
183
187
|
elsif comment = chunk[/\A(#.*)/, 1]
|
184
188
|
comment_size = comment.size
|
185
|
-
comment.sub!(
|
189
|
+
comment.sub!(/#/, '')
|
186
190
|
tokens << new_token(:COMMENT, comment, :chunk => code[0..i])
|
187
191
|
i += comment_size
|
188
192
|
|
189
193
|
elsif slash_comment = chunk[/\A(\/\/.*)/, 1]
|
190
194
|
slash_comment_size = slash_comment.size
|
191
|
-
slash_comment.sub!(
|
195
|
+
slash_comment.sub!(/\/\//, '')
|
192
196
|
tokens << new_token(:SLASH_COMMENT, slash_comment, :chunk => code[0..i])
|
193
197
|
i += slash_comment_size
|
194
198
|
|
@@ -206,18 +210,20 @@ class PuppetLint
|
|
206
210
|
tokens << new_token(:REGEX, str_content[0..-2], :chunk => code[0..i])
|
207
211
|
i += str_content.size + 1
|
208
212
|
|
209
|
-
elsif
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
+
elsif eolindent = chunk[/\A((\r\n|\r|\n)[ \t]+)/m, 1]
|
214
|
+
eol = eolindent[/\A([\r\n]+)/m, 1]
|
215
|
+
indent = eolindent[/\A[\r\n]+([ \t]+)/m, 1]
|
216
|
+
tokens << new_token(:NEWLINE, eol, :chunk => code[0..i])
|
217
|
+
tokens << new_token(:INDENT, indent, :chunk => code[0..i+eol.size])
|
218
|
+
i += indent.size + eol.size
|
213
219
|
|
214
220
|
elsif whitespace = chunk[/\A([ \t]+)/, 1]
|
215
221
|
tokens << new_token(:WHITESPACE, whitespace, :chunk => code[0..i])
|
216
222
|
i += whitespace.size
|
217
223
|
|
218
|
-
elsif chunk
|
219
|
-
tokens << new_token(:NEWLINE,
|
220
|
-
i +=
|
224
|
+
elsif eol = chunk[/\A(\r\n|\r|\n)/, 1]
|
225
|
+
tokens << new_token(:NEWLINE, eol, :chunk => code[0..i])
|
226
|
+
i += eol.size
|
221
227
|
|
222
228
|
elsif chunk.match(/\A\//)
|
223
229
|
tokens << new_token(:DIV, '/', :chunk => code[0..i])
|
@@ -265,11 +271,11 @@ class PuppetLint
|
|
265
271
|
# Returns the instantiated PuppetLint::Lexer::Token object.
|
266
272
|
def new_token(type, value, opts = {})
|
267
273
|
if opts[:chunk]
|
268
|
-
line_no = opts[:chunk].
|
274
|
+
line_no = opts[:chunk].scan(/(\r\n|\r|\n)/).size + 1
|
269
275
|
if line_no == 1
|
270
276
|
column = opts[:chunk].length
|
271
277
|
else
|
272
|
-
column = opts[:chunk].length - opts[:chunk].rindex(
|
278
|
+
column = opts[:chunk].length - opts[:chunk].rindex(/(\r\n|\r|\n)/) - 1
|
273
279
|
end
|
274
280
|
column += 1 if column == 0
|
275
281
|
else
|
@@ -330,7 +336,7 @@ class PuppetLint
|
|
330
336
|
tokens << new_token(:STRING, value, :line => line, :column => column)
|
331
337
|
first = false
|
332
338
|
else
|
333
|
-
line += value.
|
339
|
+
line += value.scan(/(\r\n|\r|\n)/).size
|
334
340
|
token_column = column + (ss.pos - value.size)
|
335
341
|
tokens << new_token(:DQPOST, value, :line => line, :column => token_column)
|
336
342
|
end
|
@@ -339,29 +345,30 @@ class PuppetLint
|
|
339
345
|
tokens << new_token(:DQPRE, value, :line => line, :column => column)
|
340
346
|
first = false
|
341
347
|
else
|
342
|
-
line += value.
|
348
|
+
line += value.scan(/(\r\n|\r|\n)/).size
|
343
349
|
token_column = column + (ss.pos - value.size)
|
344
350
|
tokens << new_token(:DQMID, value, :line => line, :column => token_column)
|
345
351
|
end
|
346
352
|
if ss.scan(/\{/).nil?
|
347
353
|
var_name = ss.scan(/(::)?([\w-]+::)*[\w-]+/)
|
348
|
-
|
354
|
+
if var_name.nil?
|
355
|
+
token_column = column + ss.pos - 1
|
356
|
+
tokens << new_token(:DQMID, "$", :line => line, :column => token_column)
|
357
|
+
else
|
349
358
|
token_column = column + (ss.pos - var_name.size)
|
350
359
|
tokens << new_token(:UNENC_VARIABLE, var_name, :line => line, :column => token_column)
|
351
360
|
end
|
352
361
|
else
|
353
362
|
contents = ss.scan_until(/\}/)[0..-2]
|
354
|
-
if contents.match(/\A(::)?([\w-]+::)*[\w-]
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
tokens << new_token(token.type, token.value, :line => tok_line, :column => tok_col)
|
364
|
-
end
|
363
|
+
if contents.match(/\A(::)?([\w-]+::)*[\w-]+(\[.+?\])*/)
|
364
|
+
contents = "$#{contents}"
|
365
|
+
end
|
366
|
+
lexer = PuppetLint::Lexer.new
|
367
|
+
lexer.tokenise(contents)
|
368
|
+
lexer.tokens.each do |token|
|
369
|
+
tok_col = column + token.column + (ss.pos - contents.size - 1)
|
370
|
+
tok_line = token.line + line - 1
|
371
|
+
tokens << new_token(token.type, token.value, :line => tok_line, :column => tok_col)
|
365
372
|
end
|
366
373
|
end
|
367
374
|
end
|