rubocop 0.23.0 → 0.24.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +35 -1
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +6 -6
  6. data/config/default.yml +25 -6
  7. data/config/enabled.yml +20 -0
  8. data/lib/rubocop.rb +10 -13
  9. data/lib/rubocop/cli.rb +23 -20
  10. data/lib/rubocop/cop/lint/def_end_alignment.rb +47 -0
  11. data/lib/rubocop/cop/lint/end_alignment.rb +18 -65
  12. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
  13. data/lib/rubocop/cop/lint/syntax.rb +28 -4
  14. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +1 -1
  15. data/lib/rubocop/cop/lint/unused_block_argument.rb +13 -1
  16. data/lib/rubocop/cop/lint/useless_access_modifier.rb +3 -2
  17. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -9
  18. data/lib/rubocop/cop/lint/useless_setter_call.rb +28 -20
  19. data/lib/rubocop/cop/mixin/access_modifier_node.rb +18 -0
  20. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +4 -2
  21. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +42 -0
  22. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +32 -0
  23. data/lib/rubocop/cop/mixin/surrounding_space.rb +7 -8
  24. data/lib/rubocop/cop/mixin/unused_argument.rb +1 -1
  25. data/lib/rubocop/cop/offense.rb +27 -14
  26. data/lib/rubocop/cop/style/access_modifier_indentation.rb +2 -9
  27. data/lib/rubocop/cop/style/attr.rb +3 -1
  28. data/lib/rubocop/cop/style/class_check.rb +42 -0
  29. data/lib/rubocop/cop/style/each_with_object.rb +5 -1
  30. data/lib/rubocop/cop/style/empty_lines.rb +1 -4
  31. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +2 -8
  32. data/lib/rubocop/cop/style/empty_lines_around_body.rb +1 -4
  33. data/lib/rubocop/cop/style/encoding.rb +3 -5
  34. data/lib/rubocop/cop/style/end_of_line.rb +2 -5
  35. data/lib/rubocop/cop/style/file_name.rb +2 -4
  36. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -1
  37. data/lib/rubocop/cop/style/indentation_consistency.rb +2 -1
  38. data/lib/rubocop/cop/style/indentation_width.rb +25 -5
  39. data/lib/rubocop/cop/style/line_length.rb +59 -5
  40. data/lib/rubocop/cop/style/next.rb +18 -18
  41. data/lib/rubocop/cop/style/numeric_literals.rb +22 -9
  42. data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -0
  43. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  44. data/lib/rubocop/cop/style/semicolon.rb +1 -3
  45. data/lib/rubocop/cop/style/space_after_colon.rb +7 -3
  46. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +3 -1
  47. data/lib/rubocop/cop/style/space_before_comma.rb +16 -0
  48. data/lib/rubocop/cop/style/space_before_semicolon.rb +16 -0
  49. data/lib/rubocop/cop/style/tab.rb +6 -5
  50. data/lib/rubocop/cop/style/trailing_comma.rb +33 -6
  51. data/lib/rubocop/cop/style/trailing_whitespace.rb +4 -3
  52. data/lib/rubocop/cop/style/unneeded_capital_w.rb +6 -0
  53. data/lib/rubocop/cop/style/unneeded_percent_q.rb +45 -0
  54. data/lib/rubocop/cop/style/unneeded_percent_x.rb +2 -3
  55. data/lib/rubocop/cop/style/word_array.rb +1 -1
  56. data/lib/rubocop/cop/team.rb +6 -12
  57. data/lib/rubocop/cop/util.rb +26 -8
  58. data/lib/rubocop/cop/variable_force.rb +3 -6
  59. data/lib/rubocop/cop/variable_force/variable.rb +7 -3
  60. data/lib/rubocop/processed_source.rb +52 -12
  61. data/lib/rubocop/{file_inspector.rb → runner.rb} +50 -59
  62. data/lib/rubocop/version.rb +1 -1
  63. data/relnotes/v0.24.0.md +77 -0
  64. data/rubocop.gemspec +4 -4
  65. data/spec/rubocop/cli_spec.rb +38 -21
  66. data/spec/rubocop/config_loader_spec.rb +7 -6
  67. data/spec/rubocop/config_spec.rb +8 -8
  68. data/spec/rubocop/cop/cop_spec.rb +1 -1
  69. data/spec/rubocop/cop/lint/def_end_alignment_spec.rb +108 -0
  70. data/spec/rubocop/cop/lint/end_alignment_spec.rb +0 -47
  71. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +6 -7
  72. data/spec/rubocop/cop/lint/unused_block_argument_spec.rb +19 -0
  73. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +8 -18
  74. data/spec/rubocop/cop/lint/useless_setter_call_spec.rb +99 -51
  75. data/spec/rubocop/cop/offense_spec.rb +3 -3
  76. data/spec/rubocop/cop/rails/delegate_spec.rb +1 -1
  77. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +12 -0
  78. data/spec/rubocop/cop/style/align_hash_spec.rb +4 -4
  79. data/spec/rubocop/cop/style/align_parameters_spec.rb +1 -1
  80. data/spec/rubocop/cop/style/attr_spec.rb +12 -2
  81. data/spec/rubocop/cop/style/class_check_spec.rb +41 -0
  82. data/spec/rubocop/cop/style/each_with_object_spec.rb +5 -0
  83. data/spec/rubocop/cop/style/if_with_semicolon_spec.rb +5 -0
  84. data/spec/rubocop/cop/style/indentation_width_spec.rb +95 -0
  85. data/spec/rubocop/cop/style/line_length_spec.rb +75 -0
  86. data/spec/rubocop/cop/style/next_spec.rb +28 -0
  87. data/spec/rubocop/cop/style/numeric_literals_spec.rb +10 -0
  88. data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +5 -0
  89. data/spec/rubocop/cop/style/space_after_colon_spec.rb +17 -0
  90. data/spec/rubocop/cop/style/space_around_equals_in_parameter_default_spec.rb +11 -0
  91. data/spec/rubocop/cop/style/space_around_operators_spec.rb +1 -0
  92. data/spec/rubocop/cop/style/space_before_comma_spec.rb +42 -0
  93. data/spec/rubocop/cop/style/space_before_semicolon_spec.rb +28 -0
  94. data/spec/rubocop/cop/style/trailing_comma_spec.rb +37 -15
  95. data/spec/rubocop/cop/style/unneeded_capital_w_spec.rb +8 -10
  96. data/spec/rubocop/cop/style/unneeded_percent_q_spec.rb +72 -0
  97. data/spec/rubocop/cop/style/word_array_spec.rb +6 -0
  98. data/spec/rubocop/cop/team_spec.rb +8 -8
  99. data/spec/rubocop/cop/util_spec.rb +10 -0
  100. data/spec/rubocop/cop/variable_force/assignment_spec.rb +1 -1
  101. data/spec/rubocop/cop/variable_force/locatable_spec.rb +1 -1
  102. data/spec/rubocop/cop/variable_force/scope_spec.rb +1 -1
  103. data/spec/rubocop/cop/variable_force/variable_spec.rb +4 -4
  104. data/spec/rubocop/formatter/base_formatter_spec.rb +5 -5
  105. data/spec/rubocop/formatter/colorizable_spec.rb +2 -2
  106. data/spec/rubocop/formatter/json_formatter_spec.rb +1 -1
  107. data/spec/rubocop/path_util_spec.rb +15 -15
  108. data/spec/rubocop/processed_source_spec.rb +104 -50
  109. data/spec/rubocop/runner_spec.rb +64 -0
  110. data/spec/spec_helper.rb +8 -10
  111. data/spec/support/shared_examples.rb +22 -0
  112. metadata +39 -15
  113. data/lib/rubocop/source_parser.rb +0 -47
  114. data/spec/rubocop/file_inspector_spec.rb +0 -84
  115. data/spec/rubocop/source_parser_spec.rb +0 -85
