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
@@ -101,5 +101,13 @@ describe RuboCop::Cop::Style::Blocks do
101
101
  new_source = autocorrect_source(cop, source)
102
102
  expect(new_source).to eq(expected_source)
103
103
  end
104
+
105
+ it 'does not auto-correct {} if do-end would introduce a syntax error' do
106
+ src = ['my_method :arg1, arg2: proc {',
107
+ ' something',
108
+ '}, arg3: :another_value'].join("\n")
109
+ new_source = autocorrect_source(cop, src)
110
+ expect(new_source).to eq(src)
111
+ end
104
112
  end
105
113
  end
@@ -137,49 +137,49 @@ describe RuboCop::Cop::Style::BracesAroundHashParameters, :config do
137
137
  describe 'auto-corrects' do
138
138
  it 'one non-hash parameter followed by a hash parameter with braces' do
139
139
  corrected = autocorrect_source(cop, ['where(1, { y: 2 })'])
140
- expect(corrected).to eq 'where(1, y: 2)'
140
+ expect(corrected).to eq 'where(1, y: 2 )'
141
141
  end
142
142
 
143
143
  it 'one object method hash parameter with braces' do
144
144
  corrected = autocorrect_source(cop, ['x.func({ y: "z" })'])
145
- expect(corrected).to eq 'x.func(y: "z")'
145
+ expect(corrected).to eq 'x.func( y: "z" )'
146
146
  end
147
147
 
148
148
  it 'one hash parameter with braces' do
149
149
  corrected = autocorrect_source(cop, ['where({ x: 1 })'])
150
- expect(corrected).to eq 'where(x: 1)'
150
+ expect(corrected).to eq 'where( x: 1 )'
151
151
  end
152
152
 
153
153
  it 'one hash parameter with braces and separators' do
154
154
  corrected = autocorrect_source(cop, ['where( ',
155
155
  ' { x: 1 } )'])
156
156
  expect(corrected).to eq(['where( ',
157
- ' x: 1 )'].join("\n"))
157
+ ' x: 1 )'].join("\n"))
158
158
  end
159
159
 
160
160
  it 'one hash parameter with braces and multiple keys' do
161
161
  corrected = autocorrect_source(cop, ['where({ x: 1, foo: "bar" })'])
162
- expect(corrected).to eq 'where(x: 1, foo: "bar")'
162
+ expect(corrected).to eq 'where( x: 1, foo: "bar" )'
163
163
  end
164
164
 
165
165
  it 'one hash parameter with braces and extra leading whitespace' do
166
166
  corrected = autocorrect_source(cop, ['where({ x: 1, y: 2 })'])
167
- expect(corrected).to eq 'where(x: 1, y: 2)'
167
+ expect(corrected).to eq 'where( x: 1, y: 2 )'
168
168
  end
169
169
 
170
170
  it 'one hash parameter with braces and extra trailing whitespace' do
171
171
  corrected = autocorrect_source(cop, ['where({ x: 1, y: 2 })'])
172
- expect(corrected).to eq 'where(x: 1, y: 2)'
172
+ expect(corrected).to eq 'where( x: 1, y: 2 )'
173
173
  end
174
174
 
175
175
  it 'one hash parameter with braces and a trailing comma' do
176
176
  corrected = autocorrect_source(cop, ['where({ x: 1, y: 2, })'])
177
- expect(corrected).to eq 'where(x: 1, y: 2)'
177
+ expect(corrected).to eq 'where( x: 1, y: 2, )'
178
178
  end
179
179
 
180
180
  it 'one hash parameter with braces and trailing comma and whitespace' do
181
181
  corrected = autocorrect_source(cop, ['where({ x: 1, y: 2, })'])
182
- expect(corrected).to eq 'where(x: 1, y: 2)'
182
+ expect(corrected).to eq 'where( x: 1, y: 2, )'
183
183
  end
184
184
  end
185
185
  end
