rubocop 0.26.1 → 0.27.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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -0
  3. data/.rubocop_todo.yml +10 -6
  4. data/.travis.yml +2 -0
  5. data/CHANGELOG.md +30 -0
  6. data/README.md +9 -2
  7. data/assets/logo.png +0 -0
  8. data/assets/output.html.erb +68 -65
  9. data/config/default.yml +42 -7
  10. data/config/disabled.yml +5 -0
  11. data/config/enabled.yml +32 -7
  12. data/lib/rubocop.rb +10 -2
  13. data/lib/rubocop/comment_config.rb +11 -17
  14. data/lib/rubocop/config.rb +20 -16
  15. data/lib/rubocop/config_loader.rb +8 -12
  16. data/lib/rubocop/cop/cop.rb +13 -12
  17. data/lib/rubocop/cop/lint/block_alignment.rb +4 -6
  18. data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -2
  19. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  20. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -3
  21. data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -2
  22. data/lib/rubocop/cop/metrics/abc_size.rb +27 -0
  23. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -4
  24. data/lib/rubocop/cop/metrics/class_length.rb +1 -1
  25. data/lib/rubocop/cop/metrics/line_length.rb +2 -5
  26. data/lib/rubocop/cop/metrics/method_length.rb +2 -2
  27. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +24 -15
  28. data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +15 -2
  29. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +63 -0
  30. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  31. data/lib/rubocop/cop/mixin/if_node.rb +3 -1
  32. data/lib/rubocop/cop/mixin/method_complexity.rb +3 -3
  33. data/lib/rubocop/cop/mixin/{on_method.rb → on_method_def.rb} +3 -3
  34. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +2 -2
  35. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  36. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
  37. data/lib/rubocop/cop/mixin/string_literals_help.rb +28 -0
  38. data/lib/rubocop/cop/rails/delegate.rb +2 -2
  39. data/lib/rubocop/cop/style/access_modifier_indentation.rb +2 -2
  40. data/lib/rubocop/cop/style/accessor_method_name.rb +2 -2
  41. data/lib/rubocop/cop/style/align_hash.rb +16 -12
  42. data/lib/rubocop/cop/style/align_parameters.rb +1 -1
  43. data/lib/rubocop/cop/style/and_or.rb +14 -6
  44. data/lib/rubocop/cop/style/array_join.rb +1 -1
  45. data/lib/rubocop/cop/style/block_comments.rb +16 -8
  46. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +6 -30
  47. data/lib/rubocop/cop/style/case_indentation.rb +20 -12
  48. data/lib/rubocop/cop/style/collection_methods.rb +4 -4
  49. data/lib/rubocop/cop/style/colon_method_call.rb +9 -0
  50. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  51. data/lib/rubocop/cop/style/comment_indentation.rb +22 -22
  52. data/lib/rubocop/cop/style/def_with_parentheses.rb +2 -2
  53. data/lib/rubocop/cop/style/deprecated_hash_methods.rb +1 -1
  54. data/lib/rubocop/cop/style/double_negation.rb +6 -1
  55. data/lib/rubocop/cop/style/else_alignment.rb +93 -0
  56. data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -1
  57. data/lib/rubocop/cop/style/empty_lines.rb +1 -1
  58. data/lib/rubocop/cop/style/empty_lines_around_class_body.rb +34 -0
  59. data/lib/rubocop/cop/style/empty_lines_around_method_body.rb +37 -0
  60. data/lib/rubocop/cop/style/empty_lines_around_module_body.rb +30 -0
  61. data/lib/rubocop/cop/style/encoding.rb +1 -1
  62. data/lib/rubocop/cop/style/format_string.rb +4 -4
  63. data/lib/rubocop/cop/style/indent_array.rb +2 -2
  64. data/lib/rubocop/cop/style/indent_hash.rb +17 -12
  65. data/lib/rubocop/cop/style/indentation_width.rb +27 -19
  66. data/lib/rubocop/cop/style/method_call_parentheses.rb +3 -3
  67. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -1
  68. data/lib/rubocop/cop/style/method_def_parentheses.rb +17 -11
  69. data/lib/rubocop/cop/style/method_name.rb +1 -1
  70. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +174 -0
  71. data/lib/rubocop/cop/style/non_nil_check.rb +12 -15
  72. data/lib/rubocop/cop/style/not.rb +1 -1
  73. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +12 -17
  74. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  75. data/lib/rubocop/cop/style/predicate_name.rb +2 -2
  76. data/lib/rubocop/cop/style/redundant_begin.rb +2 -2
  77. data/lib/rubocop/cop/style/redundant_return.rb +3 -3
  78. data/lib/rubocop/cop/style/redundant_self.rb +3 -3
  79. data/lib/rubocop/cop/style/regexp_literal.rb +17 -13
  80. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -2
  81. data/lib/rubocop/cop/style/single_line_methods.rb +7 -4
  82. data/lib/rubocop/cop/style/space_after_method_name.rb +2 -2
  83. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +17 -11
  84. data/lib/rubocop/cop/style/space_before_block_braces.rb +1 -1
  85. data/lib/rubocop/cop/style/space_inside_block_braces.rb +17 -14
  86. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +10 -6
  87. data/lib/rubocop/cop/style/string_literals.rb +13 -16
  88. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +41 -0
  89. data/lib/rubocop/cop/style/trailing_comma.rb +1 -3
  90. data/lib/rubocop/cop/style/trivial_accessors.rb +3 -3
  91. data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -1
  92. data/lib/rubocop/cop/style/unneeded_percent_q.rb +2 -2
  93. data/lib/rubocop/cop/style/word_array.rb +23 -19
  94. data/lib/rubocop/cop/team.rb +13 -26
  95. data/lib/rubocop/cop/util.rb +5 -0
  96. data/lib/rubocop/cop/variable_force/locatable.rb +7 -13
  97. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  98. data/lib/rubocop/formatter/formatter_set.rb +9 -1
  99. data/lib/rubocop/formatter/html_formatter.rb +83 -55
  100. data/lib/rubocop/formatter/simple_text_formatter.rb +2 -2
  101. data/lib/rubocop/formatter/text_util.rb +25 -0
  102. data/lib/rubocop/options.rb +14 -7
  103. data/lib/rubocop/path_util.rb +11 -7
  104. data/lib/rubocop/runner.rb +7 -2
  105. data/lib/rubocop/version.rb +1 -1
  106. data/relnotes/v0.27.0.md +77 -0
  107. data/rubocop.gemspec +1 -1
  108. data/spec/fixtures/html_formatter/expected.html +495 -0
  109. data/spec/fixtures/html_formatter/project/app/controllers/application_controller.rb +5 -0
  110. data/spec/fixtures/html_formatter/project/app/controllers/books_controller.rb +74 -0
  111. data/spec/fixtures/html_formatter/project/app/models/book.rb +5 -0
  112. data/spec/rubocop/cli_spec.rb +56 -13
  113. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +1 -1
  114. data/spec/rubocop/cop/metrics/abc_size_spec.rb +99 -0
  115. data/spec/rubocop/cop/rails/action_filter_spec.rb +1 -0
  116. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +23 -1
  117. data/spec/rubocop/cop/style/align_hash_spec.rb +13 -0
  118. data/spec/rubocop/cop/style/align_parameters_spec.rb +44 -33
  119. data/spec/rubocop/cop/style/blocks_spec.rb +8 -0
  120. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +9 -9
  121. data/spec/rubocop/cop/style/case_indentation_spec.rb +3 -2
  122. data/spec/rubocop/cop/style/colon_method_call_spec.rb +5 -0
  123. data/spec/rubocop/cop/style/comment_indentation_spec.rb +6 -1
  124. data/spec/rubocop/cop/style/else_alignment_spec.rb +437 -0
  125. data/spec/rubocop/cop/style/empty_lines_around_class_body_spec.rb +75 -0
  126. data/spec/rubocop/cop/style/{empty_lines_around_body_spec.rb → empty_lines_around_method_body_spec.rb} +9 -50
  127. data/spec/rubocop/cop/style/empty_lines_around_module_body_spec.rb +79 -0
  128. data/spec/rubocop/cop/style/file_name_spec.rb +1 -1
  129. data/spec/rubocop/cop/style/format_string_spec.rb +12 -0
  130. data/spec/rubocop/cop/style/indent_array_spec.rb +6 -1
  131. data/spec/rubocop/cop/style/indent_hash_spec.rb +2 -1
  132. data/spec/rubocop/cop/style/indentation_width_spec.rb +765 -722
  133. data/spec/rubocop/cop/style/multiline_operation_indentation_spec.rb +414 -0
  134. data/spec/rubocop/cop/style/non_nil_check_spec.rb +86 -55
  135. data/spec/rubocop/cop/style/single_line_methods_spec.rb +5 -1
  136. data/spec/rubocop/cop/style/space_before_block_braces_spec.rb +2 -1
  137. data/spec/rubocop/cop/style/space_inside_block_braces_spec.rb +2 -1
  138. data/spec/rubocop/cop/style/string_literals_in_interpolation_spec.rb +63 -0
  139. data/spec/rubocop/cop/style/string_literals_spec.rb +2 -2
  140. data/spec/rubocop/cop/style/word_array_spec.rb +15 -1
  141. data/spec/rubocop/formatter/base_formatter_spec.rb +1 -1
  142. data/spec/rubocop/formatter/disabled_lines_formatter_spec.rb +0 -1
  143. data/spec/rubocop/formatter/formatter_set_spec.rb +9 -0
  144. data/spec/rubocop/formatter/html_formatter_spec.rb +25 -122
  145. data/spec/rubocop/formatter/offense_count_formatter_spec.rb +0 -1
  146. data/spec/rubocop/runner_spec.rb +1 -1
  147. data/spec/spec_helper.rb +12 -130
  148. data/spec/support/cop_helper.rb +72 -0
  149. data/spec/support/coverage.rb +15 -0
  150. data/spec/support/{offenses_matcher.rb → custom_matchers.rb} +28 -0
  151. data/spec/support/jruby_workaround.rb +15 -0
  152. data/spec/support/{isolated_environment.rb → shared_contexts.rb} +19 -0
  153. metadata +49 -14
  154. data/lib/rubocop/cop/style/empty_lines_around_body.rb +0 -75
  155. data/spec/support/shared_context.rb +0 -20