@@ -13,8 +13,83 @@ describe RuboCop::Cop::Style::LineLength, :config do
13
13
  expect(cop.config_to_allow_offenses).to eq('Max' => 81)
14
14
  end
15
15
 
16
+ it 'highlights excessive characters' do
17
+ inspect_source(cop, '#' * 80 + 'abc')
18
+ expect(cop.highlights).to eq(['abc'])
19
+ end
20
+
16
21
  it "accepts a line that's 80 characters wide" do
17
22
  inspect_source(cop, ['#' * 80])
18
23
  expect(cop.offenses).to be_empty
19
24
  end
25
+
26
+ context 'when AllowURI option is enabled' do
27
+ let(:cop_config) { { 'Max' => 80, 'AllowURI' => true } }
28
+
29
+ context 'and all the excessive characters are part of an URL' do
30
+ # This code example is allowed by AllowURI feature itself :).
31
+ let(:source) { <<-END }
32
+ # Some documentation comment...
33
+ # See: https://github.com/bbatsov/rubocop/commit/3b48d8bdf5b1c2e05e35061837309890f04ab08c
34
+ END
35
+
36
+ it 'accepts the line' do
37
+ inspect_source(cop, source)
38
+ expect(cop.offenses).to be_empty
39
+ end
40
+ end
41
+
42
+ context 'and the excessive characters include a complete URL' do
43
+ # rubocop:disable Style/LineLength
44
+ let(:source) { <<-END }
45
+ # See: http://google.com/, http://gmail.com/, https://maps.google.com/, http://plus.google.com/
46
+ END
47
+ # rubocop:enable Style/LineLength
48
+
49
+ it 'registers an offense for the line' do
50
+ inspect_source(cop, source)
51
+ expect(cop.offenses.size).to eq(1)
52
+ end
53
+
54
+ it 'highlights all the excessive characters' do
55
+ inspect_source(cop, source)
56
+ expect(cop.highlights).to eq(['http://plus.google.com/'])
57
+ end
58
+ end
59
+
60
+ context 'and the excessive characters include part of an URL ' \
61
+ 'and another word' do
62
+ # rubocop:disable Style/LineLength
63
+ let(:source) { <<-END }
64
+ # See: https://github.com/bbatsov/rubocop/commit/3b48d8bdf5b1c2e05e35061837309890f04ab08c and
65
+ # http://google.com/
66
+ END
67
+ # rubocop:enable Style/LineLength
68
+
69
+ it 'registers an offense for the line' do
70
+ inspect_source(cop, source)
71
+ expect(cop.offenses.size).to eq(1)
72
+ end
73
+
74
+ it 'highlights only the non-URL part' do
75
+ inspect_source(cop, source)
76
+ expect(cop.highlights).to eq([' and'])
77
+ end
78
+ end
79
+ end
80
+
81
+ context 'when AllowURI option is disabled' do
82
+ let(:cop_config) { { 'Max' => 80, 'AllowURI' => false } }
83
+
84
+ context 'and all the excessive characters are part of an URL' do
85
+ let(:source) { <<-END }
86
+ # See: https://github.com/bbatsov/rubocop/commit/3b48d8bdf5b1c2e05e35061837309890f04ab08c
87
+ END
88
+
89
+ it 'registers an offense for the line' do
90
+ inspect_source(cop, source)
91
+ expect(cop.offenses.size).to eq(1)
92
+ end
93
+ end
94
+ end
20
95
  end