@@ -6,8 +6,9 @@ describe RuboCop::Cop::Style::CaseIndentation do
6
6
  subject(:cop) { described_class.new(config) }
7
7
  let(:config) do
8
8
  merged = RuboCop::ConfigLoader
9
- .default_configuration['Style/CaseIndentation'].merge(cop_config)
10
- RuboCop::Config.new('Style/CaseIndentation' => merged)
9
+ .default_configuration['Style/CaseIndentation'].merge(cop_config)
10
+ RuboCop::Config.new('Style/CaseIndentation' => merged,
11
+ 'Style/IndentationWidth' => { 'Width' => 2 })
11
12
  end
12
13
 
13
14
  context 'with IndentWhenRelativeTo: case' do
@@ -53,6 +53,11 @@ describe RuboCop::Cop::Style::ColonMethodCall do
53
53
  expect(cop.offenses).to be_empty
54
54
  end
55
55
 
56
+ it 'does not register an offense for Java static types' do
57
+ inspect_source(cop, 'Java::int')
58
+ expect(cop.offenses).to be_empty
59
+ end
60
+
56
61
  it 'auto-corrects "::" with "."' do
57
62
  new_source = autocorrect_source(cop, 'test::method')
58
63
  expect(new_source).to eq('test.method')
@@ -3,7 +3,12 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe RuboCop::Cop::Style::CommentIndentation do
6
- subject(:cop) { described_class.new }
6
+ subject(:cop) { described_class.new(config) }
7
+ let(:config) do
8
+ RuboCop::Config
9
+ .new('Style/IndentationWidth' => { 'Width' => indentation_width })
10
+ end
11
+ let(:indentation_width) { 2 }
7
12
 
8
13
  context 'on outer level' do
9
14
  it 'accepts a correctly indented comment' do