@@ -0,0 +1,414 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::MultilineOperationIndentation do
6
+ subject(:cop) { described_class.new(config) }
7
+ let(:config) do
8
+ merged = RuboCop::ConfigLoader
9
+ .default_configuration['Style/MultilineOperationIndentation']
10
+ .merge(cop_config)
11
+ RuboCop::Config
12
+ .new('Style/MultilineOperationIndentation' => merged,
13
+ 'Style/IndentationWidth' => { 'Width' => indentation_width })
14
+ end
15
+ let(:indentation_width) { 2 }
16
+
17
+ shared_examples 'common' do
18
+ it 'accepts indented operands in ordinary statement' do
19
+ inspect_source(cop,
20
+ ['a +',
21
+ ' b'])
22
+ expect(cop.messages).to be_empty
23
+ end
24
+
25
+ it 'registers an offense for no indentation of second line' do
26
+ inspect_source(cop,
27
+ ['a +',
28
+ 'b'])
29
+ expect(cop.messages).to eq(['Use 2 (not 0) spaces for indenting an ' \
30
+ 'expression spanning multiple lines.'])
31
+ expect(cop.highlights).to eq(['b'])
32
+ end
33
+
34
+ it 'registers an offense for one space indentation of second line' do
35
+ inspect_source(cop,
36
+ ['a',
37
+ ' .b'])
38
+ expect(cop.messages).to eq(['Use 2 (not 1) spaces for indenting an ' \
39
+ 'expression spanning multiple lines.'])
40
+ expect(cop.highlights).to eq(['.b'])
41
+ end
42
+
43
+ it 'registers an offense for three spaces indentation of second line' do
44
+ inspect_source(cop,
45
+ ['a ||',
46
+ ' b',
47
+ 'c and',
48
+ ' d'])
49
+ expect(cop.messages).to eq(['Use 2 (not 3) spaces for indenting an ' \
50
+ 'expression spanning multiple lines.'] * 2)
51
+ expect(cop.highlights).to eq(%w(b d))
52
+ end
53
+
54
+ it 'registers an offense for extra indentation of third line' do
55
+ inspect_source(cop,
56
+ [' a ||',
57
+ ' b ||',
58
+ ' c'])
59
+ expect(cop.messages).to eq(['Use 2 (not 4) spaces for indenting an ' \
60
+ 'expression spanning multiple lines.'])
61
+ expect(cop.highlights).to eq(['c'])
62
+ end
63
+
64
+ it 'registers an offense for the emacs ruby-mode 1.1 indentation of an ' \
65
+ 'expression in an array' do
66
+ inspect_source(cop,
67
+ [' [',
68
+ ' a +',
69
+ ' b',
70
+ ' ]'])
71
+ expect(cop.messages).to eq(['Use 2 (not 0) spaces for indenting an ' \
72
+ 'expression spanning multiple lines.'])
73
+ expect(cop.highlights).to eq(['b'])
74
+ end
75
+
76
+ it 'accepts two spaces indentation of second line' do
77
+ inspect_source(cop,
78
+ [' a ||',
79
+ ' b'])
80
+ expect(cop.messages).to be_empty
81
+ end
82
+
83
+ it 'accepts no extra indentation of third line' do
84
+ inspect_source(cop,
85
+ [' a &&',
86
+ ' b &&',
87
+ ' c'])
88
+ expect(cop.messages).to be_empty
89
+ end
90
+
91
+ it 'accepts indented operands in for body' do
92
+ inspect_source(cop,
93
+ ['for x in a',
94
+ ' something &&',
95
+ ' something_else',
96
+ 'end'])
97
+ expect(cop.highlights).to be_empty
98
+ end
99
+
100
+ it 'accepts alignment inside a grouped expression' do
101
+ inspect_source(cop,
102
+ ['(a +',
103
+ ' b)'])
104
+ expect(cop.messages).to be_empty
105
+ end
106
+
107
+ it 'accepts an expression where the first operand spans multiple lines' do
108
+ inspect_source(cop,
109
+ ['subject.each do |item|',
110
+ ' result = resolve(locale) and return result',
111
+ 'end and nil'])
112
+ expect(cop.messages).to be_empty
113
+ end
114
+
115
+ it 'registers an offense for badly indented operands in chained ' \
116
+ 'method call' do
117
+ inspect_source(cop,
118
+ ['Foo',
119
+ '.a',
120
+ ' .b'])
121
+ expect(cop.messages).to eq(['Use 2 (not 0) spaces for indenting an ' \
122
+ 'expression spanning multiple lines.'])
123
+ expect(cop.highlights).to eq(['.a'])
124
+ end
125
+
126
+ it 'registers an offense for badly indented operands in chained ' \
127
+ 'method call' do
128
+ inspect_source(cop,
129
+ ['Foo',
130
+ '.a',
131
+ ' .b(c)'])
132
+ expect(cop.messages).to eq(['Use 2 (not 0) spaces for indenting an ' \
133
+ 'expression spanning multiple lines.'])
134
+ expect(cop.highlights).to eq(['.a'])
135
+ end
136
+
137
+ it 'accepts even indentation of consecutive lines in typical RSpec code' do
138
+ inspect_source(cop,
139
+ ['expect { Foo.new }.',
140
+ ' to change { Bar.count }.',
141
+ ' from(1).to(2)'])
142
+ expect(cop.messages).to be_empty
143
+ end
144
+
145
+ it 'registers an offense for extra indentation of 3rd line in typical ' \
146
+ 'RSpec code' do
147
+ inspect_source(cop,
148
+ ['expect { Foo.new }.',
149
+ ' to change { Bar.count }.',
150
+ ' from(1).to(2)'])
151
+ expect(cop.messages).to eq(['Use 2 (not 6) spaces for indenting an ' \
152
+ 'expression spanning multiple lines.'])
153
+ end
154
+ end
155
+
156
+ context 'when EnforcedStyle is aligned' do
157
+ let(:cop_config) { { 'EnforcedStyle' => 'aligned' } }
158
+
159
+ include_examples 'common'
160
+
161
+ it 'accepts aligned operands in if condition' do
162
+ inspect_source(cop,
163
+ ['if a +',
164
+ ' b',
165
+ ' something',
166
+ 'end'])
167
+ expect(cop.messages).to be_empty
168
+ end
169
+
170
+ it 'registers an offense for misaligned operands in if condition' do
171
+ inspect_source(cop,
172
+ ['if a +',
173
+ ' b',
174
+ ' something',
175
+ 'end'])
176
+ expect(cop.messages).to eq(['Align the operands of a condition in an ' \
177
+ '`if` statement spanning multiple lines.'])
178
+ expect(cop.highlights).to eq(['b'])
179
+ expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'indented')
180
+ end
181
+
182
+ it 'registers an offense for misaligned operands in unless condition' do
183
+ inspect_source(cop,
184
+ ['unless a',
185
+ ' .b',
186
+ ' something',
187
+ 'end'])
188
+ expect(cop.messages).to eq(['Align the operands of a condition in an ' \
189
+ '`unless` statement spanning multiple ' \
190
+ 'lines.'])
191
+ expect(cop.highlights).to eq(['.b'])
192
+ expect(cop.config_to_allow_offenses).to be_nil
193
+ end
194
+
195
+ it 'registers an offense for misaligned operands in while condition' do
196
+ inspect_source(cop,
197
+ ['while a.',
198
+ ' b',
199
+ ' something',
200
+ 'end'])
201
+ expect(cop.messages).to eq(['Align the operands of a condition in a ' \
202
+ '`while` statement spanning multiple lines.'])
203
+ expect(cop.highlights).to eq(['b'])
204
+ end
205
+
206
+ it 'registers an offense for misaligned operands in until condition' do
207
+ inspect_source(cop,
208
+ ['until a.',
209
+ ' b',
210
+ ' something',
211
+ 'end'])
212
+ expect(cop.messages).to eq(['Align the operands of a condition in an ' \
213
+ '`until` statement spanning multiple lines.'])
214
+ expect(cop.highlights).to eq(['b'])
215
+ end
216
+
217
+ it 'accepts aligned operands in assignment' do
218
+ inspect_source(cop,
219
+ ['formatted_int = int_part',
220
+ ' .to_s',
221
+ ' .reverse',
222
+ " .gsub(/...(?=.)/, '\&_')"])
223
+ expect(cop.messages).to be_empty
224
+ end
225
+
226
+ it 'registers an offense for unaligned operands in assignment' do
227
+ inspect_source(cop,
228
+ ['bar = Foo',
229
+ ' .a',
230
+ ' .b(c)'])
231
+ expect(cop.messages).to eq(['Align the operands of an expression in an ' \
232
+ 'assignment spanning multiple lines.'])
233
+ expect(cop.highlights).to eq(['.a'])
234
+ end
235
+
236
+ it 'auto-corrects' do
237
+ new_source = autocorrect_source(cop, ['until a.',
238
+ ' b',
239
+ ' something',
240
+ 'end'])
241
+ expect(new_source).to eq(['until a.',
242
+ ' b',
243
+ ' something',
244
+ 'end'].join("\n"))
245
+ end
246
+ end
247
+
248
+ context 'when EnforcedStyle is indented' do
249
+ let(:cop_config) { { 'EnforcedStyle' => 'indented' } }
250
+
251
+ include_examples 'common'
252
+
253
+ it 'accepts indented operands in if condition' do
254
+ inspect_source(cop,
255
+ ['if a +',
256
+ ' b',
257
+ ' something',
258
+ 'end'])
259
+ expect(cop.messages).to be_empty
260
+ end
261
+
262
+ it 'registers an offense for aligned operands in if condition' do
263
+ inspect_source(cop,
264
+ ['if a +',
265
+ ' b',
266
+ ' something',
267
+ 'end'])
268
+ expect(cop.messages).to eq(['Use 4 (not 3) spaces for indenting a ' \
269
+ 'condition in an `if` statement spanning ' \
270
+ 'multiple lines.'])
271
+ expect(cop.highlights).to eq(['b'])
272
+ expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'aligned')
273
+ end
274
+
275
+ it 'accepts the indentation of a broken string' do
276
+ inspect_source(cop,
277
+ ["MSG = 'Use 2 (not %d) spaces for indenting a ' \\",
278
+ " 'broken line.'"])
279
+ expect(cop.messages).to be_empty
280
+ end
281
+
282
+ it 'accepts normal indentation of method parameters' do
283
+ inspect_source(cop,
284
+ ['Parser::Source::Range.new(expr.source_buffer,',
285
+ ' begin_pos,',
286
+ ' begin_pos + line.length)'])
287
+ expect(cop.messages).to be_empty
288
+ end
289
+
290
+ it 'accepts any indentation of method parameters' do
291
+ inspect_source(cop,
292
+ ['a(b.',
293
+ ' c',
294
+ '.d)'])
295
+ expect(cop.messages).to be_empty
296
+ end
297
+
298
+ it 'accepts normal indentation inside grouped expression' do
299
+ inspect_source(cop,
300
+ ['arg_array.size == a.size && (',
301
+ ' arg_array == a ||',
302
+ ' arg_array.map(&:children) == a.map(&:children)',
303
+ ')'])
304
+ expect(cop.messages).to be_empty
305
+ end
306
+
307
+ [
308
+ %w(an if),
309
+ %w(an unless),
310
+ %w(a while),
311
+ %w(an until)
312
+ ].each do |article, keyword|
313
+ it "accepts double indentation of #{keyword} condition" do
314
+ inspect_source(cop,
315
+ ["#{keyword} receiver.nil? &&",
316
+ ' !args.empty? &&',
317
+ ' BLACKLIST.include?(method_name)',
318
+ 'end',
319
+ "#{keyword} receiver.",
320
+ ' nil?',
321
+ 'end'])
322
+ expect(cop.messages).to be_empty
323
+ end
324
+
325
+ it "registers an offense for a 2 space indentation of #{keyword} " \
326
+ 'condition' do
327
+ inspect_source(cop,
328
+ ["#{keyword} receiver.nil? &&",
329
+ ' !args.empty? &&',
330
+ ' BLACKLIST.include?(method_name)',
331
+ 'end',
332
+ "#{keyword} receiver.",
333
+ ' nil?',
334
+ 'end'])
335
+ expect(cop.highlights).to eq(['!args.empty?',
336
+ 'BLACKLIST.include?(method_name)',
337
+ 'nil?'])
338
+ expect(cop.messages).to eq(['Use 4 (not 2) spaces for indenting a ' \
339
+ "condition in #{article} `#{keyword}` " \
340
+ 'statement spanning multiple lines.'] * 3)
341
+ end
342
+
343
+ it "accepts indented operands in #{keyword} body" do
344
+ inspect_source(cop,
345
+ ["#{keyword} a",
346
+ ' something &&',
347
+ ' something_else',
348
+ 'end'])
349
+ expect(cop.highlights).to be_empty
350
+ end
351
+ end
352
+
353
+ %w(unless if).each do |keyword|
354
+ it "accepts special indentation of return #{keyword} condition" do
355
+ inspect_source(cop,
356
+ ["return #{keyword} receiver.nil? &&",
357
+ ' !args.empty? &&',
358
+ ' BLACKLIST.include?(method_name)'])
359
+ expect(cop.messages).to be_empty
360
+ end
361
+ end
362
+
363
+ it 'registers an offense for wrong indentation of for expression' do
364
+ inspect_source(cop,
365
+ ['for n in a +',
366
+ ' b',
367
+ 'end'])
368
+ expect(cop.messages).to eq(['Use 4 (not 2) spaces for indenting a ' \
369
+ 'collection in a `for` statement spanning ' \
370
+ 'multiple lines.'])
371
+ expect(cop.highlights).to eq(['b'])
372
+ end
373
+
374
+ it 'accepts special indentation of for expression' do
375
+ inspect_source(cop,
376
+ ['for n in a +',
377
+ ' b',
378
+ 'end'])
379
+ expect(cop.messages).to be_empty
380
+ end
381
+
382
+ it 'accepts indentation of assignment' do
383
+ inspect_source(cop,
384
+ ['formatted_int = int_part',
385
+ ' .abs',
386
+ ' .to_s',
387
+ ' .reverse',
388
+ " .gsub(/...(?=.)/, '\&_')",
389
+ ' .reverse'])
390
+ expect(cop.messages).to be_empty
391
+ end
392
+
393
+ it 'registers an offense for aligned operatiors in assignment' do
394
+ inspect_source(cop,
395
+ ['formatted_int = int_part',
396
+ ' .abs',
397
+ ' .reverse'])
398
+ expect(cop.messages).to eq(['Use 2 (not 16) spaces for indenting an ' \
399
+ 'expression in an assignment spanning ' \
400
+ 'multiple lines.'] * 2)
401
+ end
402
+
403
+ it 'auto-corrects' do
404
+ new_source = autocorrect_source(cop, ['until a.',
405
+ ' b',
406
+ ' something',
407
+ 'end'])
408
+ expect(new_source).to eq(['until a.',
409
+ ' b',
410
+ ' something',
411
+ 'end'].join("\n"))
412
+ end
413
+ end
414
+ end
@@ -5,71 +5,80 @@ require 'spec_helper'
5
5
  describe RuboCop::Cop::Style::NonNilCheck, :config do