@@ -7,6 +7,7 @@ describe RuboCop::Cop::Style::Next, :config do
7
7
  let(:cop_config) { {} }
8
8
 
9
9
  it 'finds all kind of loops with condition at the end of the iteration' do
10
+ # TODO: Split this long example into multiple examples.
10
11
  inspect_source(cop,
11
12
  ['3.downto(1) do',
12
13
  ' if o == 1',
@@ -122,6 +123,28 @@ describe RuboCop::Cop::Style::Next, :config do
122
123
  '',
123
124
  'loop do',
124
125
  ' break unless o == 1',
126
+ 'end',
127
+ '',
128
+ 'loop do',
129
+ ' if o == 1',
130
+ ' break',
131
+ ' end',
132
+ 'end'])
133
+ expect(cop.offenses.size).to eq(0)
134
+ end
135
+
136
+ it 'ignores loops with conditional return' do
137
+ inspect_source(cop,
138
+ ['loop do',
139
+ " puts ''",
140
+ ' return if o == 1',
141
+ 'end',
142
+ '',
143
+ 'loop do',
144
+ " puts ''",
145
+ ' if o == 1',
146
+ ' return',
147
+ ' end',
125
148
  'end'])
126
149
  expect(cop.offenses.size).to eq(0)
127
150
  end
