Skip to content

Commit 0207c1f

Browse files
author
Sergei Gerasenko
committed
Create a new plugin for ensuring a single space before a '=>'
This will trigger a warning only for resources with single parameters such as: ``` file { 'foo': ensure⎵⎵=> file, } ```
1 parent 1be24a2 commit 0207c1f

File tree

3 files changed

+200
-1
lines changed

3 files changed

+200
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ Any flag that can be specified on the command line can also be specified in the
117117
Or to specify an allowlist of allowed checks, include a line like:
118118

119119
```
120-
--only-checks=trailing_whitespace,hard_tabs,duplicate_params,double_quoted_strings,unquoted_file_mode,only_variable_string,variables_not_enclosed,single_quote_string_with_variables,variable_contains_dash,ensure_not_symlink_target,unquoted_resource_title,relative_classname_inclusion,file_mode,resource_reference_without_title_capital,leading_zero,arrow_alignment,variable_is_lowercase,ensure_first_param,resource_reference_without_whitespace,file_ensure,trailing_comma,leading_zero
120+
--only-checks=trailing_whitespace,hard_tabs,duplicate_params,double_quoted_strings,unquoted_file_mode,only_variable_string,variables_not_enclosed,single_quote_string_with_variables,variable_contains_dash,ensure_not_symlink_target,unquoted_resource_title,relative_classname_inclusion,file_mode,resource_reference_without_title_capital,leading_zero,arrow_alignment,space_before_arrow,variable_is_lowercase,ensure_first_param,resource_reference_without_whitespace,file_ensure,trailing_comma,leading_zero
121121
```
122122

123123
Please note that there is an important difference between reading options from the command line and reading options from a configuration file: In the former case the shell interprets one level of quotes. That does not happen in the latter case. So, it would make sense to quote some configuration values on the command line, like so:
@@ -253,6 +253,7 @@ For a complete list of checks, and how to resolve errors on each check, see the
253253
* Should not exceed an 140-character line width.
254254
* An exception has been made for `source => 'puppet://...'` lines as splitting these over multiple lines decreases the readability of the manifests.
255255
* Should align arrows (`=>`) within blocks of attributes.
256+
* Should contain at most a single space before an arrows(`=>`) where the parameter block contains exactly one parameter.
256257

