puppet-lint 2.1.1 → 2.2.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.
@@ -77,8 +77,13 @@ class PuppetLint
77
77
  when :DQPOST
78
78
  "#{@value}\""
79
79
  when :VARIABLE
80
- if !@prev_code_token.nil? && [:DQPRE, :DQMID].include?(@prev_code_token.type)
81
- "${#{@value}}"
80
+ enclose_token_types = Set[:DQPRE, :DQMID, :HEREDOC_PRE, :HEREDOC_MID].freeze
81
+ if !@prev_code_token.nil? && enclose_token_types.include?(@prev_code_token.type)
82
+ if @raw.nil?
83
+ "${#{@value}}"
84
+ else
85
+ "${#{@raw}}"
86
+ end
82
87
  else
83
88
  "$#{@value}"
84
89
  end
@@ -92,10 +97,90 @@ class PuppetLint
92
97
  "/#{@value}/"
93
98
  when :MLCOMMENT
94
99
  @raw
100
+ when :HEREDOC_OPEN
101
+ "@(#{@value})"
102
+ when :HEREDOC
103
+ @raw
104
+ when :HEREDOC_POST
105
+ @raw
95
106
  else
96
107
  @value
97
108
  end
98
109
  end
110
+
111
+ # Public: Search from this token to find the next token of a given type.
112
+ #
113
+ # type - A Symbol type of the token to find, or an Array of Symbols.
114
+ # opts - An optional Hash
115
+ # :value - A token value to search for in addition to type
116
+ # :skip_blocks - A Boolean to specify whether { } blocks should be
117
+ # skipped over (defaults to true).
118
+ #
119
+ # Returns a PuppetLint::Lexer::Token object if a matching token could be
120
+ # found, otherwise nil.
121
+ def next_token_of(type, opts = {})
122
+ find_token_of(:next, type, opts)
123
+ end
124
+
125
+ # Public: Search from this token to find the previous token of a given type.
126
+ #
127
+ # type - A Symbol type of the token to find, or an Array of Symbols.
128
+ # opts - An optional Hash
129
+ # :value - A token value to search for in addition to type
130
+ # :skip_blocks - A Boolean to specify whether { } blocks should be
131
+ # skipped over (defaults to true).
132
+ #
133
+ # Returns a PuppetLint::Lexer::Token object if a matching token could be
134
+ # found, otherwise nil.
135
+ def prev_token_of(type, opts = {})
136
+ find_token_of(:prev, type, opts)
137
+ end
138
+
139
+ # Internal: Search from this token to find the next token of a given type
140
+ # in a given direction.
141
+ #
142
+ # direction - A Symbol direction to search (:next or :prev).
143
+ # type - A Symbol type of the token to find, or an Array of Symbols.
144
+ # opts - An optional Hash
145
+ # :value - A token value to search for in addition to type
146
+ # :skip_blocks - A Boolean to specify whether { } blocks should be
147
+ # skipped over (defaults to true).
148
+ #
149
+ # Returns a PuppetLint::Lexer::Token object if a matching token could be
150
+ # found, otherwise nil.
151
+ def find_token_of(direction, type, opts = {})
152
+ return nil unless [:next, :prev].include?(direction)
153
+
154
+ opts[:skip_blocks] ||= true
155
+ to_find = Array[*type]
156
+
157
+ token_iter = self.send("#{direction}_token".to_sym)
158
+ while !token_iter.nil?
159
+ if to_find.include? token_iter.type
160
+ if opts[:value]
161
+ return token_iter if token_iter.value == opts[:value]
162
+ else
163
+ return token_iter
164
+ end
165
+ end
166
+
167
+ opening_token = direction == :next ? "L" : "R"
168
+ closing_token = direction == :next ? "R" : "L"
169
+
170
+ if opts[:skip_blocks]
171
+ case token_iter.type
172
+ when "#{opening_token}BRACE".to_sym
173
+ token_iter = token_iter.send("#{direction}_token_of".to_sym, ["#{closing_token}BRACE".to_sym, opts])
174
+ when "#{opening_token}BRACK".to_sym
175
+ token_iter = token_iter.send("#{direction}_token_of".to_sym, ["#{closing_token}BRACK".to_sym, opts])
176
+ when "#{opening_token}PAREN".to_sym
177
+ token_iter = token_iter.send("#{direction}_token_of".to_sym, ["#{closing_token}PAREN".to_sym, opts])
178
+ end
179
+ end
180
+ token_iter = token_iter.send("#{direction}_token".to_sym)
181
+ end
182
+ nil
183
+ end
99
184
  end