@@ -216,4 +239,9 @@ describe RuboCop::Cop::Style::Next, :config do
216
239
  'end'])
217
240
  expect(cop.offenses.size).to eq(0)
218
241
  end
242
+
243
+ it 'does not blow up on empty body until block' do
244
+ inspect_source(cop, 'until sup; end')
245
+ expect(cop.offenses.size).to eq(0)
246
+ end
219
247
  end
@@ -67,4 +67,14 @@ describe RuboCop::Cop::Style::NumericLiterals, :config do
67
67
  corrected = autocorrect_source(cop, ['a = -123456'])
68
68
  expect(corrected).to eq 'a = -123_456'
69
69
  end
70
+
71
+ it 'autocorrects floating-point numbers' do
72
+ corrected = autocorrect_source(cop, ['a = 123456.78'])
73
+ expect(corrected).to eq 'a = 123_456.78'
74
+ end
75
+
76
+ it 'autocorrects negative floating-point numbers' do
77
+ corrected = autocorrect_source(cop, ['a = -123456.78'])
78
+ expect(corrected).to eq 'a = -123_456.78'
79
+ end
70
80
  end
@@ -106,6 +106,11 @@ describe RuboCop::Cop::Style::ParenthesesAroundCondition, :config do
106
106
  end
107
107
  end
108
108
 
109
+ it 'does not blow up when the condition is a ternary op' do
110
+ inspect_source(cop, ['x if (a ? b : c)'])
111
+ expect(cop.offenses.size).to eq(1)
112
+ end
113
+
109
114
  context 'safe assignment is allowed' do
110
115
  it 'accepts = in condition surrounded with parentheses' do