257258
### Quoting
258259

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# frozen_string_literal: true
2+
3+
# Check the manifest tokens for any arrows (=>) that have too much space
4+
# before them in situations when a given resource has at most one line with
5+
# such arrows. For example:
6+
7+
# file {
8+
# # too much space after "foo"
9+
# foo⎵⎵=>⎵'bar'
10+
# }
11+
#
12+
# file {
13+
# # too much space after 'bar'
14+
# foo⎵=>⎵{ bar⎵⎵=>⎵'baz' }
15+
# }
16+
#
17+
18+
# Linting multi-parameter resources like this:
19+
#
20+
# package { 'xxx':
21+
# foo => 'bar',
22+
# bar => 'baz',
23+
# }
24+
#
25+
# is handled by the "arrow_alignment") plugin.
26+
27+
PuppetLint.new_check(:space_before_arrow) do
28+
def check
29+
resource_indexes.each do |res_idx|
30+
resource_tokens = res_idx[:tokens]
31+
resource_tokens.reject! do |token|
32+
Set[:COMMENT, :SLASH_COMMENT, :MLCOMMENT].include?(token.type)
33+
end
34+
35+
first_arrow = resource_tokens.index { |r| r.type == :FARROW }
36+
last_arrow = resource_tokens.rindex { |r| r.type == :FARROW }
37+
next if first_arrow.nil?
38+
next if last_arrow.nil?
39+
40+
# If this is a single line resource, skip it
41+
next unless resource_tokens[first_arrow].line == resource_tokens[last_arrow].line
42+
43+
resource_tokens.select { |token| token.type == :FARROW }.each do |token|
44+
prev_token = token.prev_token
45+
next unless prev_token
46+
next if prev_token.value == ' '
47+
48+
line = prev_token.line
49+
column = prev_token.column
50+
51+
notify(
52+
:warning,
53+
message: "there should be a single space before '=>' on line #{line}, column #{column}",
54+
line: line,
55+
column: column,
56+
token: prev_token
57+
)
58+
end
59+
end
60+
end
61+
62+
def fix(problem)
63+
token = problem[:token]
64+
65+
if token.type == :WHITESPACE
66+
token.value = ' '
67+
return
68+
end
69+
70+
add_token(tokens.index(token), PuppetLint::Lexer::Token.new(:WHITESPACE, ' ', 0, 0))
71+
end
72+
end
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
require 'spec_helper'
2+
3+
describe 'space_before_arrow' do
4+
let(:msg) { %q{there should be a single space before '=>' on line %d, column %d} }
5+
6+
context 'with code that should not trigger any warnings' do
7+
context 'resource with multiple parameters on different lines' do
8+
let(:code) do
9+
<<-END
10+
file { 'foo':
11+
foo => bar,
12+
bar => buzz,
13+
}
14+
END
15+
end
16+
17+
it 'does not detect any problems' do
18+
expect(problems).to be_empty
19+
end
20+
end
21+
22+
context 'resource with single param and normal spacing' do
23+
let(:code) do
24+
<<-END
25+
file { 'foo':
26+
foo => bar,
27+
}
28+
END
29+
end
30+
31+
it 'does not detect any problems' do
32+
expect(problems).to be_empty
33+
end
34+
end
35+
36+
context 'resource with multiple params and normal spacing' do
37+
let(:code) do
38+
<<-END
39+
file { 'foo':
40+
foo => { "bar" => "baz" },
41+
}
42+
END
43+
end
44+
45+
it 'does not detect any problems' do
46+
expect(problems).to be_empty
47+
end
48+
end
49+
end
50+
51+
context 'resource with a single param and simple value with too much space before arrow' do
52+
let(:code) do
53+
<<-END
54+
file { 'foo':
55+
foo => bar,
56+
}
57+
END
58+
end
59+
60+
context 'with fix disabled' do
61+
it 'does not detect any problems' do
62+
expect(problems.size).to eq(1)
63+
end
64+
65+
it 'produces 1 warning' do
66+
expect(problems).to contain_warning(msg % [2, 14]).on_line(2).in_column(14)
67+
end
68+
end
69+
70+
context 'with fix enabled' do
71+
before do
72+
PuppetLint.configuration.fix = true
73+
end
74+
75+
after do
76+
PuppetLint.configuration.fix = false
77+
end
78+
79+
it 'detects the problem' do
80+
expect(problems.size).to eq(1)
81+
end
82+
83+
it 'fixes the manifest' do
84+
expect(problems).to contain_fixed(msg % [2, 14])
85+
end
86+
end
87+
end
88+
89+
context 'resource with a single param, a hash as value and bad spacing within the hash' do
90+
let(:code) do
91+
<<-END
92+
file { 'foo':
93+
foo => { "bar" => "baz" },
94+
}
95+
END
96+
end
97+
98+
context 'with fix disabled' do
99+
it 'does not detect any problems' do
100+
expect(problems.size).to eq(1)
101+
end
102+
103+
it 'produces a warning' do
104+
expect(problems).to contain_warning(msg % [2, 25]).on_line(2).in_column(25)
105+
end
106+
end
107+
108+
context 'with fix enabled' do
109+
before do
110+
PuppetLint.configuration.fix = true
111+
end
112+
113+
after do
114+
PuppetLint.configuration.fix = false
115+
end
116+
117+
it 'detects the problem' do
118+
expect(problems.size).to eq(1)
119+
end
120+
121+
it 'fixes the manifest' do
122+
expect(problems).to contain_fixed(msg % [2, 25])
123+
end
124+
end
125+
end
126+
end

0 commit comments

Comments
 (0)