puppet-lint 0.4.0.pre1 → 1.0.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.
Files changed (70) hide show
  1. data/.travis.yml +3 -4
  2. data/Gemfile +2 -5
  3. data/README.md +2 -149
  4. data/Rakefile +0 -5
  5. data/lib/puppet-lint.rb +74 -20
  6. data/lib/puppet-lint/bin.rb +20 -85
  7. data/lib/puppet-lint/checkplugin.rb +158 -12
  8. data/lib/puppet-lint/checks.rb +39 -222
  9. data/lib/puppet-lint/configuration.rb +12 -31
  10. data/lib/puppet-lint/data.rb +329 -0
  11. data/lib/puppet-lint/lexer.rb +37 -30
  12. data/lib/puppet-lint/lexer/token.rb +14 -16
  13. data/lib/puppet-lint/monkeypatches/string_prepend.rb +6 -0
  14. data/lib/puppet-lint/optparser.rb +105 -0
  15. data/lib/puppet-lint/plugins.rb +28 -9
  16. data/lib/puppet-lint/plugins/check_classes.rb +162 -238
  17. data/lib/puppet-lint/plugins/check_comments.rb +40 -25
  18. data/lib/puppet-lint/plugins/check_conditionals.rb +16 -20
  19. data/lib/puppet-lint/plugins/check_documentation.rb +14 -20
  20. data/lib/puppet-lint/plugins/check_nodes.rb +23 -0
  21. data/lib/puppet-lint/plugins/check_resources.rb +127 -141
  22. data/lib/puppet-lint/plugins/check_strings.rb +133 -107
  23. data/lib/puppet-lint/plugins/check_variables.rb +11 -11
  24. data/lib/puppet-lint/plugins/check_whitespace.rb +86 -92
  25. data/lib/puppet-lint/tasks/puppet-lint.rb +17 -1
  26. data/lib/puppet-lint/version.rb +1 -1
  27. data/puppet-lint.gemspec +4 -2
  28. data/spec/fixtures/test/manifests/ignore.pp +1 -0
  29. data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
  30. data/spec/puppet-lint/bin_spec.rb +104 -84
  31. data/spec/puppet-lint/configuration_spec.rb +19 -19
  32. data/spec/puppet-lint/ignore_overrides_spec.rb +97 -0
  33. data/spec/puppet-lint/lexer/token_spec.rb +9 -9
  34. data/spec/puppet-lint/lexer_spec.rb +352 -325
  35. data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +77 -23
  36. data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +14 -12
  37. data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +18 -14
  38. data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +30 -30
  39. data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +31 -26
  40. data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +34 -28
  41. data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +14 -12
  42. data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +74 -30
  43. data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +27 -20
  44. data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +78 -13
  45. data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +17 -12
  46. data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +13 -10
  47. data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +21 -16
  48. data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +69 -0
  49. data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +42 -38
  50. data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +22 -10
  51. data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +81 -18
  52. data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +69 -112
  53. data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +27 -20
  54. data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +177 -171
  55. data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +165 -88
  56. data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +97 -22
  57. data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +25 -0
  58. data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +97 -111
  59. data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +10 -9
  60. data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +53 -53
  61. data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +26 -14
  62. data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +10 -9
  63. data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +31 -15
  64. data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +340 -322
  65. data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +30 -23
  66. data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +42 -41
  67. data/spec/puppet-lint_spec.rb +3 -3
  68. data/spec/spec_helper.rb +109 -116
  69. metadata +109 -50
  70. data/spec/puppet-lint/plugins/check_classes/class_parameter_defaults_spec.rb +0 -60
@@ -1,40 +1,55 @@
1
- class PuppetLint::Plugins::CheckComments < PuppetLint::CheckPlugin
2
- # Public: Check the manifest tokens for any comments started with slashes
3
- # (//) and record a warning for each instance found.
4
- #
5
- # Returns nothing.
6
- check 'slash_comments' do
1
+ # Public: Check the manifest tokens for any comments started with slashes
2
+ # (//) and record a warning for each instance found.
3
+ PuppetLint.new_check(:slash_comments) do
4
+ def check
7
5
  tokens.select { |token|
8
6
  token.type == :SLASH_COMMENT
9
7
  }.each do |token|