111
116
  inspect_source(cop,
@@ -18,6 +18,23 @@ describe RuboCop::Cop::Style::SpaceAfterColon do
18
18
  expect(cop.messages).to be_empty
19
19
  end
20
20
 
21
+ it 'accepts colon in ternary followed by space' do
22
+ inspect_source(cop, ['x = w ? a : b'])
23
+ expect(cop.messages).to be_empty
24
+ end
25
+
26
+ it 'accepts hash rockets' do
27
+ inspect_source(cop, ['x = {"a"=>1}'])
28
+ expect(cop.messages).to be_empty
29
+ end
30
+
31
+ it 'accepts if' do
32
+ inspect_source(cop, ['x = if w',
33
+ ' a',
34
+ ' end'])
35
+ expect(cop.messages).to be_empty
36
+ end
37
+
21
38
  if RUBY_VERSION >= '2.1'
22
39
  it 'accepts colons denoting required keyword argument' do
23
40
  inspect_source(cop, ['def initialize(table:, nodes:)',
@@ -36,6 +36,17 @@ describe RuboCop::Cop::Style::SpaceAroundEqualsInParameterDefault, :config do
36
36
  new_source = autocorrect_source(cop, ['def f(x, y=0, z=1)', 'end'])
37
37
  expect(new_source).to eq(['def f(x, y = 0, z = 1)', 'end'].join("\n"))
38
38
  end
39
+
40
+ it 'accepts default value assignment with space' do
41
+ inspect_source(cop, ['def f(x, y = +1, z = {})', 'end'])
42
+ expect(cop.messages).to be_empty
43
+ end
44
+
45
+ it 'auto-corrects missing space' do
46
+ new_source = autocorrect_source(cop, ['def f(x=-1, y= 0, z =+1)', 'end'])
47
+ expect(new_source).to eq(['def f(x = -1, y = 0, z = +1)',
48
+ 'end'].join("\n"))
49
+ end
39
50
  end
40
51
 
41
52
  context 'when EnforcedStyle is no_space' do
@@ -130,6 +130,7 @@ describe RuboCop::Cop::Style::SpaceAroundOperators do
130
130
  ' end',
131
131
  '',
132
132
  ' def each &block',
133
+ ' +11',
133
134
  ' end',
134
135
  '',
135
136
  ' def self.search *args',
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::SpaceBeforeComma do
6
+ subject(:cop) { described_class.new }
7
+
8
+ it 'registers an offense for block argument with space before comma' do
9
+ inspect_source(cop, ['each { |s , t| }'])
10
+ expect(cop.messages).to eq(
11
+ ['Space found before comma.'])
12
+ end
13
+
14
+ it 'registers an offense for array index with space before comma' do
15
+ inspect_source(cop, ['formats[0 , 1]'])
16
+ expect(cop.messages).to eq(
17
+ ['Space found before comma.'])
18
+ end
19
+
20
+ it 'registers an offense for method call arg with space before comma' do
21
+ inspect_source(cop, ['a(1 , 2)'])
22
+ expect(cop.messages).to eq(
23
+ ['Space found before comma.'])
24
+ end
25
+
26
+ it 'does not register an offense for no spaces before comma' do
27
+ inspect_source(cop, ['a(1, 2)'])
28
+ expect(cop.messages).to be_empty
29
+ end
30
+
31
+ it 'auto-corrects space before comma' do
32
+ new_source = autocorrect_source(cop,
33
+ 'each { |s , t| a(1 , formats[0 , 1])}')
34
+ expect(new_source).to eq('each { |s, t| a(1, formats[0, 1])}')
35
+ end
36
+
37
+ it 'handles more than one space before a comma' do
38
+ new_source = autocorrect_source(cop,
39
+ 'each { |s , t| a(1 , formats[0 , 1])}')
40
+ expect(new_source).to eq('each { |s, t| a(1, formats[0, 1])}')
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::SpaceBeforeSemicolon do
6
+ subject(:cop) { described_class.new }
7
+
8
+ it 'registers an offense for space before semicolon' do
9
+ inspect_source(cop, ['x = 1 ; y = 2'])
10
+ expect(cop.messages).to eq(
11
+ ['Space found before semicolon.'])
12
+ end
13
+
14
+ it 'does not register an offense for no space before semicolons' do
15
+ inspect_source(cop, ['x = 1; y = 2'])
16
+ expect(cop.messages).to be_empty
17
+ end
18
+
19
+ it 'auto-corrects space before semicolon' do
20
+ new_source = autocorrect_source(cop, 'x = 1 ; y = 2')
21
+ expect(new_source).to eq('x = 1; y = 2')
22
+ end
23
+
24
+ it 'handles more than one space before a semicolon' do
25
+ new_source = autocorrect_source(cop, 'x = 1 ; y = 2')
26
+ expect(new_source).to eq('x = 1; y = 2')
27
+ end
28
+ end
@@ -5,25 +5,26 @@ require 'spec_helper'
5
5
  describe RuboCop::Cop::Style::TrailingComma, :config do
6
6
  subject(:cop) { described_class.new(config) }
7
7
 
8
- shared_examples 'single line lists' do
8
+ shared_examples 'single line lists' do |extra_info|
9
9
  it 'registers an offense for trailing comma in an Array literal' do
10
10
  inspect_source(cop, 'VALUES = [1001, 2020, 3333, ]')
11
11
  expect(cop.messages)
12
- .to eq(['Avoid comma after the last item of an array.'])
12
+ .to eq(["Avoid comma after the last item of an array#{extra_info}."])
13
13
  expect(cop.highlights).to eq([','])
14
14
  end
15
15
 
16
16
  it 'registers an offense for trailing comma in a Hash literal' do
17
17
  inspect_source(cop, 'MAP = { a: 1001, b: 2020, c: 3333, }')
18
18
  expect(cop.messages)
19
- .to eq(['Avoid comma after the last item of a hash.'])
19
+ .to eq(["Avoid comma after the last item of a hash#{extra_info}."])
20
20
  expect(cop.highlights).to eq([','])
21
21
  end
22
22
 
23
23
  it 'registers an offense for trailing comma in a method call' do
24
24
  inspect_source(cop, 'some_method(a, b, c, )')
25
25
  expect(cop.messages)
26
- .to eq(['Avoid comma after the last parameter of a method call.'])
26
+ .to eq(['Avoid comma after the last parameter of a method ' \
27
+ "call#{extra_info}."])
27
28
  expect(cop.highlights).to eq([','])
28
29
  end
29
30
 
@@ -31,7 +32,8 @@ describe RuboCop::Cop::Style::TrailingComma, :config do
31
32
  ' parameters at the end' do
32
33
  inspect_source(cop, 'some_method(a, b, c: 0, d: 1, )')
33
34
  expect(cop.messages)
34
- .to eq(['Avoid comma after the last parameter of a method call.'])
35
+ .to eq(['Avoid comma after the last parameter of a method ' \
36
+ "call#{extra_info}."])
35
37
  expect(cop.highlights).to eq([','])
36
38
  end
37
39
 
@@ -78,12 +80,13 @@ describe RuboCop::Cop::Style::TrailingComma, :config do
78
80
  context 'with single line list of values' do
79
81
  context 'when EnforcedStyleForMultiline is no_comma' do
80
82
  let(:cop_config) { { 'EnforcedStyleForMultiline' => 'no_comma' } }
81
- include_examples 'single line lists'
83
+ include_examples 'single line lists', ''
82
84
  end
83
85
 
84
86
  context 'when EnforcedStyleForMultiline is comma' do
85
87
  let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } }
86
- include_examples 'single line lists'
88
+ include_examples 'single line lists',
89
+ ', unless each item is on its own line'
87
90
  end
88
91
  end
89
92
 
@@ -157,13 +160,21 @@ describe RuboCop::Cop::Style::TrailingComma, :config do
157
160
  context 'when EnforcedStyleForMultiline is comma' do
158
161
  let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } }
159
162
 
160
- it 'accepts Array literal with no trailing comma when closing bracket ' \
161
- 'is on same line as last value' do
162
- inspect_source(cop, ['VALUES = [',
163
- ' 1001,',
164
- ' 2020,',
165
- ' 3333]'])
166
- expect(cop.offenses).to be_empty
163
+ context 'when closing bracket is on same line as last value' do
164
+ it 'accepts Array literal with no trailing comma' do
165
+ inspect_source(cop, ['VALUES = [',
166
+ ' 1001,',
167
+ ' 2020,',
168
+ ' 3333]'])
169
+ expect(cop.offenses).to be_empty
170
+ end
171
+
172
+ it 'accepts a method call with Hash as last parameter split on ' \
173
+ 'multiple lines' do
174
+ inspect_source(cop, ['some_method(a: "b",',
175
+ ' c: "d")'])
176
+ expect(cop.offenses).to be_empty
177
+ end
167
178
  end
168
179
 
169
180
  it 'accepts Array literal with two of the values on the same line' do
@@ -174,6 +185,17 @@ describe RuboCop::Cop::Style::TrailingComma, :config do
174
185
  expect(cop.offenses).to be_empty
175
186
  end
176
187
 
188
+ it 'registers an offense for an Array literal with two of the values ' \
189
+ 'on the same line and a trailing comma' do
190
+ inspect_source(cop, ['VALUES = [',
191
+ ' 1001, 2020,',
192
+ ' 3333,',
193
+ ' ]'])
194
+ expect(cop.messages)
195
+ .to eq(['Avoid comma after the last item of an array, unless each ' \
196
+ 'item is on its own line.'])
197
+ end
198
+
177
199
  it 'registers an offense for no trailing comma in a Hash literal' do
178
200
  inspect_source(cop, ['MAP = { a: 1001,',
179
201
  ' b: 2020,',
@@ -248,7 +270,7 @@ describe RuboCop::Cop::Style::TrailingComma, :config do
248
270
  " 'auth' => <<-HELP.chomp",
249
271
  '...',
250
272
  'HELP',
251
- '},)']) # We still need a comma after the hash.
273
+ '})'])
252
274
  expect(cop.offenses).to be_empty
253
275
  end
254
276
  end