6
6
  subject(:cop) { described_class.new(config) }
7
7
 
8
- let(:cop_config) do
9
- {
10
- 'IncludeSemanticChanges' => false
11
- }
12
- end
8
+ context 'when not allowing semantic changes' do
9
+ let(:cop_config) do
10
+ {
11
+ 'IncludeSemanticChanges' => false
12
+ }
13
+ end
13
14
 
14
- it 'registers an offense for != nil' do
15
- inspect_source(cop, 'x != nil')
16
- expect(cop.offenses.size).to eq(1)
17
- expect(cop.highlights).to eq(['!='])
18
- end
15
+ it 'registers an offense for != nil' do
16
+ inspect_source(cop, 'x != nil')
17
+ expect(cop.offenses.size).to eq(1)
18
+ expect(cop.highlights).to eq(['!='])
19
+ expect(cop.messages)
20
+ .to eq(['Prefer `!expression.nil?` over `expression != nil`.'])
21
+ end
19
22
 
20
- it 'does not register an offense for !x.nil?' do
21
- inspect_source(cop, '!x.nil?')
22
- expect(cop.offenses).to be_empty
23
- end
23
+ it 'does not register an offense for != 0' do
24
+ inspect_source(cop, 'x != 0')
25
+ expect(cop.offenses).to be_empty
26
+ end
24
27
 