100
185
  end
101
186
  end
@@ -14,6 +14,44 @@ PuppetLint.new_check(:right_to_left_relationship) do
14
14
  end
15
15
  end
16
16
 
17
+ # Public: Test the manifest tokens for chaining arrow that is
18
+ # on the line of the left operand when the right operand is on another line.
19
+ #
20
+ # https://docs.puppet.com/guides/style_guide.html#chaining-arrow-syntax
21
+ PuppetLint.new_check(:arrow_on_right_operand_line) do
22
+ def check
23
+ tokens.select { |r| Set[:IN_EDGE, :IN_EDGE_SUB].include?(r.type) }.each do |token|
24
+ if token.next_code_token.line != token.line
25
+ notify :warning, {
26
+ :message => 'arrow should be on the right operand\'s line',
27
+ :line => token.line,
28
+ :column => token.column,
29
+ :token => token,
30
+ }
31
+ end
32
+ end
33
+ end
34
+
35
+ def fix(problem)
36
+ token = problem[:token]
37
+ tokens.delete(token)
38
+ # remove any excessive whitespace on the line
39
+ temp_token = token.prev_code_token
40
+ while (temp_token = temp_token.next_token)
41
+ tokens.delete(temp_token) if whitespace?(temp_token)
42
+ break if temp_token.type == :NEWLINE
43
+ end
44
+
45
+ index = tokens.index(token.next_code_token)
46
+ tokens.insert(index, token)
47
+ tokens.insert(index + 1, PuppetLint::Lexer::Token.new(:WHITESPACE, ' ', 0, 0))
48
+ end
49
+
50
+ def whitespace?(token)
51
+ Set[:INDENT, :WHITESPACE].include?(token.type)
52
+ end
53
+ end
54
+
17
55
  # Public: Test the manifest tokens for any classes or defined types that are
18
56
  # not in an appropriately named file for the autoloader to detect and record
19
57
  # an error of each instance found.
@@ -295,7 +333,7 @@ PuppetLint.new_check(:variable_scope) do
295
333
 
296
334
  future_parser_scopes = {}
297
335
  in_pipe = false
298
- temp_scope_vars = []
336
+ block_params_stack = []
299
337
 
300
338
  object_tokens.each do |token|
301
339
  case token.type
@@ -303,18 +341,28 @@ PuppetLint.new_check(:variable_scope) do
303
341
  if token.prev_code_token.type == :VARIABLE
304
342
  variables_in_scope << token.prev_code_token.value
305
343
  elsif token.prev_code_token.type == :RBRACK
306
- temp_token = token.prev_code_token
344
+ temp_token = token
307
345
 
308
- until temp_token.type == :LBRACK do
309
- if temp_token.type == :VARIABLE
346
+ brack_depth = 0
347
+ while temp_token = temp_token.prev_code_token
348
+ case temp_token.type
349
+ when :VARIABLE
310
350
  variables_in_scope << temp_token.value
351
+ when :RBRACK
352
+ brack_depth += 1
353
+ when :LBRACK
354
+ brack_depth -= 1
355
+ break if brack_depth == 0
356
+ when :COMMA
357
+ # ignore
358
+ else # unexpected
359
+ break
311
360
  end
312
- temp_token = temp_token.prev_code_token
313
361
  end
314
362
  end
315
363
  when :VARIABLE
316
364
  if in_pipe
317
- temp_scope_vars << token.value
365
+ block_params_stack[-1] << token.value
318
366
  else
319
367
  referenced_variables << token
320
368
  end
@@ -322,7 +370,7 @@ PuppetLint.new_check(:variable_scope) do
322
370
  in_pipe = !in_pipe
323
371
 
324
372
  if in_pipe
325
- temp_scope_vars = []
373
+ block_params_stack << []
326
374
  else