@@ -71,15 +71,13 @@ describe RuboCop::Cop::Style::UnneededCapitalW do
71
71
  expect(cop.offenses).to be_empty
72
72
  end
73
73
 
74
- # TESTS FOR AUTOCORRECTION
75
-
76
- # it 'auto-corrects an array of words' do
77
- # new_source = autocorrect_source(cop, "['one', %q(two), 'three']")
78
- # expect(new_source).to eq('%w(one two three)')
79
- # end
74
+ it 'auto-corrects an array of words' do
75
+ new_source = autocorrect_source(cop, '%W(one two three)')
76
+ expect(new_source).to eq('%w(one two three)')
77
+ end
80
78
 
81
- # it 'auto-corrects an array of words and character constants' do
82
- # new_source = autocorrect_source(cop, '[%{one}, %Q(two), ?\n, ?\t]')
83
- # expect(new_source).to eq('%W(one two \n \t)')
84
- # end
79
+ it 'auto-corrects an array of words and character constants' do
80
+ new_source = autocorrect_source(cop, '%W(one two ?\n ?\t)')
81
+ expect(new_source).to eq('%w(one two ?\n ?\t)')
82
+ end
85
83
  end
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::UnneededPercentQ do
6
+ subject(:cop) { described_class.new }
7
+
8
+ context 'with %q strings' do
9
+ it 'registers an offense for only single quotes' do
10
+ inspect_source(cop, "%q('hi')")
11
+ expect(cop.messages).to eq(['Use `%q` only for strings that contain ' \
12
+ 'both single quotes and double quotes.'])
13
+ end
14
+
15
+ it 'registers an offense for only double quotes' do
16
+ inspect_source(cop, '%q("hi")')
17
+ expect(cop.offenses.size).to eq(1)
18
+ end
19
+
20
+ it 'accepts a string with single quotes and double quotes' do
21
+ inspect_source(cop, %Q(%q('"hi"')))
22
+ expect(cop.offenses).to be_empty
23
+ end
24
+
25
+ it 'normally auto-corrects %q to single quotes' do
26
+ new_source = autocorrect_source(cop, '%q(hi)')
27
+ expect(new_source).to eq("'hi'")
28
+ end
29
+
30
+ it 'auto-corrects %q to double quotes if necessary' do
31
+ new_source = autocorrect_source(cop, "%q('hi')")
32
+ expect(new_source).to eq(%q("'hi'"))
33
+ end
34
+ end
35
+
36
+ context 'with %Q strings' do
37
+ it 'registers an offense for static string with only double quotes' do
38
+ inspect_source(cop, '%Q("hi")')
39
+ expect(cop.messages).to eq(['Use `%Q` only for strings that contain ' \
40
+ 'both single quotes and double quotes, or ' \
41
+ 'for dynamic strings that contain double ' \
42
+ 'quotes.'])
43
+ end
44
+
45
+ it 'accepts a string with single quotes and double quotes' do
46
+ inspect_source(cop, %Q(%Q('"hi"')))
47
+ expect(cop.offenses).to be_empty
48
+ end
49
+
50
+ it 'accepts a dynamic %Q string with double quotes' do
51
+ inspect_source(cop, '%Q("hi#{4}")')
52
+ expect(cop.offenses).to be_empty
53
+ end
54
+
55
+ it 'auto-corrects static %Q to double quotes' do
56
+ new_source = autocorrect_source(cop, '%Q(hi)')
57
+ # One could argue that the double quotes are not necessary for a static
58
+ # string, but that's the job of the StringLiterals cop to check.
59
+ expect(new_source).to eq('"hi"')
60
+ end
61
+
62
+ it 'auto-corrects static %Q with inner double quotes to single quotes' do
63
+ new_source = autocorrect_source(cop, '%Q("hi")')
64
+ expect(new_source).to eq(%q('"hi"'))
65
+ end
66
+
67
+ it 'auto-corrects dynamic %Q to double quotes' do
68
+ new_source = autocorrect_source(cop, '%Q(hi #{func})')
69
+ expect(new_source).to eq('"hi #{func}"')
70
+ end
71
+ end
72
+ end