25
- it 'does not register an offense for not x.nil?' do
26
- inspect_source(cop, 'not x.nil?')
27
- expect(cop.offenses).to be_empty
28
- end
28
+ it 'does not register an offense for !x.nil?' do
29
+ inspect_source(cop, '!x.nil?')
30
+ expect(cop.offenses).to be_empty
31
+ end
29
32
 
30
- it 'does not register an offense if only expression in predicate' do
31
- inspect_source(cop, ['def signed_in?',
32
- ' !current_user.nil?',
33
- 'end'])
34
- expect(cop.offenses).to be_empty
35
- end
33
+ it 'does not register an offense for not x.nil?' do
34
+ inspect_source(cop, 'not x.nil?')
35
+ expect(cop.offenses).to be_empty
36
+ end
36
37
 
37
- it 'does not register an offense if only expression in class predicate' do
38
- inspect_source(cop, ['def Test.signed_in?',
39
- ' !current_user.nil?',
40
- 'end'])
41
- expect(cop.offenses).to be_empty
42
- end
38
+ it 'does not register an offense if only expression in predicate' do
39
+ inspect_source(cop, ['def signed_in?',
40
+ ' !current_user.nil?',
41
+ 'end'])
42
+ expect(cop.offenses).to be_empty
43
+ end
43
44
 