@@ -0,0 +1,437 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe RuboCop::Cop::Style::ElseAlignment do
6
+ subject(:cop) { described_class.new(config) }
7
+ let(:config) do
8
+ RuboCop::Config.new('Lint/EndAlignment' => end_alignment_config)
9
+ end
10
+ let(:end_alignment_config) do
11
+ { 'Enabled' => true, 'AlignWith' => 'variable' }
12
+ end
13
+
14
+ it 'accepts a ternary if' do
15
+ inspect_source(cop,
16
+ ['cond ? func1 : func2'])
17
+ expect(cop.offenses).to be_empty
18
+ end
19
+
20
+ context 'with if statement' do
21
+ it 'registers an offense for misaligned else' do
22
+ inspect_source(cop,
23
+ ['if cond',
24
+ ' func1',
25
+ ' else',
26
+ ' func2',
27
+ 'end'])
28
+ expect(cop.messages).to eq(['Align `else` with `if`.'])
29
+ expect(cop.highlights).to eq(['else'])
30
+ end
31
+
32
+ it 'registers an offense for misaligned elsif' do
33
+ inspect_source(cop,
34
+ [' if a1',
35
+ ' b1',
36
+ 'elsif a2',
37
+ ' b2',
38
+ ' end'])
39
+ expect(cop.messages).to eq(['Align `elsif` with `if`.'])
40
+ expect(cop.highlights).to eq(['elsif'])
41
+ end
42
+
43
+ describe '#autocorrect' do
44
+ it 'corrects bad alignment' do
45
+ corrected = autocorrect_source(cop,
46
+ [' if a1',
47
+ ' b1',
48
+ ' elsif a2',
49
+ ' b2',
50
+ 'else',
51
+ ' c',
52
+ ' end'])
53
+ expect(cop.messages).to eq(['Align `elsif` with `if`.',
54
+ 'Align `else` with `if`.'])
55
+ expect(corrected)
56
+ .to eq [' if a1',
57
+ ' b1',
58
+ ' elsif a2',
59
+ ' b2',
60
+ ' else',
61
+ ' c',
62
+ ' end'].join("\n")
63
+ end
64
+ end
65
+
66
+ it 'accepts a one line if statement' do
67
+ inspect_source(cop,
68
+ ['if cond then func1 else func2 end'])
69
+ expect(cop.offenses).to be_empty
70
+ end
71
+
72
+ it 'accepts a correctly aligned if/elsif/else/end' do
73
+ inspect_source(cop,
74
+ ['if a1',
75
+ ' b1',
76
+ 'elsif a2',
77
+ ' b2',
78
+ 'else',
79
+ ' c',
80
+ 'end'])
81
+ expect(cop.offenses).to be_empty
82
+ end
83
+
84
+ context 'with assignment' do
85
+ context 'when alignment style is variable' do
86
+ context 'and end is aligned with variable' do
87
+ it 'accepts an if with end aligned with setter' do
88
+ inspect_source(cop,
89
+ ['foo.bar = if baz',
90
+ ' derp1',
91
+ 'else',
92
+ ' derp2',
93
+ 'end'])
94
+ expect(cop.offenses).to be_empty
95
+ end
96
+
97
+ it 'accepts an if with end aligned with element assignment' do
98
+ inspect_source(cop,
99
+ ['foo[bar] = if baz',
100
+ ' derp',
101
+ 'end'])
102
+ expect(cop.offenses).to be_empty
103
+ end
104
+
105
+ it 'accepts an if/else' do
106
+ inspect_source(cop,
107
+ ['var = if a',
108
+ ' 0',
109
+ 'else',
110
+ ' 1',
111
+ 'end'])
112
+ expect(cop.offenses).to be_empty
113
+ end
114
+
115
+ it 'accepts an if/else with chaining after the end' do
116
+ inspect_source(cop,
117
+ ['var = if a',
118
+ ' 0',
119
+ 'else',
120
+ ' 1',
121
+ 'end.abc.join("")'])
122
+ expect(cop.offenses).to be_empty
123
+ end
124
+
125
+ it 'accepts an if/else with chaining with a block after the end' do
126
+ inspect_source(cop,
127
+ ['var = if a',
128
+ ' 0',
129
+ 'else',
130
+ ' 1',
131
+ 'end.abc.tap {}'])
132
+ expect(cop.offenses).to be_empty
133
+ end
134
+ end
135
+
136
+ context 'and end is aligned with keyword' do
137
+ it 'registers an offense for an if with setter' do
138
+ inspect_source(cop,
139
+ ['foo.bar = if baz',
140
+ ' derp1',
141
+ ' else',
142
+ ' derp2',
143
+ ' end'])
144
+ expect(cop.messages).to eq(['Align `else` with `foo.bar`.'])
145
+ end
146
+
147
+ it 'registers an offense for an if with element assignment' do
148
+ inspect_source(cop,
149
+ ['foo[bar] = if baz',
150
+ ' derp1',
151
+ ' else',
152
+ ' derp2',
153
+ ' end'])
154
+ expect(cop.messages).to eq(['Align `else` with `foo[bar]`.'])
155
+ end
156
+
157
+ it 'registers an offense for an if' do
158
+ inspect_source(cop,
159
+ ['var = if a',
160
+ ' 0',
161
+ ' else',
162
+ ' 1',
163
+ ' end'])
164
+ expect(cop.messages).to eq(['Align `else` with `var`.'])
165
+ end
166
+ end
167
+ end
168
+
169
+ shared_examples 'assignment and if with keyword alignment' do
170
+ context 'and end is aligned with variable' do
171
+ it 'registers an offense for an if' do
172
+ inspect_source(cop,
173
+ ['var = if a',
174
+ ' 0',
175
+ 'elsif b',
176
+ ' 1',
177
+ 'end'])
178
+ expect(cop.messages).to eq(['Align `elsif` with `if`.'])
179
+ end
180
+
181
+ it 'autocorrects bad alignment' do
182
+ corrected = autocorrect_source(cop,
183
+ ['var = if a',
184
+ ' b1',
185
+ 'else',
186
+ ' b2',
187
+ 'end'])
188
+ expect(corrected).to eq ['var = if a',
189
+ ' b1',
190
+ ' else',
191
+ ' b2',
192
+ 'end'].join("\n")
193
+ end
194
+ end
195
+
196
+ context 'and end is aligned with keyword' do
197
+ it 'accepts an if in assignment' do
198
+ inspect_source(cop,
199
+ ['var = if a',
200
+ ' 0',
201
+ ' end'])
202
+ expect(cop.offenses).to be_empty
203
+ end
204
+
205
+ it 'accepts an if/else in assignment' do
206
+ inspect_source(cop,
207
+ ['var = if a',
208
+ ' 0',
209
+ ' else',
210
+ ' 1',
211
+ ' end'])
212
+ expect(cop.offenses).to be_empty
213
+ end
214
+
215
+ it 'accepts an if/else in assignment on next line' do
216
+ inspect_source(cop,
217
+ ['var =',
218
+ ' if a',
219
+ ' 0',
220
+ ' else',
221
+ ' 1',
222
+ ' end'])
223
+ expect(cop.offenses).to be_empty
224
+ end
225
+
226
+ it 'accepts a while in assignment' do
227
+ inspect_source(cop,
228
+ ['var = while a',
229
+ ' b',
230
+ ' end'])
231
+ expect(cop.offenses).to be_empty
232
+ end
233
+
234
+ it 'accepts an until in assignment' do
235
+ inspect_source(cop,
236
+ ['var = until a',
237
+ ' b',
238
+ ' end'])
239
+ expect(cop.offenses).to be_empty
240
+ end
241
+ end
242
+ end
243
+
244
+ context 'when alignment style is keyword by choice' do
245
+ let(:end_alignment_config) do
246
+ { 'Enabled' => true, 'AlignWith' => 'keyword' }
247
+ end
248
+
249
+ include_examples 'assignment and if with keyword alignment'
250
+ end
251
+
252
+ context 'when alignment style is keyword by default' do
253
+ let(:end_alignment_config) do
254
+ { 'Enabled' => false, 'AlignWith' => 'variable' }
255
+ end
256
+
257
+ include_examples 'assignment and if with keyword alignment'
258
+ end
259
+ end
260
+
261
+ it 'accepts an if/else branches with rescue clauses' do
262
+ # Because of how the rescue clauses come out of Parser, these are
263
+ # special and need to be tested.
264
+ inspect_source(cop,
265
+ ['if a',
266
+ ' a rescue nil',
267
+ 'else',
268
+ ' a rescue nil',
269
+ 'end'])
270
+ expect(cop.offenses).to be_empty
271
+ end
272
+ end
273
+
274
+ context 'with unless' do
275
+ it 'registers an offense for misaligned else' do
276
+ inspect_source(cop,
277
+ ['unless cond',
278
+ ' func1',
279
+ ' else',
280
+ ' func2',
281
+ 'end'])
282
+ expect(cop.messages).to eq(['Align `else` with `unless`.'])
283
+ end
284
+
285
+ it 'accepts a correctly aligned else in an otherwise empty unless' do
286
+ inspect_source(cop,
287
+ ['unless a',
288
+ 'else',
289
+ 'end'])
290
+ expect(cop.offenses).to be_empty
291
+ end
292
+
293
+ it 'accepts an empty unless' do
294
+ inspect_source(cop,
295
+ ['unless a',
296
+ 'end'])
297
+ expect(cop.offenses).to be_empty
298
+ end
299
+ end
300
+
301
+ context 'with case' do
302
+ it 'registers an offense for misaligned else' do
303
+ inspect_source(cop,
304
+ ['case a',
305
+ 'when b',
306
+ ' c',
307
+ 'when d',
308
+ ' e',
309
+ ' else',
310
+ ' f',
311
+ 'end'])
312
+ expect(cop.messages).to eq(['Align `else` with `when`.'])
313
+ end
314
+
315
+ it 'accepts correctly aligned case/when/else' do
316
+ inspect_source(cop,
317
+ ['case a',
318
+ 'when b',
319
+ ' c',
320
+ ' c',
321
+ 'when d',
322
+ 'else',
323
+ ' f',
324
+ 'end'])
325
+ expect(cop.offenses).to be_empty
326
+ end
327
+
328
+ it 'accepts case without else' do
329
+ inspect_source(cop,
330
+ ['case superclass',
331
+ 'when /\A(#{NAMESPACEMATCH})(?:\s|\Z)/',
332
+ ' $1',
333
+ 'when "self"',
334
+ ' namespace.path',
335
+ 'end'])
336
+ expect(cop.offenses).to be_empty
337
+ end
338
+
339
+ it 'accepts else aligned with when but not with case' do
340
+ # "Indent when as deep as case" is the job of another cop, and this is
341
+ # one of the possible styles supported by configuration.
342
+ inspect_source(cop,
343
+ ['case code_type',
344
+ " when 'ruby', 'sql', 'plain'",
345
+ ' code_type',
346
+ " when 'erb'",
347
+ " 'ruby; html-script: true'",
348
+ ' when "html"',
349
+ " 'xml'",
350
+ ' else',
351
+ " 'plain'",
352
+ 'end'])
353
+ expect(cop.offenses).to be_empty
354
+ end
355
+ end
356
+
357
+ context 'with def/defs' do
358
+ it 'accepts an empty def body' do
359
+ inspect_source(cop,
360
+ ['def test',
361
+ 'end'])
362
+ expect(cop.offenses).to be_empty
363
+ end
364
+
365
+ it 'accepts an empty defs body' do
366
+ inspect_source(cop,
367
+ ['def self.test',
368
+ 'end'])
369
+ expect(cop.offenses).to be_empty
370
+ end
371
+
372
+ if RUBY_VERSION >= '2.1'
373
+ context 'when modifier and def are on the same line' do
374
+ it 'accepts a correctly aligned body' do
375
+ inspect_source(cop,
376
+ ['private def test',
377
+ ' something',
378
+ 'rescue',
379
+ ' handling',
380
+ 'else',
381
+ ' something_else',
382
+ 'end'])
383
+ expect(cop.offenses).to be_empty
384
+ end
385
+
386
+ it 'registers an offense for else not aligned with private' do
387
+ inspect_source(cop,
388
+ ['private def test',
389
+ ' something',
390
+ ' rescue',
391
+ ' handling',
392
+ ' else',
393
+ ' something_else',
394
+ ' end'])
395
+ expect(cop.messages).to eq(['Align `else` with `private`.'])
396
+ end
397
+ end
398
+ end
399
+ end
400
+
401
+ context 'with begin/rescue/else/ensure/end' do
402
+ it 'registers an offense for misaligned else' do
403
+ inspect_source(cop,
404
+ ['def my_func',
405
+ " puts 'do something outside block'",
406
+ ' begin',
407
+ " puts 'do something error prone'",
408
+ ' rescue SomeException, SomeOther => e',
409
+ " puts 'wrongly intended error handling'",
410
+ ' rescue',
411
+ " puts 'wrongly intended error handling'",
412
+ 'else',
413
+ " puts 'wrongly intended normal case handling'",
414
+ ' ensure',
415
+ " puts 'wrongly intended common handling'",
416
+ ' end',
417
+ 'end'])
418
+ expect(cop.messages).to eq(['Align `else` with `begin`.'])
419
+ end
420
+ end
421
+
422
+ context 'with def/rescue/else/end' do
423
+ it 'registers an offense for misaligned else' do
424
+ inspect_source(cop,
425
+ ['def my_func',
426
+ " puts 'do something error prone'",
427
+ 'rescue SomeException',
428
+ " puts 'error handling'",
429
+ 'rescue',
430
+ " puts 'error handling'",
431
+ ' else',
432
+ " puts 'normal handling'",
433
+ 'end'])
434
+ expect(cop.messages).to eq(['Align `else` with `def`.'])
435
+ end
436
+ end
437
+ end