halyard-puppet-lint 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +7 -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
|