44
- it 'does not register an offense if last expression in predicate' do
45
- inspect_source(cop, ['def signed_in?',
46
- ' something',
47
- ' !current_user.nil?',
48
- 'end'])
49
- expect(cop.offenses).to be_empty
50
- end
45
+ it 'does not register an offense if only expression in class predicate' do
46
+ inspect_source(cop, ['def Test.signed_in?',
47
+ ' current_user != nil',
48
+ 'end'])
49
+ expect(cop.offenses).to be_empty
50
+ end
51
51
 
52
- it 'does not register an offense if last expression in class predicate' do
53
- inspect_source(cop, ['def Test.signed_in?',
54
- ' something',
55
- ' !current_user.nil?',
56
- 'end'])
57
- expect(cop.offenses).to be_empty
58
- end
52
+ it 'does not register an offense if last expression in predicate' do
53
+ inspect_source(cop, ['def signed_in?',
54
+ ' something',
55
+ ' current_user != nil',
56
+ 'end'])
57
+ expect(cop.offenses).to be_empty
58
+ end
59
59
 
60
- it 'autocorrects by changing `!= nil` to `!x.nil?`' do
61
- corrected = autocorrect_source(cop, 'x != nil')
62
- expect(corrected).to eq '!x.nil?'
63
- end
60
+ it 'does not register an offense if last expression in class predicate' do
61
+ inspect_source(cop, ['def Test.signed_in?',
62
+ ' something',
63
+ ' current_user != nil',
64
+ 'end'])
65
+ expect(cop.offenses).to be_empty
66
+ end
64
67
 
