puppet-lint 2.1.1 → 2.2.0

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