puppet-lint-halyard 1.1.0.1
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 +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +10 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +210 -0
- data/Rakefile +14 -0
- data/bin/puppet-lint +7 -0
- data/lib/puppet-lint.rb +214 -0
- data/lib/puppet-lint/bin.rb +79 -0
- data/lib/puppet-lint/checkplugin.rb +176 -0
- data/lib/puppet-lint/checks.rb +91 -0
- data/lib/puppet-lint/configuration.rb +153 -0
- data/lib/puppet-lint/data.rb +521 -0
- data/lib/puppet-lint/lexer.rb +373 -0
- data/lib/puppet-lint/lexer/token.rb +101 -0
- data/lib/puppet-lint/monkeypatches.rb +2 -0
- data/lib/puppet-lint/monkeypatches/string_percent.rb +52 -0
- data/lib/puppet-lint/monkeypatches/string_prepend.rb +13 -0
- data/lib/puppet-lint/optparser.rb +118 -0
- data/lib/puppet-lint/plugins.rb +74 -0
- data/lib/puppet-lint/plugins/check_classes.rb +285 -0
- data/lib/puppet-lint/plugins/check_comments.rb +55 -0
- data/lib/puppet-lint/plugins/check_conditionals.rb +65 -0
- data/lib/puppet-lint/plugins/check_documentation.rb +31 -0
- data/lib/puppet-lint/plugins/check_nodes.rb +29 -0
- data/lib/puppet-lint/plugins/check_resources.rb +194 -0
- data/lib/puppet-lint/plugins/check_strings.rb +174 -0
- data/lib/puppet-lint/plugins/check_variables.rb +19 -0
- data/lib/puppet-lint/plugins/check_whitespace.rb +170 -0
- data/lib/puppet-lint/tasks/puppet-lint.rb +91 -0
- data/lib/puppet-lint/version.rb +3 -0
- data/puppet-lint.gemspec +24 -0
- data/spec/fixtures/test/manifests/fail.pp +2 -0
- data/spec/fixtures/test/manifests/ignore.pp +1 -0
- data/spec/fixtures/test/manifests/ignore_multiple_block.pp +6 -0
- data/spec/fixtures/test/manifests/ignore_multiple_line.pp +2 -0
- data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
- data/spec/fixtures/test/manifests/init.pp +3 -0
- data/spec/fixtures/test/manifests/malformed.pp +1 -0
- data/spec/fixtures/test/manifests/url_interpolation.pp +12 -0
- data/spec/fixtures/test/manifests/warning.pp +2 -0
- data/spec/puppet-lint/bin_spec.rb +326 -0
- data/spec/puppet-lint/configuration_spec.rb +56 -0
- data/spec/puppet-lint/ignore_overrides_spec.rb +109 -0
- data/spec/puppet-lint/lexer/token_spec.rb +18 -0
- data/spec/puppet-lint/lexer_spec.rb +783 -0
- data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +105 -0
- data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +35 -0
- data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +33 -0
- data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +45 -0
- data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +76 -0
- data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +73 -0
- data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +25 -0
- data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +196 -0
- data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +45 -0
- data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +84 -0
- data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +98 -0
- data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +36 -0
- data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +52 -0
- data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +146 -0
- data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +100 -0
- data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +55 -0
- data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +89 -0
- data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +113 -0
- data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +45 -0
- data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +216 -0
- data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +199 -0
- data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +114 -0
- data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +62 -0
- data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +129 -0
- data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +17 -0
- data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +73 -0
- data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +37 -0
- data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +21 -0
- data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +54 -0
- data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +524 -0
- data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +45 -0
- data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +101 -0
- data/spec/puppet-lint_spec.rb +20 -0
- data/spec/spec_helper.rb +129 -0
- metadata +229 -0
@@ -0,0 +1,373 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'strscan'
|
3
|
+
require 'puppet-lint/lexer/token'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
class PuppetLint
|
7
|
+
# Internal: A generic error thrown by the lexer when it encounters something
|
8
|
+
# it can't handle.
|
9
|
+
class LexerError < StandardError
|
10
|
+
# Internal: Get the Integer line number of the location of the error.
|
11
|
+
attr_reader :line_no
|
12
|
+
|
13
|
+
# Internal: Get the Integer column number of the location of the error.
|
14
|
+
attr_reader :column
|
15
|
+
|
16
|
+
# Internal: Initialise a new PuppetLint::LexerError object.
|
17
|
+
#
|
18
|
+
# line_no - The Integer line number of the location of the error.
|
19
|
+
# column - The Integer column number of the location of the error.
|
20
|
+
def initialize(line_no, column)
|
21
|
+
@line_no = line_no
|
22
|
+
@column = column
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Internal: The puppet-lint lexer. Converts your manifest into its tokenised
|
27
|
+
# form.
|
28
|
+
class Lexer
|
29
|
+
def initialize
|
30
|
+
@line_no = 1
|
31
|
+
@column = 1
|
32
|
+
end
|
33
|
+
|
34
|
+
# Internal: A Hash whose keys are Strings representing reserved keywords in
|
35
|
+
# the Puppet DSL.
|
36
|
+
KEYWORDS = {
|
37
|
+
'class' => true,
|
38
|
+
'case' => true,
|
39
|
+
'default' => true,
|
40
|
+
'define' => true,
|
41
|
+
'import' => true,
|
42
|
+
'if' => true,
|
43
|
+
'else' => true,
|
44
|
+
'elsif' => true,
|
45
|
+
'inherits' => true,
|
46
|
+
'node' => true,
|
47
|
+
'and' => true,
|
48
|
+
'or' => true,
|
49
|
+
'undef' => true,
|
50
|
+
'true' => true,
|
51
|
+
'false' => true,
|
52
|
+
'in' => true,
|
53
|
+
'unless' => true,
|
54
|
+
}
|
55
|
+
|
56
|
+
# Internal: A Hash whose keys are Symbols representing token types which
|
57
|
+
# a regular expression can follow.
|
58
|
+
REGEX_PREV_TOKENS = {
|
59
|
+
:NODE => true,
|
60
|
+
:LBRACE => true,
|
61
|
+
:RBRACE => true,
|
62
|
+
:MATCH => true,
|
63
|
+
:NOMATCH => true,
|
64
|
+
:COMMA => true,
|
65
|
+
}
|
66
|
+
|
67
|
+
# Internal: An Array of Arrays containing tokens that can be described by
|
68
|
+
# a single regular expression. Each sub-Array contains 2 elements, the
|
69
|
+
# name of the token as a Symbol and a regular expression describing the
|
70
|
+
# value of the token.
|
71
|
+
KNOWN_TOKENS = [
|
72
|
+
[:CLASSREF, /\A(((::){0,1}[A-Z][-\w]*)+)/],
|
73
|
+
[:NUMBER, /\A\b((?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?))\b/],
|
74
|
+
[:NAME, /\A(((::)?[a-z0-9][-\w]*)(::[a-z0-9][-\w]*)*)/],
|
75
|
+
[:LBRACK, /\A(\[)/],
|
76
|
+
[:RBRACK, /\A(\])/],
|
77
|
+
[:LBRACE, /\A(\{)/],
|
78
|
+
[:RBRACE, /\A(\})/],
|
79
|
+
[:LPAREN, /\A(\()/],
|
80
|
+
[:RPAREN, /\A(\))/],
|
81
|
+
[:ISEQUAL, /\A(==)/],
|
82
|
+
[:MATCH, /\A(=~)/],
|
83
|
+
[:FARROW, /\A(=>)/],
|
84
|
+
[:EQUALS, /\A(=)/],
|
85
|
+
[:APPENDS, /\A(\+=)/],
|
86
|
+
[:PARROW, /\A(\+>)/],
|
87
|
+
[:PLUS, /\A(\+)/],
|
88
|
+
[:GREATEREQUAL, /\A(>=)/],
|
89
|
+
[:RSHIFT, /\A(>>)/],
|
90
|
+
[:GREATERTHAN, /\A(>)/],
|
91
|
+
[:LESSEQUAL, /\A(<=)/],
|
92
|
+
[:LLCOLLECT, /\A(<<\|)/],
|
93
|
+
[:OUT_EDGE, /\A(<-)/],
|
94
|
+
[:OUT_EDGE_SUB, /\A(<~)/],
|
95
|
+
[:LCOLLECT, /\A(<\|)/],
|
96
|
+
[:LSHIFT, /\A(<<)/],
|
97
|
+
[:LESSTHAN, /\A(<)/],
|
98
|
+
[:NOMATCH, /\A(!~)/],
|
99
|
+
[:NOTEQUAL, /\A(!=)/],
|
100
|
+
[:NOT, /\A(!)/],
|
101
|
+
[:RRCOLLECT, /\A(\|>>)/],
|
102
|
+
[:RCOLLECT, /\A(\|>)/],
|
103
|
+
[:IN_EDGE, /\A(->)/],
|
104
|
+
[:IN_EDGE_SUB, /\A(~>)/],
|
105
|
+
[:MINUS, /\A(-)/],
|
106
|
+
[:COMMA, /\A(,)/],
|
107
|
+
[:DOT, /\A(\.)/],
|
108
|
+
[:COLON, /\A(:)/],
|
109
|
+
[:AT, /\A(@)/],
|
110
|
+
[:SEMIC, /\A(;)/],
|
111
|
+
[:QMARK, /\A(\?)/],
|
112
|
+
[:BACKSLASH, /\A(\\)/],
|
113
|
+
[:TIMES, /\A(\*)/],
|
114
|
+
[:MODULO, /\A(%)/],
|
115
|
+
[:PIPE, /\A(\|)/],
|
116
|
+
]
|
117
|
+
|
118
|
+
# Internal: A Hash whose keys are Symbols representing token types which
|
119
|
+
# are considered to be formatting tokens (i.e. tokens that don't contain
|
120
|
+
# code).
|
121
|
+
FORMATTING_TOKENS = {
|
122
|
+
:WHITESPACE => true,
|
123
|
+
:NEWLINE => true,
|
124
|
+
:COMMENT => true,
|
125
|
+
:MLCOMMENT => true,
|
126
|
+
:SLASH_COMMENT => true,
|
127
|
+
:INDENT => true,
|
128
|
+
}
|
129
|
+
|
130
|
+
# Internal: Access the internal token storage.
|
131
|
+
#
|
132
|
+
# Returns an Array of PuppetLint::Lexer::Toxen objects.
|
133
|
+
def tokens
|
134
|
+
@tokens ||= []
|
135
|
+
end
|
136
|
+
|
137
|
+
# Internal: Convert a Puppet manifest into tokens.
|
138
|
+
#
|
139
|
+
# code - The Puppet manifest to be tokenised as a String.
|
140
|
+
#
|
141
|
+
# Returns an Array of PuppetLint::Lexer::Token objects.
|
142
|
+
# Raises PuppetLint::LexerError if it encounters unexpected characters
|
143
|
+
# (usually the result of syntax errors).
|
144
|
+
def tokenise(code)
|
145
|
+
i = 0
|
146
|
+
|
147
|
+
while i < code.size
|
148
|
+
chunk = code[i..-1]
|
149
|
+
|
150
|
+
found = false
|
151
|
+
|
152
|
+
KNOWN_TOKENS.each do |type, regex|
|
153
|
+
if value = chunk[regex, 1]
|
154
|
+
length = value.size
|
155
|
+
if type == :NAME
|
156
|
+
if KEYWORDS.include? value
|
157
|
+
tokens << new_token(value.upcase.to_sym, value, length)
|
158
|
+
else
|
159
|
+
tokens << new_token(type, value, length)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
tokens << new_token(type, value, length)
|
163
|
+
end
|
164
|
+
i += length
|
165
|
+
found = true
|
166
|
+
break
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
unless found
|
171
|
+
if var_name = chunk[/\A\$((::)?([\w-]+::)*[\w-]+(\[.+?\])*)/, 1]
|
172
|
+
length = var_name.size + 1
|
173
|
+
tokens << new_token(:VARIABLE, var_name, length)
|
174
|
+
|
175
|
+
elsif chunk.match(/\A'(.*?)'/m)
|
176
|
+
str_content = StringScanner.new(code[i+1..-1]).scan_until(/(\A|[^\\])(\\\\)*'/m)
|
177
|
+
length = str_content.size + 1
|
178
|
+
tokens << new_token(:SSTRING, str_content[0..-2], length)
|
179
|
+
|
180
|
+
elsif chunk.match(/\A"/)
|
181
|
+
str_contents = StringScanner.new(code[i+1..-1]).scan_until(/(\A|[^\\])(\\\\)*"/m)
|
182
|
+
_ = code[0..i].split("\n")
|
183
|
+
interpolate_string(str_contents, _.count, _.last.length)
|
184
|
+
length = str_contents.size + 1
|
185
|
+
|
186
|
+
elsif comment = chunk[/\A(#.*)/, 1]
|
187
|
+
length = comment.size
|
188
|
+
comment.sub!(/#/, '')
|
189
|
+
tokens << new_token(:COMMENT, comment, length)
|
190
|
+
|
191
|
+
elsif slash_comment = chunk[/\A(\/\/.*)/, 1]
|
192
|
+
length = slash_comment.size
|
193
|
+
slash_comment.sub!(/\/\//, '')
|
194
|
+
tokens << new_token(:SLASH_COMMENT, slash_comment, length)
|
195
|
+
|
196
|
+
elsif mlcomment = chunk[/\A(\/\*.*?\*\/)/m, 1]
|
197
|
+
length = mlcomment.size
|
198
|
+
mlcomment_raw = mlcomment.dup
|
199
|
+
mlcomment.sub!(/\A\/\* ?/, '')
|
200
|
+
mlcomment.sub!(/ ?\*\/\Z/, '')
|
201
|
+
mlcomment.gsub!(/^ *\*/, '')
|
202
|
+
tokens << new_token(:MLCOMMENT, mlcomment, length)
|
203
|
+
tokens.last.raw = mlcomment_raw
|
204
|
+
|
205
|
+
elsif chunk.match(/\A\/.*?\//) && possible_regex?
|
206
|
+
str_content = StringScanner.new(code[i+1..-1]).scan_until(/(\A|[^\\])(\\\\)*\//m)
|
207
|
+
length = str_content.size + 1
|
208
|
+
tokens << new_token(:REGEX, str_content[0..-2], length)
|
209
|
+
|
210
|
+
elsif eolindent = chunk[/\A((\r\n|\r|\n)[ \t]+)/m, 1]
|
211
|
+
eol = eolindent[/\A([\r\n]+)/m, 1]
|
212
|
+
indent = eolindent[/\A[\r\n]+([ \t]+)/m, 1]
|
213
|
+
tokens << new_token(:NEWLINE, eol, eol.size)
|
214
|
+
tokens << new_token(:INDENT, indent, indent.size)
|
215
|
+
length = indent.size + eol.size
|
216
|
+
|
217
|
+
elsif whitespace = chunk[/\A([ \t]+)/, 1]
|
218
|
+
length = whitespace.size
|
219
|
+
tokens << new_token(:WHITESPACE, whitespace, length)
|
220
|
+
|
221
|
+
elsif eol = chunk[/\A(\r\n|\r|\n)/, 1]
|
222
|
+
length = eol.size
|
223
|
+
tokens << new_token(:NEWLINE, eol, length)
|
224
|
+
|
225
|
+
elsif chunk.match(/\A\//)
|
226
|
+
length = 1
|
227
|
+
tokens << new_token(:DIV, '/', length)
|
228
|
+
|
229
|
+
else
|
230
|
+
raise PuppetLint::LexerError.new(@line_no, @column)
|
231
|
+
end
|
232
|
+
|
233
|
+
i += length
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
tokens
|
238
|
+
end
|
239
|
+
|
240
|
+
# Internal: Given the tokens already processed, determine if the next token
|
241
|
+
# could be a regular expression.
|
242
|
+
#
|
243
|
+
# Returns true if the next token could be a regex, otherwise return false.
|
244
|
+
def possible_regex?
|
245
|
+
prev_token = tokens.reject { |r|
|
246
|
+
FORMATTING_TOKENS.include? r.type
|
247
|
+
}.last
|
248
|
+
|
249
|
+
return true if prev_token.nil?
|
250
|
+
|
251
|
+
if REGEX_PREV_TOKENS.include? prev_token.type
|
252
|
+
true
|
253
|
+
else
|
254
|
+
false
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# Internal: Create a new PuppetLint::Lexer::Token object, calculate its
|
259
|
+
# line number and column and then add it to the Linked List of tokens.
|
260
|
+
#
|
261
|
+
# type - The Symbol token type.
|
262
|
+
# value - The token value.
|
263
|
+
# length - The Integer length of the token's value.
|
264
|
+
# opts - A Hash of additional values required to determine line number and
|
265
|
+
# column:
|
266
|
+
# :line - The Integer line number if calculated externally.
|
267
|
+
# :column - The Integer column number if calculated externally.
|
268
|
+
#
|
269
|
+
# Returns the instantiated PuppetLint::Lexer::Token object.
|
270
|
+
def new_token(type, value, length, opts = {})
|
271
|
+
column = opts[:column] || @column
|
272
|
+
line_no = opts[:line] || @line_no
|
273
|
+
|
274
|
+
token = Token.new(type, value, line_no, column)
|
275
|
+
unless tokens.last.nil?
|
276
|
+
token.prev_token = tokens.last
|
277
|
+
tokens.last.next_token = token
|
278
|
+
|
279
|
+
unless FORMATTING_TOKENS.include?(token.type)
|
280
|
+
prev_nf_idx = tokens.rindex { |r| ! FORMATTING_TOKENS.include? r.type }
|
281
|
+
unless prev_nf_idx.nil?
|
282
|
+
prev_nf_token = tokens[prev_nf_idx]
|
283
|
+
prev_nf_token.next_code_token = token
|
284
|
+
token.prev_code_token = prev_nf_token
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
@column += length
|
290
|
+
if type == :NEWLINE
|
291
|
+
@line_no += 1
|
292
|
+
@column = 1
|
293
|
+
end
|
294
|
+
|
295
|
+
token
|
296
|
+
end
|
297
|
+
|
298
|
+
# Internal: Split a string on multiple terminators, excluding escaped
|
299
|
+
# terminators.
|
300
|
+
#
|
301
|
+
# string - The String to be split.
|
302
|
+
# terminators - The String of terminators that the String should be split
|
303
|
+
# on.
|
304
|
+
#
|
305
|
+
# Returns an Array consisting of two Strings, the String up to the first
|
306
|
+
# terminator and the terminator that was found.
|
307
|
+
def get_string_segment(string, terminators)
|
308
|
+
str = string.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]+/)
|
309
|
+
begin
|
310
|
+
[str[0..-2], str[-1,1]]
|
311
|
+
rescue
|
312
|
+
[nil, nil]
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
# Internal: Tokenise the contents of a double quoted string.
|
317
|
+
#
|
318
|
+
# string - The String to be tokenised.
|
319
|
+
# line - The Integer line number of the start of the passed string.
|
320
|
+
# column - The Integer column number of the start of the passed string.
|
321
|
+
#
|
322
|
+
# Returns nothing.
|
323
|
+
def interpolate_string(string, line, column)
|
324
|
+
ss = StringScanner.new(string)
|
325
|
+
first = true
|
326
|
+
value, terminator = get_string_segment(ss, '"$')
|
327
|
+
until value.nil?
|
328
|
+
if terminator == "\""
|
329
|
+
if first
|
330
|
+
tokens << new_token(:STRING, value, value.size + 2, :line => line, :column => column)
|
331
|
+
first = false
|
332
|
+
else
|
333
|
+
line += value.scan(/(\r\n|\r|\n)/).size
|
334
|
+
token_column = column + (ss.pos - value.size)
|
335
|
+
tokens << new_token(:DQPOST, value, value.size + 1, :line => line, :column => token_column)
|
336
|
+
end
|
337
|
+
else
|
338
|
+
if first
|
339
|
+
tokens << new_token(:DQPRE, value, value.size + 1, :line => line, :column => column)
|
340
|
+
first = false
|
341
|
+
else
|
342
|
+
line += value.scan(/(\r\n|\r|\n)/).size
|
343
|
+
token_column = column + (ss.pos - value.size)
|
344
|
+
tokens << new_token(:DQMID, value, value.size, :line => line, :column => token_column)
|
345
|
+
end
|
346
|
+
if ss.scan(/\{/).nil?
|
347
|
+
var_name = ss.scan(/(::)?([\w-]+::)*[\w-]+/)
|
348
|
+
if var_name.nil?
|
349
|
+
token_column = column + ss.pos - 1
|
350
|
+
tokens << new_token(:DQMID, "$", 1, :line => line, :column => token_column)
|
351
|
+
else
|
352
|
+
token_column = column + (ss.pos - var_name.size)
|
353
|
+
tokens << new_token(:UNENC_VARIABLE, var_name, var_name.size, :line => line, :column => token_column)
|
354
|
+
end
|
355
|
+
else
|
356
|
+
contents = ss.scan_until(/\}/)[0..-2]
|
357
|
+
if contents.match(/\A(::)?([\w-]+::)*[\w-]+(\[.+?\])*/)
|
358
|
+
contents = "$#{contents}"
|
359
|
+
end
|
360
|
+
lexer = PuppetLint::Lexer.new
|
361
|
+
lexer.tokenise(contents)
|
362
|
+
lexer.tokens.each do |token|
|
363
|
+
tok_col = column + token.column + (ss.pos - contents.size - 1)
|
364
|
+
tok_line = token.line + line - 1
|
365
|
+
tokens << new_token(token.type, token.value, token.value.size, :line => tok_line, :column => tok_col)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
value, terminator = get_string_segment(ss, '"$')
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
class PuppetLint
|
2
|
+
class Lexer
|
3
|
+
# Public: Stores a fragment of the manifest and the information about its
|
4
|
+
# location in the manifest.
|
5
|
+
class Token
|
6
|
+
# Public: Returns the Symbol type of the Token.
|
7
|
+
attr_accessor :type
|
8
|
+
|
9
|
+
# Public: Returns the String value of the Token.
|
10
|
+
attr_accessor :value
|
11
|
+
|
12
|
+
# Public: Returns the raw value of the Token.
|
13
|
+
attr_accessor :raw
|
14
|
+
|
15
|
+
# Public: Returns the Integer line number of the manifest text where
|
16
|
+
# the Token can be found.
|
17
|
+
attr_reader :line
|
18
|
+
|
19
|
+
# Public: Returns the Integer column number of the line of the manifest
|
20
|
+
# text where the Token can be found.
|
21
|
+
attr_reader :column
|
22
|
+
|
23
|
+
# Public: Gets/sets the next token in the manifest.
|
24
|
+
attr_accessor :next_token
|
25
|
+
|
26
|
+
# Public: Gets/sets the previous token in the manifest.
|
27
|
+
attr_accessor :prev_token
|
28
|
+
|
29
|
+
# Public: Gets/sets the next code token (skips whitespace, comments,
|
30
|
+
# etc) in the manifest.
|
31
|
+
attr_accessor :next_code_token
|
32
|
+
|
33
|
+
# Public: Gets/sets the previous code tokne (skips whitespace,
|
34
|
+
# comments, etc) in the manifest.
|
35
|
+
attr_accessor :prev_code_token
|
36
|
+
|
37
|
+
# Public: Initialise a new Token object.
|
38
|
+
#
|
39
|
+
# type - An upper case Symbol describing the type of Token.
|
40
|
+
# value - The String value of the Token.
|
41
|
+
# line - The Integer line number where the Token can be found in the
|
42
|
+
# manifest.
|
43
|
+
# column - The Integer number of characters from the start of the line to
|
44
|
+
# the start of the Token.
|
45
|
+
#
|
46
|
+
# Returns the instantiated Token.
|
47
|
+
def initialize(type, value, line, column)
|
48
|
+
@value = value
|
49
|
+
@type = type
|
50
|
+
@line = line
|
51
|
+
@column = column
|
52
|
+
@next_token = nil
|
53
|
+
@prev_token = nil
|
54
|
+
@next_code_token = nil
|
55
|
+
@prev_code_token = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Produce a human friendly description of the Token when
|
59
|
+
# inspected.
|
60
|
+
#
|
61
|
+
# Returns a String describing the Token.
|
62
|
+
def inspect
|
63
|
+
"<Token #{@type.inspect} (#{@value}) @#{@line}:#{@column}>"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Public: Produce a Puppet DSL representation of a Token.
|
67
|
+
#
|
68
|
+
# Returns a Puppet DSL String.
|
69
|
+
def to_manifest
|
70
|
+
case @type
|
71
|
+
when :STRING
|
72
|
+
"\"#{@value}\""
|
73
|
+
when :SSTRING
|
74
|
+
"'#{@value}'"
|
75
|
+
when :DQPRE
|
76
|
+
"\"#{@value}"
|
77
|
+
when :DQPOST
|
78
|
+
"#{@value}\""
|
79
|
+
when :VARIABLE
|
80
|
+
if !@prev_code_token.nil? && [:DQPRE, :DQMID].include?(@prev_code_token.type)
|
81
|
+
"${#{@value}}"
|
82
|
+
else
|
83
|
+
"$#{@value}"
|
84
|
+
end
|
85
|
+
when :UNENC_VARIABLE
|
86
|
+
"$#{@value}"
|
87
|
+
when :NEWLINE
|
88
|
+
"\n"
|
89
|
+
when :COMMENT
|
90
|
+
"##{@value}"
|
91
|
+
when :REGEX
|
92
|
+
"/#{@value}/"
|
93
|
+
when :MLCOMMENT
|
94
|
+
@raw
|
95
|
+
else
|
96
|
+
@value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|