10
- if PuppetLint.configuration.fix
11
- token.type = :COMMENT
12
- notify_type = :fixed
13
- else
14
- notify_type = :warning
15
- end
16
-
17
- notify notify_type, {
18
- :message => '// comment found',
19
- :linenumber => token.line,
20
- :column => token.column,
8
+ notify :warning, {
9
+ :message => '// comment found',
10
+ :line => token.line,
11
+ :column => token.column,
12
+ :token => token,
21
13
  }
22
14
  end
23
15
  end
24
16
 
25
- # Public: Check the manifest tokens for any comments encapsulated with
26
- # slash-asterisks (/* */) and record a warning for each instance found.
27
- #
28
- # Returns nothing.
29
- check 'star_comments' do
17
+ def fix(problem)
18
+ problem[:token].type = :COMMENT
19
+ end
20
+ end
21
+
22
+ # Public: Check the manifest tokens for any comments encapsulated with
23
+ # slash-asterisks (/* */) and record a warning for each instance found.
24
+ PuppetLint.new_check(:star_comments) do
25
+ def check
30
26
  tokens.select { |token|
31
27
  token.type == :MLCOMMENT
32
28
  }.each do |token|
33
29
  notify :warning, {
34
- :message => '/* */ comment found',
35
- :linenumber => token.line,
36
- :column => token.column,
30
+ :message => '/* */ comment found',
31
+ :line => token.line,
32
+ :column => token.column,
33
+ :token => token,
37
34
  }
38
35
  end
39
36
  end
37
+
38
+ def fix(problem)
39
+ comment_lines = problem[:token].value.split("\n")
40
+ first_line = comment_lines.shift
41
+ problem[:token].type = :COMMENT
42
+ problem[:token].value = " #{first_line}"
43
+
44
+ index = tokens.index(problem[:token].next_token)
45
+ comment_lines.reverse.each do |line|
46
+ [
47
+ PuppetLint::Lexer::Token.new(:COMMENT, " #{line}", 0, 0),
48
+ PuppetLint::Lexer::Token.new(:INDENT, problem[:token].prev_token.value.dup, 0, 0),
49
+ PuppetLint::Lexer::Token.new(:NEWLINE, "\n", 0, 0),
50
+ ].each do |new_token|
51
+ tokens.insert(index, new_token)
52
+ end
53
+ end
54
+ end
40
55
  end
@@ -1,21 +1,17 @@
1
- class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
2
- # Public: Test the manifest tokens for any selectors embedded within resource
3
- # declarations and record a warning for each instance found.
4
- #
5
- # Returns nothing.
6
- check 'selector_inside_resource' do
1
+ # Public: Test the manifest tokens for any selectors embedded within resource
2
+ # declarations and record a warning for each instance found.
3
+ PuppetLint.new_check(:selector_inside_resource) do
4
+ def check
7
5
  resource_indexes.each do |resource|
8
- resource_tokens = tokens[resource[:start]..resource[:end]]
9
-
10
- resource_tokens.each do |token|
6
+ resource[:tokens].each do |token|
11
7
  if token.type == :FARROW
12
8
  if token.next_code_token.type == :VARIABLE
13
9
  unless token.next_code_token.next_code_token.nil?
14
10
  if token.next_code_token.next_code_token.type == :QMARK
15
11
  notify :warning, {
16
- :message => 'selector inside resource block',
17
- :linenumber => token.line,
18
- :column => token.column,
12
+ :message => 'selector inside resource block',
13
+ :line => token.line,
14
+ :column => token.column,
19
15
  }
20
16
  end
21
17
  end
@@ -24,12 +20,12 @@ class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
24
20
  end
25
21
  end
26
22
  end
23
+ end
27
24
 
28
- # Public: Test the manifest tokens for any case statements that do not
29
- # contain a "default" case and record a warning for each instance found.
30
- #
31
- # Returns nothing.
32
- check 'case_without_default' do
25
+ # Public: Test the manifest tokens for any case statements that do not
26
+ # contain a "default" case and record a warning for each instance found.
27
+ PuppetLint.new_check(:case_without_default) do
28
+ def check
33
29
  case_indexes = []
34
30
 
35
31
  tokens.each_index do |token_idx|
@@ -55,9 +51,9 @@ class PuppetLint::Plugins::CheckConditionals < PuppetLint::CheckPlugin
55
51
 
56
52
  unless case_tokens.index { |r| r.type == :DEFAULT }
57
53
  notify :warning, {
58
- :message => 'case statement without a default case',
59
- :linenumber => case_tokens.first.line,
60
- :column => case_tokens.first.column,
54
+ :message => 'case statement without a default case',
55
+ :line => case_tokens.first.line,
56
+ :column => case_tokens.first.column,
61
57
  }
62
58
  end
63
59
  end
@@ -1,25 +1,19 @@
1
- class PuppetLint::Plugins::CheckDocumentation < PuppetLint::CheckPlugin
2
- check 'documentation' do
3
- comment_tokens = {
4
- :COMMENT => true,
5
- :MLCOMMENT => true,
6
- :SLASH_COMMENT => true,
7
- }
8
-
9
- whitespace_tokens = {
10
- :WHITESPACE => true,
11
- :NEWLINE => true,
12
- :INDENT => true,
13
- }
1
+ # Public: Check the manifest tokens for any class or defined type that does not
2
+ # have a comment directly above it (hopefully, explaining the usage of it) and
3
+ # record a warning for each instance found.
4
+ PuppetLint.new_check(:documentation) do
5
+ COMMENT_TOKENS = Set[:COMMENT, :MLCOMMENT, :SLASH_COMMENT]
6
+ WHITESPACE_TOKENS = Set[:WHITESPACE, :NEWLINE, :INDENT]
14
7
 
8
+ def check
15
9
  (class_indexes + defined_type_indexes).each do |item_idx|
16
- prev_token = tokens[item_idx[:start] - 1]
17
- while (!prev_token.nil?) && whitespace_tokens.include?(prev_token.type)
10
+ prev_token = item_idx[:tokens].first.prev_token
11
+ while (!prev_token.nil?) && WHITESPACE_TOKENS.include?(prev_token.type)
18
12
  prev_token = prev_token.prev_token
19
13
  end
20
14
 
21
- unless (!prev_token.nil?) && comment_tokens.include?(prev_token.type)
22
- first_token = tokens[item_idx[:start]]
15
+ unless (!prev_token.nil?) && COMMENT_TOKENS.include?(prev_token.type)
16
+ first_token = item_idx[:tokens].first
23
17
  if first_token.type == :CLASS
24
18
  type = 'class'
25
19
  else
@@ -27,9 +21,9 @@ class PuppetLint::Plugins::CheckDocumentation < PuppetLint::CheckPlugin
27
21
  end
28
22
 
29
23
  notify :warning, {
30
- :message => "#{type} not documented",
31
- :linenumber => first_token.line,
32
- :column => first_token.column,
24
+ :message => "#{type} not documented",
25
+ :line => first_token.line,
26
+ :column => first_token.column,
33
27
  }
34
28
  end
35
29
  end
@@ -0,0 +1,23 @@
1
+ # Public: Check the manifest for unquoted node names and record a warning for
2
+ # each instance found.
3
+ PuppetLint.new_check(:unquoted_node_name) do
4
+ def check
5
+ tokens.select { |r|
6
+ r.type == :NODE && r.next_code_token.type == :NAME
7
+ }.each do |token|
8
+ value_token = token.next_code_token
9
+ unless value_token.value == 'default'
10
+ notify :warning, {
11
+ :message => 'unquoted node name found',
12
+ :line => value_token.line,
13
+ :column => value_token.column,
14
+ :token => value_token,
15
+ }
16
+ end
17
+ end
18
+ end
19
+
20
+ def fix(problem)
21
+ problem[:token].type = :SSTRING
22
+ end
23
+ end
@@ -1,208 +1,194 @@
1
- class PuppetLint::Plugins::CheckResources < PuppetLint::CheckPlugin
2
- # Public: Check the manifest tokens for any resource titles / namevars that
3
- # are not quoted and record a warning for each instance found.
4
- #
5
- # Return nothing.
6
- check 'unquoted_resource_title' do
1
+ # Public: Check the manifest tokens for any resource titles / namevars that
2
+ # are not quoted and record a warning for each instance found.
3
+ PuppetLint.new_check(:unquoted_resource_title) do
4
+ def check
7
5
  title_tokens.each do |token|
8
6
  if token.type == :NAME
9
- if PuppetLint.configuration.fix
10
- token.type = :SSTRING
11
- notify_type = :fixed
12
- else
13
- notify_type = :warning
14
- end
15
-
16
- notify notify_type, {
17
- :message => 'unquoted resource title',
18
- :linenumber => token.line,
19
- :column => token.column,
7
+ notify :warning, {
8
+ :message => 'unquoted resource title',
9
+ :line => token.line,
10
+ :column => token.column,
11
+ :token => token,
20
12
  }
21
13
  end
22
14
  end
23
15
  end
24
16
 
25
- # Public: Check the tokens of each resource instance for an ensure parameter
26
- # and if found, check that it is the first parameter listed. If it is not
27
- # the first parameter, record a warning.
28
- #
29
- # Returns nothing.
30
- check 'ensure_first_param' do
31
- resource_indexes.each do |resource|
32
- resource_tokens = tokens[resource[:start]..resource[:end]]
17
+ def fix(problem)
18
+ problem[:token].type = :SSTRING
19
+ end
20
+ end
33
21
 
34
- param_tokens = resource_tokens.select { |resource_token|
35
- resource_token.type == :NAME && resource_token.next_code_token.type == :FARROW
36
- }
37
- ensure_attr_index = param_tokens.index { |resource_token|
38
- resource_token.value == 'ensure'
22
+ # Public: Check the tokens of each resource instance for an ensure parameter
23
+ # and if found, check that it is the first parameter listed. If it is not
24
+ # the first parameter, record a warning.
25
+ PuppetLint.new_check(:ensure_first_param) do
26
+ def check
27
+ resource_indexes.each do |resource|
28
+ ensure_attr_index = resource[:param_tokens].index { |param_token|
29
+ param_token.value == 'ensure'
39
30
  }
40
31
 
41
32
  unless ensure_attr_index.nil?
42
33
  if ensure_attr_index > 0
43
- ensure_token = param_tokens[ensure_attr_index]
34
+ ensure_token = resource[:param_tokens][ensure_attr_index]
44
35
  notify :warning, {
45
- :message => "ensure found on line but it's not the first attribute",
46
- :linenumber => ensure_token.line,
47
- :column => ensure_token.column,
36
+ :message => "ensure found on line but it's not the first attribute",
37
+ :line => ensure_token.line,
38
+ :column => ensure_token.column,
48
39
  }
49
40
  end
50
41
  end
51
42
  end
52
43
  end
44
+ end
53
45
 
54
- check 'duplicate_params' do
46
+ # Public: Check the tokens of each resource instance for any duplicate
47
+ # parameters and record a warning for each instance found.
48
+ PuppetLint.new_check(:duplicate_params) do
49
+ def check
55
50
  resource_indexes.each do |resource|
56
- resource_tokens = tokens[resource[:start]..resource[:end]].reject { |r|
57
- formatting_tokens.include? r.type
58
- }
59
-
60
51
  seen_params = {}
61
52
  level = 0
62
- resource_tokens.each_with_index do |token, idx|
53
+
54
+ resource[:tokens].each_with_index do |token, idx|
63
55
  case token.type
64
56
  when :LBRACE
65
57
  level += 1
66
58
  next
67
59
  when :RBRACE
68
- seen_params[level] = {}
60
+ seen_params.delete(level)
69
61
  level -= 1
70
62
  next
71
- end
72
- seen_params[level] ||= {}
73
-
74
- if token.type == :FARROW
75
- prev_token = resource_tokens[idx - 1]
63
+ when :FARROW
64
+ prev_token = token.prev_code_token
76
65
  next unless prev_token.type == :NAME
77
- if seen_params[level].include? prev_token.value
66
+
67
+ if (seen_params[level] ||= Set.new).include?(prev_token.value)
78
68
  notify :error, {
79
- :message => 'duplicate parameter found in resource',
80
- :linenumber => prev_token.line,
81
- :column => prev_token.column,
69
+ :message => 'duplicate parameter found in resource',
70
+ :line => prev_token.line,
71
+ :column => prev_token.column,
82
72
  }
83
73
  else
84
- seen_params[level][prev_token.value] = true
74
+ seen_params[level] << prev_token.value
85
75
  end
86
76
  end
87
77
  end
88
78
  end
89
79
  end
80
+ end
90
81
 
91
- # Public: Check the tokens of each File resource instance for a mode
92
- # parameter and if found, record a warning if the value of that parameter is
93
- # not a quoted string.
94
- #
95
- # Returns nothing.
96
- check 'unquoted_file_mode' do
97
- resource_indexes.each do |resource|
98
- resource_tokens = tokens[resource[:start]..resource[:end]]
99
- prev_tokens = tokens[0..resource[:start]]
82
+ # Public: Check the tokens of each File resource instance for a mode
83
+ # parameter and if found, record a warning if the value of that parameter is
84
+ # not a quoted string.
85
+ PuppetLint.new_check(:unquoted_file_mode) do
86
+ TOKEN_TYPES = Set[:NAME, :NUMBER]
100
87
 
101
- lbrace_idx = prev_tokens.rindex { |r|
102
- r.type == :LBRACE
103
- }
104
-
105
- resource_type_token = tokens[lbrace_idx].prev_code_token
106
- if resource_type_token.value == "file"
107
- resource_tokens.select { |resource_token|
108
- resource_token.type == :NAME and resource_token.value == 'mode'
109
- }.each do |resource_token|
110
- value_token = resource_token.next_code_token.next_code_token
111
- if {:NAME => true, :NUMBER => true}.include? value_token.type
112
- if PuppetLint.configuration.fix
113
- value_token.type = :SSTRING
114
- notify_type = :fixed
115
- else
116
- notify_type = :warning
117
- end
118
-
119
- notify notify_type, {
120
- :message => 'unquoted file mode',
121
- :linenumber => value_token.line,
122
- :column => value_token.column,
123
- }
124
- end
88
+ def check
89
+ resource_indexes.each do |resource|
90
+ if resource[:type].value == "file"
91
+ resource[:param_tokens].select { |param_token|
92
+ param_token.value == 'mode' &&
93
+ TOKEN_TYPES.include?(param_token.next_code_token.next_code_token.type)
94
+ }.each do |param_token|
95
+ value_token = param_token.next_code_token.next_code_token
96
+ notify :warning, {
97
+ :message => 'unquoted file mode',
98
+ :line => value_token.line,
99
+ :column => value_token.column,
100
+ :token => value_token,
101
+ }
125
102
  end
126
103
  end
127
104
  end
128
105
  end
129
106
 
130
- # Public: Check the tokens of each File resource instance for a mode
131
- # parameter and if found, record a warning if the value of that parameter is
132
- # not a 4 digit octal value (0755) or a symbolic mode ('o=rwx,g+r').
133
- #
134
- # Returns nothing.
135
- check 'file_mode' do
136
- msg = 'mode should be represented as a 4 digit octal value or symbolic mode'
137
- sym_mode = /\A([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*\Z/
138
-
139
- resource_indexes.each do |resource|
140
- resource_tokens = tokens[resource[:start]..resource[:end]]
141
- prev_tokens = tokens[0..resource[:start]]
142
-
143
- lbrace_idx = prev_tokens.rindex { |r|
144
- r.type == :LBRACE
145
- }
146
-
147
- resource_type_token = tokens[lbrace_idx].prev_code_token
148
- if resource_type_token.value == "file"
149
- resource_tokens.select { |resource_token|
150
- resource_token.type == :NAME and resource_token.value == 'mode'
151
- }.each do |resource_token|
152
- value_token = resource_token.next_code_token.next_code_token
107
+ def fix(problem)
108
+ problem[:token].type = :SSTRING
109
+ end
110
+ end
153
111
 
154
- break if value_token.value =~ /\A[0-7]{4}\Z/
155
- break if value_token.type == :VARIABLE
156
- break if value_token.value =~ sym_mode
157
- break if value_token.type == :UNDEF
112
+ # Public: Check the tokens of each File resource instance for a mode
113
+ # parameter and if found, record a warning if the value of that parameter is
114
+ # not a 4 digit octal value (0755) or a symbolic mode ('o=rwx,g+r').
115
+ PuppetLint.new_check(:file_mode) do
116
+ MSG = 'mode should be represented as a 4 digit octal value or symbolic mode'
117
+ SYM_RE = "([ugoa]*[-=+][-=+rstwxXugo]*)(,[ugoa]*[-=+][-=+rstwxXugo]*)*"
118
+ IGNORE_TYPES = Set[:VARIABLE, :UNDEF]
119
+ MODE_RE = Regexp.new(/\A([0-7]{4}|#{SYM_RE})\Z/)
158
120
 
159
- notify_type = :warning
121
+ def check
122
+ resource_indexes.each do |resource|
123
+ if resource[:type].value == "file"
124
+ resource[:param_tokens].select { |param_token|
125
+ param_token.value == 'mode'
126
+ }.each do |param_token|
127
+ value_token = param_token.next_code_token.next_code_token
160
128
 
161
- if PuppetLint.configuration.fix && value_token.value =~ /\A[0-7]{3}\Z/
162
- value_token.value = "0#{value_token.value.to_s}"
163
- value_token.type = :SSTRING
164
- notify_type = :fixed
165
- end
129
+ break if IGNORE_TYPES.include?(value_token.type)
130
+ break if value_token.value =~ MODE_RE
166
131
 
167
- notify notify_type, {
168
- :message => msg,
169
- :linenumber => value_token.line,
170
- :column => value_token.column,
132
+ notify :warning, {
133
+ :message => MSG,
134
+ :line => value_token.line,
135
+ :column => value_token.column,
136
+ :token => value_token,
171
137
  }
172
138
  end
173
139
  end
174
140
  end
175
141
  end
176
142
 
177
- # Public: Check the tokens of each File resource instance for an ensure
178
- # parameter and record a warning if the value of that parameter looks like
179
- # a symlink target (starts with a '/').
180
- #
181
- # Returns nothing.
182
- check 'ensure_not_symlink_target' do
183
- resource_indexes.each do |resource|
184
- resource_tokens = tokens[resource[:start]..resource[:end]]
185
- prev_tokens = tokens[0..resource[:start]]
186
-
187
- lbrace_idx = prev_tokens.rindex { |r|
188
- r.type == :LBRACE
189
- }
143
+ def fix(problem)
144
+ if problem[:token].value =~ /\A[0-7]{3}\Z/
145
+ problem[:token].type = :SSTRING
146
+ problem[:token].value = "0#{problem[:token].value.to_s}"
147
+ else
148
+ raise PuppetLint::NoFix
149
+ end
150
+ end
151
+ end
190
152
 
191
- resource_type_token = tokens[lbrace_idx].prev_code_token
192
- if resource_type_token.value == "file"
193
- resource_tokens.select { |resource_token|
194
- resource_token.type == :NAME and resource_token.value == 'ensure'
153
+ # Public: Check the tokens of each File resource instance for an ensure
154
+ # parameter and record a warning if the value of that parameter looks like
155
+ # a symlink target (starts with a '/').
156
+ PuppetLint.new_check(:ensure_not_symlink_target) do
157
+ def check
158
+ resource_indexes.each do |resource|
159
+ if resource[:type].value == "file"
160
+ resource[:param_tokens].select { |param_token|
161
+ param_token.value == 'ensure'
195
162
  }.each do |ensure_token|
196
163
  value_token = ensure_token.next_code_token.next_code_token
197
164
  if value_token.value.start_with? '/'
198
165
  notify :warning, {
199
- :message => 'symlink target specified in ensure attr',
200
- :linenumber => value_token.line,
201
- :column => value_token.column,
166
+ :message => 'symlink target specified in ensure attr',
167
+ :line => value_token.line,
168
+ :column => value_token.column,
169
+ :param_token => ensure_token,
170
+ :value_token => value_token,
202
171
  }
203
172
  end
204
173
  end
205
174
  end
206
175
  end
207
176
  end
177
+
178
+ def fix(problem)
179
+ index = tokens.index(problem[:value_token])
180
+
181
+ [
182
+ PuppetLint::Lexer::Token.new(:NAME, 'symlink', 0, 0),
183
+ PuppetLint::Lexer::Token.new(:COMMA, ',', 0, 0),
184
+ PuppetLint::Lexer::Token.new(:NEWLINE, "\n", 0, 0),
185
+ PuppetLint::Lexer::Token.new(:INDENT, problem[:param_token].prev_token.value.dup, 0, 0),
186
+ PuppetLint::Lexer::Token.new(:NAME, 'target', 0, 0),
187
+ PuppetLint::Lexer::Token.new(:WHITESPACE, problem[:param_token].next_token.value.dup, 0, 0),
188
+ PuppetLint::Lexer::Token.new(:FARROW, '=>', 0, 0),
189
+ PuppetLint::Lexer::Token.new(:WHITESPACE, ' ', 0, 0),
190
+ ].reverse.each do |new_token|
191
+ tokens.insert(index, new_token)
192
+ end
193
+ end
208
194
  end