65
- it 'does not autocorrect by removing non-nil (!x.nil?) check' do
66
- corrected = autocorrect_source(cop, '!x.nil?')
67
- expect(corrected).to eq '!x.nil?'
68
- end
68
+ it 'autocorrects by changing `!= nil` to `!x.nil?`' do
69
+ corrected = autocorrect_source(cop, 'x != nil')
70
+ expect(corrected).to eq '!x.nil?'
71
+ end
69
72
 
70
- it 'does not blow up when autocorrecting implicit receiver' do
71
- corrected = autocorrect_source(cop, '!nil?')
72
- expect(corrected).to eq '!nil?'
73
+ it 'does not autocorrect by removing non-nil (!x.nil?) check' do
74
+ corrected = autocorrect_source(cop, '!x.nil?')
75
+ expect(corrected).to eq '!x.nil?'
76
+ end
77
+
78
+ it 'does not blow up when autocorrecting implicit receiver' do
79
+ corrected = autocorrect_source(cop, '!nil?')
80
+ expect(corrected).to eq '!nil?'
81
+ end
73
82
  end
74
83
 
75
84
  context 'when allowing semantic changes' do
@@ -84,9 +93,21 @@ describe RuboCop::Cop::Style::NonNilCheck, :config do
84
93
  it 'registers an offense for `!x.nil?`' do