327
375
  start_idx = tokens.find_index(token)
328
376
  end_token = nil
@@ -341,7 +389,11 @@ PuppetLint.new_check(:variable_scope) do
341
389
  end
342
390
  end
343
391
 
344
- future_parser_scopes.merge!(Hash[(token.line..end_token.line).to_a.map { |i| [i, temp_scope_vars] }])
392
+ params = block_params_stack.pop
393
+ (token.line..end_token.line).each do |line|
394
+ future_parser_scopes[line] ||= []
395
+ future_parser_scopes[line].concat(params)
396
+ end
345
397
  end
346
398
  end
347
399
  end
@@ -8,6 +8,16 @@ PuppetLint.new_check(:unquoted_node_name) do
8
8
  node_tokens.each do |node|
9
9
  node_token_idx = tokens.index(node)
10
10
  node_lbrace_tok = tokens[node_token_idx..-1].find { |token| token.type == :LBRACE }
11
+ if node_lbrace_tok.nil?
12
+ notify :error, {
13
+ :check => :syntax,
14
+ :message => 'Syntax error (try running `puppet parser validate <file>`)',
15
+ :line => node.line,
16
+ :column => node.column,
17
+ }
18
+ next
19
+ end
20
+
11
21
  node_lbrace_idx = tokens.index(node_lbrace_tok)
12
22
 
