puppet-lint 2.3.0 → 2.3.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 +4 -4
- data/.rubocop.yml +74 -0
- data/.rubocop_todo.yml +89 -0
- data/.travis.yml +11 -9
- data/CHANGELOG.md +54 -0
- data/Gemfile +3 -0
- data/Rakefile +14 -3
- data/appveyor.yml +1 -4
- data/bin/puppet-lint +1 -1
- data/lib/puppet-lint.rb +25 -21
- data/lib/puppet-lint/bin.rb +15 -19
- data/lib/puppet-lint/checkplugin.rb +24 -17
- data/lib/puppet-lint/checks.rb +42 -31
- data/lib/puppet-lint/configuration.rb +11 -8
- data/lib/puppet-lint/data.rb +236 -164
- data/lib/puppet-lint/lexer.rb +225 -203
- data/lib/puppet-lint/lexer/token.rb +34 -18
- data/lib/puppet-lint/optparser.rb +33 -30
- data/lib/puppet-lint/plugins.rb +42 -38
- data/lib/puppet-lint/plugins/check_classes/arrow_on_right_operand_line.rb +26 -28
- data/lib/puppet-lint/plugins/check_classes/autoloader_layout.rb +21 -20
- data/lib/puppet-lint/plugins/check_classes/class_inherits_from_params_class.rb +8 -9
- data/lib/puppet-lint/plugins/check_classes/code_on_top_scope.rb +9 -8
- data/lib/puppet-lint/plugins/check_classes/inherits_across_namespaces.rb +12 -11
- data/lib/puppet-lint/plugins/check_classes/names_containing_dash.rb +13 -12
- data/lib/puppet-lint/plugins/check_classes/names_containing_uppercase.rb +14 -13
- data/lib/puppet-lint/plugins/check_classes/nested_classes_or_defines.rb +9 -10
- data/lib/puppet-lint/plugins/check_classes/parameter_order.rb +40 -31
- data/lib/puppet-lint/plugins/check_classes/right_to_left_relationship.rb +3 -2
- data/lib/puppet-lint/plugins/check_classes/variable_scope.rb +21 -24
- data/lib/puppet-lint/plugins/check_comments/slash_comments.rb +3 -2
- data/lib/puppet-lint/plugins/check_comments/star_comments.rb +6 -5
- data/lib/puppet-lint/plugins/check_conditionals/case_without_default.rb +21 -20
- data/lib/puppet-lint/plugins/check_conditionals/selector_inside_resource.rb +10 -13
- data/lib/puppet-lint/plugins/check_documentation/documentation.rb +26 -17
- data/lib/puppet-lint/plugins/check_nodes/unquoted_node_name.rb +11 -11
- data/lib/puppet-lint/plugins/check_resources/duplicate_params.rb +4 -3
- data/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb +17 -18
- data/lib/puppet-lint/plugins/check_resources/ensure_not_symlink_target.rb +17 -16
- data/lib/puppet-lint/plugins/check_resources/file_mode.rb +22 -23
- data/lib/puppet-lint/plugins/check_resources/unquoted_file_mode.rb +14 -13
- data/lib/puppet-lint/plugins/check_resources/unquoted_resource_title.rb +9 -8
- data/lib/puppet-lint/plugins/check_strings/double_quoted_strings.rb +8 -8
- data/lib/puppet-lint/plugins/check_strings/only_variable_string.rb +29 -42
- data/lib/puppet-lint/plugins/check_strings/puppet_url_without_modules.rb +5 -4
- data/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb +3 -2
- data/lib/puppet-lint/plugins/check_strings/single_quote_string_with_variables.rb +4 -3
- data/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb +3 -2
- data/lib/puppet-lint/plugins/check_variables/variable_contains_dash.rb +9 -8
- data/lib/puppet-lint/plugins/check_variables/variable_is_lowercase.rb +9 -8
- data/lib/puppet-lint/plugins/check_whitespace/140chars.rb +9 -9
- data/lib/puppet-lint/plugins/check_whitespace/2sp_soft_tabs.rb +4 -3
- data/lib/puppet-lint/plugins/check_whitespace/80chars.rb +10 -10
- data/lib/puppet-lint/plugins/check_whitespace/arrow_alignment.rb +23 -22
- data/lib/puppet-lint/plugins/check_whitespace/hard_tabs.rb +3 -2
- data/lib/puppet-lint/plugins/check_whitespace/trailing_whitespace.rb +3 -2
- data/lib/puppet-lint/tasks/puppet-lint.rb +3 -3
- data/lib/puppet-lint/version.rb +1 -1
- data/puppet-lint.gemspec +4 -4
- data/spec/puppet-lint/bin_spec.rb +268 -140
- data/spec/puppet-lint/checks_spec.rb +229 -0
- data/spec/puppet-lint/configuration_spec.rb +10 -9
- data/spec/puppet-lint/data_spec.rb +84 -0
- data/spec/puppet-lint/ignore_overrides_spec.rb +71 -40
- data/spec/puppet-lint/lexer/token_spec.rb +1 -1
- data/spec/puppet-lint/lexer_spec.rb +306 -73
- data/spec/puppet-lint/plugins/check_classes/arrow_on_right_operand_line_spec.rb +12 -6
- data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +10 -10
- data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +15 -11
- data/spec/puppet-lint/plugins/check_classes/code_on_top_scope_spec.rb +26 -21
- data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +3 -3
- data/spec/puppet-lint/plugins/check_classes/name_contains_uppercase_spec.rb +4 -5
- data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +13 -0
- data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +33 -25
- data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +80 -55
- data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +2 -2
- data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +165 -130
- data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +2 -2
- data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +53 -35
- data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +59 -49
- data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +18 -14
- data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +14 -10
- data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +7 -7
- data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +54 -44
- data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +114 -89
- data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +41 -30
- data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +46 -40
- data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +46 -40
- data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +95 -71
- data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +28 -24
- data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +11 -9
- data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +1 -2
- data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +18 -14
- data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +1 -1
- data/spec/puppet-lint/plugins/check_variables/variable_is_lowercase_spec.rb +1 -1
- data/spec/puppet-lint/plugins/check_whitespace/140chars_spec.rb +22 -15
- data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +8 -6
- data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +23 -29
- data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +588 -494
- data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +1 -1
- data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +27 -19
- data/spec/puppet-lint_spec.rb +2 -12
- data/spec/spec_helper.rb +35 -30
- metadata +6 -5
- data/lib/puppet-lint/monkeypatches.rb +0 -2
- data/lib/puppet-lint/monkeypatches/string_percent.rb +0 -52
- data/lib/puppet-lint/monkeypatches/string_prepend.rb +0 -13
data/lib/puppet-lint/lexer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'pp'
|
2
4
|
require 'strscan'
|
3
5
|
require 'puppet-lint/lexer/token'
|
@@ -13,23 +15,35 @@ class PuppetLint
|
|
13
15
|
# Internal: Get the Integer column number of the location of the error.
|
14
16
|
attr_reader :column
|
15
17
|
|
18
|
+
# Internal: Get the String reason for the error (if known).
|
19
|
+
attr_reader :reason
|
20
|
+
|
16
21
|
# Internal: Initialise a new PuppetLint::LexerError object.
|
17
22
|
#
|
18
23
|
# line_no - The Integer line number of the location of the error.
|
19
24
|
# column - The Integer column number of the location of the error.
|
20
|
-
|
25
|
+
# reason - A String describing the cause of the error (if known).
|
26
|
+
def initialize(line_no, column, reason = nil)
|
21
27
|
@line_no = line_no
|
22
28
|
@column = column
|
29
|
+
@reason = reason
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
26
33
|
# Internal: The puppet-lint lexer. Converts your manifest into its tokenised
|
27
34
|
# form.
|
28
|
-
class Lexer
|
35
|
+
class Lexer # rubocop:disable Metrics/ClassLength
|
29
36
|
def initialize
|
30
37
|
@line_no = 1
|
31
38
|
@column = 1
|
32
|
-
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.heredoc_queue
|
42
|
+
@heredoc_queue ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def heredoc_queue
|
46
|
+
self.class.heredoc_queue
|
33
47
|
end
|
34
48
|
|
35
49
|
# Internal: A Hash whose keys are Strings representing reserved keywords in
|
@@ -58,8 +72,8 @@ class PuppetLint
|
|
58
72
|
'type' => true,
|
59
73
|
'attr' => true,
|
60
74
|
'private' => true,
|
61
|
-
}
|
62
|
-
|
75
|
+
}.freeze
|
76
|
+
|
63
77
|
# Internal: A Hash whose keys are Strings representing reserved keywords in
|
64
78
|
# the Puppet DSL when Application Management is enabled
|
65
79
|
# From https://github.com/puppetlabs/puppet/blob/master/lib/puppet/pops/parser/lexer2.rb#L142-L159
|
@@ -70,7 +84,7 @@ class PuppetLint
|
|
70
84
|
'consumes' => true,
|
71
85
|
'produces' => true,
|
72
86
|
'site' => true,
|
73
|
-
}
|
87
|
+
}.freeze
|
74
88
|
|
75
89
|
# Internal: A Hash whose keys are Symbols representing token types which
|
76
90
|
# a regular expression can follow.
|
@@ -85,60 +99,60 @@ class PuppetLint
|
|
85
99
|
:IF => true,
|
86
100
|
:ELSIF => true,
|
87
101
|
:LPAREN => true,
|
88
|
-
}
|
102
|
+
}.freeze
|
89
103
|
|
90
104
|
# Internal: An Array of Arrays containing tokens that can be described by
|
91
105
|
# a single regular expression. Each sub-Array contains 2 elements, the
|
92
106
|
# name of the token as a Symbol and a regular expression describing the
|
93
107
|
# value of the token.
|
94
|
-
NAME_RE =
|
108
|
+
NAME_RE = %r{\A(((::)?[_a-z0-9][-\w]*)(::[a-z0-9][-\w]*)*)}
|
95
109
|
KNOWN_TOKENS = [
|
96
|
-
[:TYPE,
|
97
|
-
[:CLASSREF,
|
98
|
-
[:NUMBER,
|
99
|
-
[:FUNCTION_NAME,
|
110
|
+
[:TYPE, %r{\A(Integer|Float|Boolean|Regexp|String|Array|Hash|Resource|Class|Collection|Scalar|Numeric|CatalogEntry|Data|Tuple|Struct|Optional|NotUndef|Variant|Enum|Pattern|Any|Callable|Type|Runtime|Undef|Default)\b}],
|
111
|
+
[:CLASSREF, %r{\A(((::){0,1}[A-Z][-\w]*)+)}],
|
112
|
+
[:NUMBER, %r{\A\b((?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?))\b}],
|
113
|
+
[:FUNCTION_NAME, %r{#{NAME_RE}\(}],
|
100
114
|
[:NAME, NAME_RE],
|
101
|
-
[:LBRACK,
|
102
|
-
[:RBRACK,
|
103
|
-
[:LBRACE,
|
104
|
-
[:RBRACE,
|
105
|
-
[:LPAREN,
|
106
|
-
[:RPAREN,
|
107
|
-
[:ISEQUAL,
|
108
|
-
[:MATCH,
|
109
|
-
[:FARROW,
|
110
|
-
[:EQUALS,
|
111
|
-
[:APPENDS,
|
112
|
-
[:PARROW,
|
113
|
-
[:PLUS,
|
114
|
-
[:GREATEREQUAL,
|
115
|
-
[:RSHIFT,
|
116
|
-
[:GREATERTHAN,
|
117
|
-
[:LESSEQUAL,
|
118
|
-
[:LLCOLLECT,
|
119
|
-
[:OUT_EDGE,
|
120
|
-
[:OUT_EDGE_SUB,
|
121
|
-
[:LCOLLECT,
|
122
|
-
[:LSHIFT,
|
123
|
-
[:LESSTHAN,
|
124
|
-
[:NOMATCH,
|
125
|
-
[:NOTEQUAL,
|
126
|
-
[:NOT,
|
127
|
-
[:RRCOLLECT,
|
128
|
-
[:RCOLLECT,
|
129
|
-
[:IN_EDGE,
|
130
|
-
[:IN_EDGE_SUB,
|
131
|
-
[:MINUS,
|
132
|
-
[:COMMA,
|
133
|
-
[:DOT,
|
134
|
-
[:COLON,
|
135
|
-
[:SEMIC,
|
136
|
-
[:QMARK,
|
137
|
-
[:BACKSLASH,
|
138
|
-
[:TIMES,
|
139
|
-
[:MODULO,
|
140
|
-
[:PIPE,
|
141
|
-
]
|
115
|
+
[:LBRACK, %r{\A(\[)}],
|
116
|
+
[:RBRACK, %r{\A(\])}],
|
117
|
+
[:LBRACE, %r{\A(\{)}],
|
118
|
+
[:RBRACE, %r{\A(\})}],
|
119
|
+
[:LPAREN, %r{\A(\()}],
|
120
|
+
[:RPAREN, %r{\A(\))}],
|
121
|
+
[:ISEQUAL, %r{\A(==)}],
|
122
|
+
[:MATCH, %r{\A(=~)}],
|
123
|
+
[:FARROW, %r{\A(=>)}],
|
124
|
+
[:EQUALS, %r{\A(=)}],
|
125
|
+
[:APPENDS, %r{\A(\+=)}],
|
126
|
+
[:PARROW, %r{\A(\+>)}],
|
127
|
+
[:PLUS, %r{\A(\+)}],
|
128
|
+
[:GREATEREQUAL, %r{\A(>=)}],
|
129
|
+
[:RSHIFT, %r{\A(>>)}],
|
130
|
+
[:GREATERTHAN, %r{\A(>)}],
|
131
|
+
[:LESSEQUAL, %r{\A(<=)}],
|
132
|
+
[:LLCOLLECT, %r{\A(<<\|)}],
|
133
|
+
[:OUT_EDGE, %r{\A(<-)}],
|
134
|
+
[:OUT_EDGE_SUB, %r{\A(<~)}],
|
135
|
+
[:LCOLLECT, %r{\A(<\|)}],
|
136
|
+
[:LSHIFT, %r{\A(<<)}],
|
137
|
+
[:LESSTHAN, %r{\A(<)}],
|
138
|
+
[:NOMATCH, %r{\A(!~)}],
|
139
|
+
[:NOTEQUAL, %r{\A(!=)}],
|
140
|
+
[:NOT, %r{\A(!)}],
|
141
|
+
[:RRCOLLECT, %r{\A(\|>>)}],
|
142
|
+
[:RCOLLECT, %r{\A(\|>)}],
|
143
|
+
[:IN_EDGE, %r{\A(->)}],
|
144
|
+
[:IN_EDGE_SUB, %r{\A(~>)}],
|
145
|
+
[:MINUS, %r{\A(-)}],
|
146
|
+
[:COMMA, %r{\A(,)}],
|
147
|
+
[:DOT, %r{\A(\.)}],
|
148
|
+
[:COLON, %r{\A(:)}],
|
149
|
+
[:SEMIC, %r{\A(;)}],
|
150
|
+
[:QMARK, %r{\A(\?)}],
|
151
|
+
[:BACKSLASH, %r{\A(\\)}],
|
152
|
+
[:TIMES, %r{\A(\*)}],
|
153
|
+
[:MODULO, %r{\A(%)}],
|
154
|
+
[:PIPE, %r{\A(\|)}],
|
155
|
+
].freeze
|
142
156
|
|
143
157
|
# Internal: A Hash whose keys are Symbols representing token types which
|
144
158
|
# are considered to be formatting tokens (i.e. tokens that don't contain
|
@@ -150,7 +164,13 @@ class PuppetLint
|
|
150
164
|
:MLCOMMENT => true,
|
151
165
|
:SLASH_COMMENT => true,
|
152
166
|
:INDENT => true,
|
153
|
-
}
|
167
|
+
}.freeze
|
168
|
+
|
169
|
+
# \t == tab
|
170
|
+
# \v == vertical tab
|
171
|
+
# \f == form feed
|
172
|
+
# \p{Zs} == ASCII + Unicode non-linebreaking whitespace
|
173
|
+
WHITESPACE_RE = %r{[\t\v\f\p{Zs}]}
|
154
174
|
|
155
175
|
# Internal: Access the internal token storage.
|
156
176
|
#
|
@@ -175,127 +195,128 @@ class PuppetLint
|
|
175
195
|
found = false
|
176
196
|
|
177
197
|
KNOWN_TOKENS.each do |type, regex|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
found = true
|
191
|
-
break
|
192
|
-
end
|
198
|
+
value = chunk[regex, 1]
|
199
|
+
next if value.nil?
|
200
|
+
|
201
|
+
length = value.size
|
202
|
+
tokens << if type == :NAME && KEYWORDS.include?(value)
|
203
|
+
new_token(value.upcase.to_sym, value)
|
204
|
+
else
|
205
|
+
new_token(type, value)
|
206
|
+
end
|
207
|
+
i += length
|
208
|
+
found = true
|
209
|
+
break
|
193
210
|
end
|
194
211
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
212
|
+
next if found
|
213
|
+
|
214
|
+
if var_name = chunk[%r{\A\$((::)?(\w+(-\w+)*::)*\w+(-\w+)*(\[.+?\])*)}, 1]
|
215
|
+
length = var_name.size + 1
|
216
|
+
tokens << new_token(:VARIABLE, var_name)
|
217
|
+
|
218
|
+
elsif chunk =~ %r{\A'.*?'}m
|
219
|
+
str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*'}m)
|
220
|
+
length = str_content.size + 1
|
221
|
+
tokens << new_token(:SSTRING, str_content[0..-2])
|
222
|
+
|
223
|
+
elsif chunk.start_with?('"')
|
224
|
+
str_contents = slurp_string(code[i + 1..-1])
|
225
|
+
lines_parsed = code[0..i].split("\n")
|
226
|
+
interpolate_string(str_contents, lines_parsed.count, lines_parsed.last.length)
|
227
|
+
length = str_contents.size + 1
|
228
|
+
|
229
|
+
elsif heredoc_name = chunk[%r{\A@\(("?.+?"?(:.+?)?(/.*?)?)\)}, 1]
|
230
|
+
heredoc_queue << heredoc_name
|
231
|
+
tokens << new_token(:HEREDOC_OPEN, heredoc_name)
|
232
|
+
length = heredoc_name.size + 3
|
233
|
+
|
234
|
+
elsif comment = chunk[%r{\A(#.*)}, 1]
|
235
|
+
length = comment.size
|
236
|
+
comment.sub!(%r{#}, '')
|
237
|
+
tokens << new_token(:COMMENT, comment)
|
238
|
+
|
239
|
+
elsif slash_comment = chunk[%r{\A(//.*)}, 1]
|
240
|
+
length = slash_comment.size
|
241
|
+
slash_comment.sub!(%r{//}, '')
|
242
|
+
tokens << new_token(:SLASH_COMMENT, slash_comment)
|
243
|
+
|
244
|
+
elsif mlcomment = chunk[%r{\A(/\*.*?\*/)}m, 1]
|
245
|
+
length = mlcomment.size
|
246
|
+
mlcomment_raw = mlcomment.dup
|
247
|
+
mlcomment.sub!(%r{\A/\* ?}, '')
|
248
|
+
mlcomment.sub!(%r{ ?\*/\Z}, '')
|
249
|
+
mlcomment.gsub!(%r{^ *\*}, '')
|
250
|
+
tokens << new_token(:MLCOMMENT, mlcomment, :raw => mlcomment_raw)
|
251
|
+
|
252
|
+
elsif chunk.match(%r{\A/.*?/}) && possible_regex?
|
253
|
+
str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*/}m)
|
254
|
+
length = str_content.size + 1
|
255
|
+
tokens << new_token(:REGEX, str_content[0..-2])
|
256
|
+
|
257
|
+
elsif eolindent = chunk[%r{\A((\r\n|\r|\n)#{WHITESPACE_RE}+)}m, 1]
|
258
|
+
eol = eolindent[%r{\A([\r\n]+)}m, 1]
|
259
|
+
tokens << new_token(:NEWLINE, eol)
|
260
|
+
length = eol.size
|
261
|
+
|
262
|
+
if heredoc_queue.empty?
|
263
|
+
indent = eolindent[%r{\A[\r\n]+(#{WHITESPACE_RE}+)}m, 1]
|
264
|
+
tokens << new_token(:INDENT, indent)
|
265
|
+
length += indent.size
|
266
|
+
else
|
267
|
+
heredoc_tag = heredoc_queue.shift
|
268
|
+
heredoc_name = heredoc_tag[%r{\A"?(.+?)"?(:.+?)?(/.*)?\Z}, 1]
|
269
|
+
str_contents = StringScanner.new(code[i + length..-1]).scan_until(%r{\|?\s*-?\s*#{heredoc_name}})
|
270
|
+
interpolate_heredoc(str_contents, heredoc_tag)
|
271
|
+
length += str_contents.size
|
272
|
+
end
|
255
273
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
274
|
+
elsif whitespace = chunk[%r{\A(#{WHITESPACE_RE}+)}, 1]
|
275
|
+
length = whitespace.size
|
276
|
+
tokens << new_token(:WHITESPACE, whitespace)
|
277
|
+
|
278
|
+
elsif eol = chunk[%r{\A(\r\n|\r|\n)}, 1]
|
279
|
+
length = eol.size
|
280
|
+
tokens << new_token(:NEWLINE, eol)
|
281
|
+
|
282
|
+
unless heredoc_queue.empty?
|
283
|
+
heredoc_tag = heredoc_queue.shift
|
284
|
+
heredoc_name = heredoc_tag[%r{\A"?(.+?)"?(:.+?)?(/.*)?\Z}, 1]
|
285
|
+
str_contents = StringScanner.new(code[i + length..-1]).scan_until(%r{\|?\s*-?\s*#{heredoc_name}})
|
286
|
+
_ = code[0..i + length].split("\n")
|
287
|
+
interpolate_heredoc(str_contents, heredoc_tag)
|
288
|
+
length += str_contents.size
|
289
|
+
end
|
272
290
|
|
273
|
-
|
274
|
-
|
275
|
-
|
291
|
+
elsif chunk.start_with?('/')
|
292
|
+
length = 1
|
293
|
+
tokens << new_token(:DIV, '/')
|
276
294
|
|
277
|
-
|
278
|
-
|
279
|
-
|
295
|
+
elsif chunk.start_with?('@')
|
296
|
+
length = 1
|
297
|
+
tokens << new_token(:AT, '@')
|
280
298
|
|
281
|
-
|
282
|
-
|
283
|
-
end
|
284
|
-
|
285
|
-
i += length
|
299
|
+
else
|
300
|
+
raise PuppetLint::LexerError.new(@line_no, @column)
|
286
301
|
end
|
302
|
+
|
303
|
+
i += length
|
287
304
|
end
|
288
305
|
|
289
306
|
tokens
|
290
307
|
end
|
291
308
|
|
292
|
-
|
293
309
|
def slurp_string(string)
|
294
|
-
dq_str_regexp =
|
310
|
+
dq_str_regexp = %r{(\$\{|(\A|[^\\])(\\\\)*")}m
|
295
311
|
scanner = StringScanner.new(string)
|
296
312
|
contents = scanner.scan_until(dq_str_regexp)
|
313
|
+
|
314
|
+
if scanner.matched.nil?
|
315
|
+
raise LexerError.new(@line_no, @column, 'Double quoted string missing closing quote')
|
316
|
+
end
|
317
|
+
|
297
318
|
until scanner.matched.end_with?('"')
|
298
|
-
contents += scanner.scan_until(
|
319
|
+
contents += scanner.scan_until(%r{\}}m)
|
299
320
|
contents += scanner.scan_until(dq_str_regexp)
|
300
321
|
end
|
301
322
|
contents
|
@@ -307,16 +328,12 @@ class PuppetLint
|
|
307
328
|
# Returns true if the next token could be a regex, otherwise return false.
|
308
329
|
def possible_regex?
|
309
330
|
prev_token = tokens.reject { |r|
|
310
|
-
FORMATTING_TOKENS.include?
|
331
|
+
FORMATTING_TOKENS.include?(r.type)
|
311
332
|
}.last
|
312
333
|
|
313
334
|
return true if prev_token.nil?
|
314
335
|
|
315
|
-
|
316
|
-
true
|
317
|
-
else
|
318
|
-
false
|
319
|
-
end
|
336
|
+
REGEX_PREV_TOKENS.include?(prev_token.type)
|
320
337
|
end
|
321
338
|
|
322
339
|
# Internal: Create a new PuppetLint::Lexer::Token object, calculate its
|
@@ -337,6 +354,14 @@ class PuppetLint
|
|
337
354
|
# passed by 3rd party plugins that haven't updated yet.
|
338
355
|
opts = args.last.is_a?(Hash) ? args.last : {}
|
339
356
|
|
357
|
+
# column number is calculated at the end of this method by calling
|
358
|
+
# to_manifest on the token. Because the string tokens (DQPRE, DQMID etc)
|
359
|
+
# are parsed before the variable token, they default to assuming that
|
360
|
+
# they are followed by an enclosed variable and we need to remove 2 from
|
361
|
+
# the column number if we encounter an unenclosed variable because of the
|
362
|
+
# missing ${ at the end of the token value.
|
363
|
+
@column -= 2 if type == :UNENC_VARIABLE
|
364
|
+
|
340
365
|
column = opts[:column] || @column
|
341
366
|
line_no = opts[:line] || @line_no
|
342
367
|
|
@@ -346,7 +371,7 @@ class PuppetLint
|
|
346
371
|
tokens.last.next_token = token
|
347
372
|
|
348
373
|
unless FORMATTING_TOKENS.include?(token.type)
|
349
|
-
prev_nf_idx = tokens.rindex { |r| !
|
374
|
+
prev_nf_idx = tokens.rindex { |r| !FORMATTING_TOKENS.include?(r.type) }
|
350
375
|
unless prev_nf_idx.nil?
|
351
376
|
prev_nf_token = tokens[prev_nf_idx]
|
352
377
|
prev_nf_token.next_code_token = token
|
@@ -355,15 +380,13 @@ class PuppetLint
|
|
355
380
|
end
|
356
381
|
end
|
357
382
|
|
358
|
-
if opts[:raw]
|
359
|
-
token.raw = opts[:raw]
|
360
|
-
end
|
383
|
+
token.raw = opts[:raw] if opts[:raw]
|
361
384
|
|
362
385
|
if type == :NEWLINE
|
363
386
|
@line_no += 1
|
364
387
|
@column = 1
|
365
388
|
else
|
366
|
-
lines = token.to_manifest.split(
|
389
|
+
lines = token.to_manifest.split(%r{(?:\r\n|\r|\n)}, -1)
|
367
390
|
@line_no += lines.length - 1
|
368
391
|
if lines.length > 1
|
369
392
|
# if the token renders to multiple lines, set the column state to the
|
@@ -371,7 +394,7 @@ class PuppetLint
|
|
371
394
|
# 1 indexed)
|
372
395
|
@column = lines.last.size + 1
|
373
396
|
else
|
374
|
-
@column += (lines.last ||
|
397
|
+
@column += (lines.last || '').size
|
375
398
|
end
|
376
399
|
end
|
377
400
|
|
@@ -388,9 +411,9 @@ class PuppetLint
|
|
388
411
|
# Returns an Array consisting of two Strings, the String up to the first
|
389
412
|
# terminator and the terminator that was found.
|
390
413
|
def get_string_segment(string, terminators)
|
391
|
-
str = string.scan_until(
|
414
|
+
str = string.scan_until(%r{([^\\]|^|[^\\])([\\]{2})*[#{terminators}]+})
|
392
415
|
begin
|
393
|
-
[str[0..-2], str[-1,1]]
|
416
|
+
[str[0..-2], str[-1, 1]]
|
394
417
|
rescue
|
395
418
|
[nil, nil]
|
396
419
|
end
|
@@ -408,14 +431,14 @@ class PuppetLint
|
|
408
431
|
first = true
|
409
432
|
value, terminator = get_string_segment(ss, '"$')
|
410
433
|
until value.nil?
|
411
|
-
if terminator == "
|
434
|
+
if terminator == '"'
|
412
435
|
if first
|
413
436
|
tokens << new_token(:STRING, value, :line => line, :column => column)
|
414
437
|
first = false
|
415
438
|
else
|
416
|
-
line += value.scan(/(\r\n|\r|\n)/).size
|
417
439
|
token_column = column + (ss.pos - value.size)
|
418
440
|
tokens << new_token(:DQPOST, value, :line => line, :column => token_column)
|
441
|
+
line += value.scan(%r{(\r\n|\r|\n)}).size
|
419
442
|
@column = column + ss.pos + 1
|
420
443
|
@line_no = line
|
421
444
|
end
|
@@ -424,23 +447,24 @@ class PuppetLint
|
|
424
447
|
tokens << new_token(:DQPRE, value, :line => line, :column => column)
|
425
448
|
first = false
|
426
449
|
else
|
427
|
-
line += value.scan(/(\r\n|\r|\n)/).size
|
428
450
|
token_column = column + (ss.pos - value.size)
|
429
451
|
tokens << new_token(:DQMID, value, :line => line, :column => token_column)
|
452
|
+
line += value.scan(%r{(\r\n|\r|\n)}).size
|
430
453
|
end
|
431
|
-
if ss.scan(
|
432
|
-
var_name = ss.scan(
|
454
|
+
if ss.scan(%r{\{}).nil?
|
455
|
+
var_name = ss.scan(%r{(::)?(\w+(-\w+)*::)*\w+(-\w+)*})
|
433
456
|
if var_name.nil?
|
434
457
|
token_column = column + ss.pos - 1
|
435
|
-
tokens << new_token(:DQMID,
|
458
|
+
tokens << new_token(:DQMID, '$', :line => line, :column => token_column)
|
436
459
|
else
|
437
460
|
token_column = column + (ss.pos - var_name.size)
|
438
461
|
tokens << new_token(:UNENC_VARIABLE, var_name, :line => line, :column => token_column)
|
439
462
|
end
|
440
463
|
else
|
441
|
-
|
464
|
+
line += value.scan(%r{(\r\n|\r|\n)}).size
|
465
|
+
contents = ss.scan_until(%r{\}})[0..-2]
|
442
466
|
raw = contents.dup
|
443
|
-
if contents.match(
|
467
|
+
if contents.match(%r{\A(::)?([\w-]+::)*[\w-]+(\[.+?\])*}) && !contents.match(%r{\A\w+\(})
|
444
468
|
contents = "$#{contents}"
|
445
469
|
end
|
446
470
|
lexer = PuppetLint::Lexer.new
|
@@ -467,12 +491,12 @@ class PuppetLint
|
|
467
491
|
# Returns nothing.
|
468
492
|
def interpolate_heredoc(string, name)
|
469
493
|
ss = StringScanner.new(string)
|
470
|
-
eos_text = name[
|
494
|
+
eos_text = name[%r{\A"?(.+?)"?(:.+?)?(/.*)?\Z}, 1]
|
471
495
|
first = true
|
472
496
|
interpolate = name.start_with?('"')
|
473
497
|
value, terminator = get_heredoc_segment(ss, eos_text, interpolate)
|
474
498
|
until value.nil?
|
475
|
-
if terminator =~
|
499
|
+
if terminator =~ %r{\A\|?\s*-?\s*#{Regexp.escape(eos_text)}}
|
476
500
|
if first
|
477
501
|
tokens << new_token(:HEREDOC, value, :raw => "#{value}#{terminator}")
|
478
502
|
first = false
|
@@ -486,18 +510,18 @@ class PuppetLint
|
|
486
510
|
else
|
487
511
|
tokens << new_token(:HEREDOC_MID, value)
|
488
512
|
end
|
489
|
-
if ss.scan(
|
490
|
-
var_name = ss.scan(
|
491
|
-
if var_name.nil?
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
513
|
+
if ss.scan(%r{\{}).nil?
|
514
|
+
var_name = ss.scan(%r{(::)?(\w+(-\w+)*::)*\w+(-\w+)*})
|
515
|
+
tokens << if var_name.nil?
|
516
|
+
new_token(:HEREDOC_MID, '$')
|
517
|
+
else
|
518
|
+
new_token(:UNENC_VARIABLE, var_name)
|
519
|
+
end
|
496
520
|
else
|
497
|
-
contents = ss.scan_until(
|
521
|
+
contents = ss.scan_until(%r{\}})[0..-2]
|
498
522
|
raw = contents.dup
|
499
|
-
if contents.match(
|
500
|
-
contents = "$#{contents}" unless contents.start_with?(
|
523
|
+
if contents.match(%r{\A(::)?([\w-]+::)*[\w-]|(\[.+?\])*}) && !contents.match(%r{\A\w+\(})
|
524
|
+
contents = "$#{contents}" unless contents.start_with?('$')
|
501
525
|
end
|
502
526
|
|
503
527
|
lexer = PuppetLint::Lexer.new
|
@@ -524,19 +548,17 @@ class PuppetLint
|
|
524
548
|
#
|
525
549
|
# Returns an Array consisting of two Strings, the String up to the first
|
526
550
|
# terminator and the terminator that was found.
|
527
|
-
def get_heredoc_segment(string, eos_text, interpolate=true)
|
528
|
-
if interpolate
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
551
|
+
def get_heredoc_segment(string, eos_text, interpolate = true)
|
552
|
+
regexp = if interpolate
|
553
|
+
%r{(([^\\]|^|[^\\])([\\]{2})*[$]+|\|?\s*-?#{Regexp.escape(eos_text)})}
|
554
|
+
else
|
555
|
+
%r{\|?\s*-?#{Regexp.escape(eos_text)}}
|
556
|
+
end
|
533
557
|
|
534
558
|
str = string.scan_until(regexp)
|
535
559
|
begin
|
536
|
-
str =~
|
537
|
-
value
|
538
|
-
terminator = $2
|
539
|
-
[value, terminator]
|
560
|
+
str =~ %r{\A(?<value>.*?)(?<terminator>[$]+|\|?\s*-?#{Regexp.escape(eos_text)})\Z}m
|
561
|
+
[Regexp.last_match(:value), Regexp.last_match(:terminator)]
|
540
562
|
rescue
|
541
563
|
[nil, nil]
|
542
564
|
end
|