85
94
  inspect_source(cop, '!x.nil?')
86
95
  expect(cop.offenses.size).to eq(1)
96
+ expect(cop.messages)
97
+ .to eq(['Explicit non-nil checks are usually redundant.'])
87
98
  expect(cop.highlights).to eq(['!x.nil?'])
88
99
  end
89
100
 
101
+ it 'does not register an offense for `x.nil?`' do
102
+ inspect_source(cop, 'x.nil?')
103
+ expect(cop.offenses).to be_empty
104
+ end
105
+
106
+ it 'does not register an offense for `!x`' do
107
+ inspect_source(cop, '!x')
108
+ expect(cop.offenses).to be_empty
109
+ end
110
+
90
111
  it 'registers an offense for `not x.nil?`' do
91
112
  inspect_source(cop, 'not x.nil?')
92
113
  expect(cop.offenses.size).to eq(1)
@@ -97,5 +118,15 @@ describe RuboCop::Cop::Style::NonNilCheck, :config do
97
118
  corrected = autocorrect_source(cop, 'x != nil')
98
119
  expect(corrected).to eq 'x'
99
120
  end
121
+
122
+ it 'autocorrects by changing `!x.nil?` to `x`' do
123
+ corrected = autocorrect_source(cop, '!x.nil?')
124
+ expect(corrected).to eq 'x'
125
+ end
126
+
127
+ it 'does not blow up when autocorrecting implicit receiver' do
128
+ corrected = autocorrect_source(cop, '!nil?')
129
+ expect(corrected).to eq 'self'
130
+ end
100
131
  end
101
132
  end