13
23
  tokens[node_token_idx..node_lbrace_idx].select { |token|
@@ -47,43 +47,22 @@ PuppetLint.new_check(:ensure_first_param) do
47
47
  end
48
48
  end
49
49
  end
50
+
50
51
  def fix(problem)
51
- # We find the first and ensure paramss boundaries
52
- first_param_name_token = nil
53
- first_param_name_idx = nil
54
- first_param_comma_token = nil
55
- first_param_comma_idx = nil
56
- ensure_param_name_token = nil
57
- ensure_param_name_idx = nil
58
- ensure_param_comma_token = nil
59
- ensure_param_comma_idx = nil
60
- tokens[(problem[:resource][:start])..(problem[:resource][:end])].each_with_index do |token, token_idx|
61
- if first_param_name_token.nil?
62
- if token.type == :NAME
63
- first_param_name_token = token
64
- first_param_name_idx = problem[:resource][:start] + token_idx
65
- end
66
- elsif first_param_comma_token.nil?
67
- if token.type == :COMMA
68
- first_param_comma_token = token
69
- first_param_comma_idx = problem[:resource][:start] + token_idx
70
- end
71
- elsif ensure_param_name_token.nil?
72
- if token.type == :NAME and token.value == 'ensure'
73
- ensure_param_name_token = token
74
- ensure_param_name_idx = problem[:resource][:start] + token_idx
75
- end
76
- elsif ensure_param_comma_token.nil?
77
- if token.type == :COMMA or token.type == :SEMIC
78
- ensure_param_comma_token = token
79
- ensure_param_comma_idx = problem[:resource][:start] + token_idx
80
- break
81
- end
82
- end
83
- end
52
+ first_param_name_token = tokens[problem[:resource][:start]].next_token_of(:NAME)
53
+ first_param_comma_token = first_param_name_token.next_token_of(:COMMA)
54
+ ensure_param_name_token = first_param_comma_token.next_token_of(:NAME, :value => 'ensure')
55
+ ensure_param_comma_token = ensure_param_name_token.next_token_of([:COMMA, :SEMIC])
56
+
84
57
  if first_param_name_token.nil? or first_param_comma_token.nil? or ensure_param_name_token.nil? or ensure_param_comma_token.nil?
85
58
  raise PuppetLint::NoFix
86
59
  end
60
+
61
+ first_param_name_idx = tokens.index(first_param_name_token)
62
+ first_param_comma_idx = tokens.index(first_param_comma_token)
63
+ ensure_param_name_idx = tokens.index(ensure_param_name_token)
64
+ ensure_param_comma_idx = tokens.index(ensure_param_comma_token)
65
+
87
66
  # Flip params
88
67
  prev_token = first_param_name_token.prev_token
89
68
  first_param_name_token.prev_token = ensure_param_name_token.prev_token
@@ -191,7 +170,7 @@ end
191
170
  PuppetLint.new_check(:file_mode) do
192
171
  MSG = 'mode should be represented as a 4 digit octal value or symbolic mode'
193
172
  SYM_RE = "([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*"
194
- IGNORE_TYPES = Set[:VARIABLE, :UNDEF]
173
+ IGNORE_TYPES = Set[:VARIABLE, :UNDEF, :FUNCTION_NAME]
195
174
  MODE_RE = Regexp.new(/\A([0-7]{4}|#{SYM_RE})\Z/)
196
175
 
197
176
  def check
@@ -10,7 +10,7 @@ PuppetLint.new_check(:double_quoted_strings) do
10
10
  }.map { |token|
11
11
  [token, token.value.gsub(' '*token.column, "\n")]
12
12
  }.select { |token, sane_value|
13
- sane_value[/(\\\$|\\"|\\'|'|\r|\t|\\t|\n|\\n)/].nil?
13
+ sane_value[/(\\\$|\\"|\\'|'|\r|\t|\\t|\n|\\n|\\\\)/].nil?
14
14
  }.each do |token, sane_value|
15
15
  notify :warning, {
16
16
  :message => 'double quoted string containing no variables',
@@ -125,8 +125,8 @@ PuppetLint.new_check(:arrow_alignment) do
125
125
 
126
126
  def check
127
127
  resource_indexes.each do |res_idx|
128
- indent_depth = [0]
129
- indent_depth_idx = 0
128
+ arrow_column = [0]
129
+ level_idx = 0
130
130
  level_tokens = []
131
131
  param_column = [nil]
132
132
  resource_tokens = res_idx[:tokens]
@@ -139,11 +139,11 @@ PuppetLint.new_check(:arrow_alignment) do
139
139
  last_arrow = resource_tokens.rindex { |r| r.type == :FARROW }
140
140
  next if first_arrow.nil?
141
141
  next if last_arrow.nil?
142
- next unless resource_tokens[first_arrow..last_arrow].any? { |r| r.type == :NEWLINE }
142
+ next if resource_tokens[first_arrow].line == resource_tokens[last_arrow].line
143
143
 
144
144
  resource_tokens.each_with_index do |token, idx|
145
145
  if token.type == :FARROW
146
- (level_tokens[indent_depth_idx] ||= []) << token
146
+ (level_tokens[level_idx] ||= []) << token
147
147
  param_token = token.prev_code_token
148
148
 
149
149
  if param_token.type == :DQPOST
@@ -158,63 +158,52 @@ PuppetLint.new_check(:arrow_alignment) do
158
158
  param_length = param_token.to_manifest.length
159
159
  end
160
160
 
161
- if param_column[indent_depth_idx].nil?
161
+ if param_column[level_idx].nil?
162
162
  if param_token.type == :DQPOST
163
- param_column[indent_depth_idx] = iter_token.column
163
+ param_column[level_idx] = iter_token.column
164
164
  else
165
- param_column[indent_depth_idx] = param_token.column
165
+ param_column[level_idx] = param_token.column
166
166
  end
167
167
  end
168
168
 
169
- indent_length = param_column[indent_depth_idx] + param_length + 1
169
+ this_arrow_column = param_column[level_idx] + param_length + 1
170
170
 
171
- if indent_depth[indent_depth_idx] < indent_length
172
- indent_depth[indent_depth_idx] = indent_length
171
+ if arrow_column[level_idx] < this_arrow_column
172
+ arrow_column[level_idx] = this_arrow_column
173
173
  end
174
174
 
175
175
  elsif token.type == :LBRACE
176
- indent_depth_idx += 1
177
- indent_depth << 0
178
- level_tokens[indent_depth_idx] ||= []
176
+ level_idx += 1
177
+ arrow_column << 0
178
+ level_tokens[level_idx] ||= []
179
179
  param_column << nil
180
180
  elsif token.type == :RBRACE || token.type == :SEMIC
181
- level_tokens[indent_depth_idx].each do |arrow_tok|
182
- unless arrow_tok.column == indent_depth[indent_depth_idx] || level_tokens[indent_depth_idx].size == 1
183
- arrows_on_line = level_tokens[indent_depth_idx].select { |t| t.line == arrow_tok.line }
184
- notify :warning, {
185
- :message => "indentation of => is not properly aligned (expected in column #{indent_depth[indent_depth_idx]}, but found it in column #{arrow_tok.column})",
186
- :line => arrow_tok.line,
187
- :column => arrow_tok.column,
188
- :token => arrow_tok,
189
- :indent_depth => indent_depth[indent_depth_idx],
190
- :newline => !(arrows_on_line.index(arrow_tok) == 0),
191
- :newline_indent => param_column[indent_depth_idx] - 1,
192
- }
181
+ if level_tokens[level_idx].map(&:line).uniq.length > 1
182
+ level_tokens[level_idx].each do |arrow_tok|
183
+ unless arrow_tok.column == arrow_column[level_idx] || level_tokens[level_idx].size == 1
184
+ arrows_on_line = level_tokens[level_idx].select { |t| t.line == arrow_tok.line }
185
+ notify :warning, {
186
+ :message => "indentation of => is not properly aligned (expected in column #{arrow_column[level_idx]}, but found it in column #{arrow_tok.column})",
187
+ :line => arrow_tok.line,
188
+ :column => arrow_tok.column,
189
+ :token => arrow_tok,
190
+ :arrow_column => arrow_column[level_idx],
191
+ :newline => !(arrows_on_line.index(arrow_tok) == 0),
192
+ :newline_indent => param_column[level_idx] - 1,
193
+ }
194
+ end
193
195
  end
194
196
  end
195
- indent_depth[indent_depth_idx] = 0
196
- level_tokens[indent_depth_idx].clear
197
- indent_depth_idx -= 1
197
+ arrow_column[level_idx] = 0
198
+ level_tokens[level_idx].clear
199
+ param_column[level_idx] = nil
200
+ level_idx -= 1
198
201
  end
199
202
  end
200
203
  end
201
204
  end
202
205
 
203
206
  def fix(problem)
204
- param_token = problem[:token].prev_code_token
205
- if param_token.type == :DQPOST
206
- param_length = 0
207
- iter_token = param_token
208
- while iter_token.type != :DQPRE do
209
- param_length += iter_token.to_manifest.length
210
- iter_token = iter_token.prev_token
211
- end
212
- param_length += iter_token.to_manifest.length
213
- else
214
- param_length = param_token.to_manifest.length
215
- end
216
- new_ws_len = (problem[:indent_depth] - (problem[:newline_indent] + param_length + 1))
217
- new_ws = ' ' * new_ws_len
218
207
  if problem[:newline]
219
208
  index = tokens.index(problem[:token].prev_code_token.prev_token)
220
209
 
@@ -226,6 +215,12 @@ PuppetLint.new_check(:arrow_alignment) do
226
215
  problem[:token].prev_code_token.prev_token.value = ' ' * problem[:newline_indent]
227
216
  end
228
217
 
218
+ end_param_idx = tokens.index(problem[:token].prev_code_token)
219
+ start_param_idx = tokens.index(problem[:token].prev_token_of([:INDENT, :NEWLINE])) + 1
220
+ param_length = tokens[start_param_idx..end_param_idx].map { |r| r.to_manifest.length }.inject(0) { |sum,x| sum + x }
221
+ new_ws_len = (problem[:arrow_column] - (problem[:newline_indent] + param_length + 1))
222
+ new_ws = ' ' * new_ws_len
223
+
229
224
  if problem[:token].prev_token.type == :WHITESPACE
230
225
  problem[:token].prev_token.value = new_ws
231
226
  else
@@ -1,3 +1,3 @@
1
1
  class PuppetLint
2
- VERSION = '2.1.1'
2
+ VERSION = '2.2.0'
3
3
  end
@@ -0,0 +1,5 @@
1
+ jenkins::cli::exec { "create-jenkins-credentials-${title}":
2
+ # lint:ignore:140chars
3
+ unless => "for i in \$(seq 1 ${::jenkins::cli_tries}); do \$HELPER_CMD credential_info ${title} && break || sleep ${::jenkins::cli_try_sleep}; done | grep ${title}",
4
+ # lint:end
5
+ }