rubocop 0.16.0 → 0.17.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -1
  4. data/CHANGELOG.md +44 -0
  5. data/CONTRIBUTING.md +40 -8
  6. data/Gemfile +6 -0
  7. data/README.md +65 -20
  8. data/Rakefile +0 -1
  9. data/config/default.yml +15 -3
  10. data/config/enabled.yml +143 -109
  11. data/lib/rubocop.rb +45 -26
  12. data/lib/rubocop/cli.rb +26 -27
  13. data/lib/rubocop/config.rb +0 -1
  14. data/lib/rubocop/config_loader.rb +16 -23
  15. data/lib/rubocop/cop/commissioner.rb +2 -7
  16. data/lib/rubocop/cop/cop.rb +24 -51
  17. data/lib/rubocop/cop/ignored_node.rb +31 -0
  18. data/lib/rubocop/cop/lint/ambiguous_operator.rb +50 -0
  19. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +36 -0
  20. data/lib/rubocop/cop/lint/assignment_in_condition.rb +3 -11
  21. data/lib/rubocop/cop/lint/block_alignment.rb +6 -20
  22. data/lib/rubocop/cop/lint/condition_position.rb +52 -0
  23. data/lib/rubocop/cop/lint/else_layout.rb +57 -0
  24. data/lib/rubocop/cop/lint/end_alignment.rb +33 -8
  25. data/lib/rubocop/cop/lint/invalid_character_literal.rb +37 -0
  26. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +2 -4
  27. data/lib/rubocop/cop/lint/syntax.rb +6 -12
  28. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +25 -0
  29. data/lib/rubocop/cop/mixin/array_syntax.rb +20 -0
  30. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +76 -0
  31. data/lib/rubocop/cop/mixin/check_assignment.rb +26 -0
  32. data/lib/rubocop/cop/{check_methods.rb → mixin/check_methods.rb} +0 -0
  33. data/lib/rubocop/cop/mixin/code_length.rb +33 -0
  34. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +53 -0
  35. data/lib/rubocop/cop/mixin/configurable_max.rb +19 -0
  36. data/lib/rubocop/cop/mixin/configurable_naming.rb +45 -0
  37. data/lib/rubocop/cop/{style → mixin}/if_node.rb +0 -0
  38. data/lib/rubocop/cop/mixin/if_then_else.rb +23 -0
  39. data/lib/rubocop/cop/mixin/negative_conditional.rb +24 -0
  40. data/lib/rubocop/cop/mixin/parser_diagnostic.rb +34 -0
  41. data/lib/rubocop/cop/mixin/safe_assignment.rb +19 -0
  42. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +32 -0
  43. data/lib/rubocop/cop/mixin/space_inside.rb +31 -0
  44. data/lib/rubocop/cop/mixin/statement_modifier.rb +59 -0
  45. data/lib/rubocop/cop/mixin/string_help.rb +32 -0
  46. data/lib/rubocop/cop/mixin/surrounding_space.rb +42 -0
  47. data/lib/rubocop/cop/rails/default_scope.rb +3 -1
  48. data/lib/rubocop/cop/style/accessor_method_name.rb +4 -12
  49. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +16 -1
  50. data/lib/rubocop/cop/style/case_indentation.rb +33 -16
  51. data/lib/rubocop/cop/style/character_literal.rb +10 -0
  52. data/lib/rubocop/cop/style/dot_position.rb +23 -6
  53. data/lib/rubocop/cop/style/empty_lines_around_body.rb +5 -5
  54. data/lib/rubocop/cop/style/favor_unless_over_negated_if.rb +1 -32
  55. data/lib/rubocop/cop/style/favor_until_over_negated_while.rb +20 -0
  56. data/lib/rubocop/cop/style/hash_syntax.rb +5 -1
  57. data/lib/rubocop/cop/style/if_unless_modifier.rb +34 -0
  58. data/lib/rubocop/cop/style/if_with_semicolon.rb +1 -1
  59. data/lib/rubocop/cop/style/indentation_consistency.rb +51 -0
  60. data/lib/rubocop/cop/style/indentation_width.rb +0 -26
  61. data/lib/rubocop/cop/style/lambda_call.rb +12 -5
  62. data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -11
  63. data/lib/rubocop/cop/style/multiline_if_then.rb +4 -9
  64. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +22 -0
  65. data/lib/rubocop/cop/style/{ternary_operator.rb → nested_ternary_operator.rb} +0 -15
  66. data/lib/rubocop/cop/style/numeric_literals.rb +30 -2
  67. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -1
  68. data/lib/rubocop/cop/style/parameter_lists.rb +7 -3
  69. data/lib/rubocop/cop/style/parentheses_around_condition.rb +9 -11
  70. data/lib/rubocop/cop/style/predicate_name.rb +4 -12
  71. data/lib/rubocop/cop/style/raise_args.rb +19 -11
  72. data/lib/rubocop/cop/style/regexp_literal.rb +19 -6
  73. data/lib/rubocop/cop/style/space_after_colon.rb +36 -0
  74. data/lib/rubocop/cop/style/space_after_comma.rb +16 -0
  75. data/lib/rubocop/cop/style/space_after_semicolon.rb +16 -0
  76. data/lib/rubocop/cop/style/space_around_block_braces.rb +38 -38
  77. data/lib/rubocop/cop/style/space_around_operators.rb +1 -2
  78. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +6 -2
  79. data/lib/rubocop/cop/style/string_literals.rb +5 -5
  80. data/lib/rubocop/cop/style/trailing_comma.rb +94 -0
  81. data/lib/rubocop/cop/style/unless_else.rb +2 -2
  82. data/lib/rubocop/cop/style/while_until_modifier.rb +32 -0
  83. data/lib/rubocop/cop/style/word_array.rb +9 -1
  84. data/lib/rubocop/cop/util.rb +14 -0
  85. data/lib/rubocop/cop/variable_inspector.rb +11 -6
  86. data/lib/rubocop/cop/variable_inspector/scope.rb +4 -3
  87. data/lib/rubocop/file_inspector.rb +22 -6
  88. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  89. data/lib/rubocop/formatter/colorizable.rb +37 -0
  90. data/lib/rubocop/formatter/disabled_config_formatter.rb +27 -6
  91. data/lib/rubocop/formatter/progress_formatter.rb +1 -1
  92. data/lib/rubocop/formatter/simple_text_formatter.rb +9 -5
  93. data/lib/rubocop/options.rb +19 -4
  94. data/lib/rubocop/target_finder.rb +4 -0
  95. data/lib/rubocop/version.rb +1 -1
  96. data/rubocop-todo.yml +10 -2
  97. data/rubocop.gemspec +3 -2
  98. data/spec/project_spec.rb +12 -7
  99. data/spec/rubocop/cli_spec.rb +262 -99
  100. data/spec/rubocop/config_loader_spec.rb +5 -5
  101. data/spec/rubocop/config_spec.rb +3 -3
  102. data/spec/rubocop/config_store_spec.rb +12 -11
  103. data/spec/rubocop/cop/commissioner_spec.rb +21 -5
  104. data/spec/rubocop/cop/cop_spec.rb +1 -1
  105. data/spec/rubocop/cop/lint/ambiguous_operator_spec.rb +113 -0
  106. data/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb +35 -0
  107. data/spec/rubocop/cop/lint/block_alignment_spec.rb +2 -2
  108. data/spec/rubocop/cop/lint/condition_position_spec.rb +49 -0
  109. data/spec/rubocop/cop/lint/else_layout_spec.rb +65 -0
  110. data/spec/rubocop/cop/lint/end_alignment_spec.rb +41 -1
  111. data/spec/rubocop/cop/lint/invalid_character_literal_spec.rb +33 -0
  112. data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +3 -3
  113. data/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb +12 -12
  114. data/spec/rubocop/cop/lint/syntax_spec.rb +2 -2
  115. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +72 -54
  116. data/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb +48 -0
  117. data/spec/rubocop/cop/offence_spec.rb +1 -1
  118. data/spec/rubocop/cop/rails/default_scope_spec.rb +6 -0
  119. data/spec/rubocop/cop/rails/output_spec.rb +2 -1
  120. data/spec/rubocop/cop/style/align_hash_spec.rb +9 -9
  121. data/spec/rubocop/cop/style/align_parameters_spec.rb +1 -1
  122. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +5 -0
  123. data/spec/rubocop/cop/style/case_indentation_spec.rb +53 -2
  124. data/spec/rubocop/cop/style/class_and_module_camel_case_spec.rb +3 -3
  125. data/spec/rubocop/cop/style/documentation_spec.rb +0 -1
  126. data/spec/rubocop/cop/style/dot_position_spec.rb +18 -3
  127. data/spec/rubocop/cop/style/empty_line_between_defs_spec.rb +4 -4
  128. data/spec/rubocop/cop/style/empty_lines_around_body_spec.rb +13 -0
  129. data/spec/rubocop/cop/style/favor_unless_over_negated_if_spec.rb +1 -1
  130. data/spec/rubocop/cop/style/favor_until_over_negated_while_spec.rb +1 -1
  131. data/spec/rubocop/cop/style/hash_syntax_spec.rb +5 -0
  132. data/spec/rubocop/cop/style/{favor_modifier_spec.rb → if_unless_modifier_spec.rb} +4 -111
  133. data/spec/rubocop/cop/style/indentation_consistency_spec.rb +490 -0
  134. data/spec/rubocop/cop/style/indentation_width_spec.rb +19 -91
  135. data/spec/rubocop/cop/style/lambda_call_spec.rb +18 -0
  136. data/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb +2 -2
  137. data/spec/rubocop/cop/style/method_def_parentheses_spec.rb +35 -1
  138. data/spec/rubocop/cop/style/method_length_spec.rb +1 -0
  139. data/spec/rubocop/cop/style/method_name_spec.rb +27 -5
  140. data/spec/rubocop/cop/style/multiline_block_chain_spec.rb +4 -4
  141. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +2 -2
  142. data/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb +18 -0
  143. data/spec/rubocop/cop/style/{ternary_operator_spec.rb → nested_ternary_operator_spec.rb} +0 -15
  144. data/spec/rubocop/cop/style/numeric_literals_spec.rb +18 -1
  145. data/spec/rubocop/cop/style/one_line_conditional_spec.rb +2 -1
  146. data/spec/rubocop/cop/style/parameter_lists_spec.rb +1 -0
  147. data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +13 -4
  148. data/spec/rubocop/cop/style/raise_args_spec.rb +22 -0
  149. data/spec/rubocop/cop/style/redundant_self_spec.rb +4 -4
  150. data/spec/rubocop/cop/style/regexp_literal_spec.rb +4 -0
  151. data/spec/rubocop/cop/style/space_after_colon_spec.rb +12 -4
  152. data/spec/rubocop/cop/style/space_after_method_name_spec.rb +2 -2
  153. data/spec/rubocop/cop/style/space_around_block_braces_spec.rb +30 -1
  154. data/spec/rubocop/cop/style/{space_around_equals_in_default_parameter_spec.rb → space_around_equals_in_parameter_default_spec.rb} +0 -0
  155. data/spec/rubocop/cop/style/space_around_operators_spec.rb +2 -1
  156. data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +20 -3
  157. data/spec/rubocop/cop/style/string_literals_spec.rb +33 -0
  158. data/spec/rubocop/cop/style/trailing_comma_spec.rb +200 -0
  159. data/spec/rubocop/cop/style/variable_name_spec.rb +27 -3
  160. data/spec/rubocop/cop/style/while_until_modifier_spec.rb +75 -0
  161. data/spec/rubocop/cop/style/word_array_spec.rb +1 -0
  162. data/spec/rubocop/cop/team_spec.rb +1 -1
  163. data/spec/rubocop/cop/variable_inspector/scope_spec.rb +3 -4
  164. data/spec/rubocop/file_inspector_spec.rb +1 -1
  165. data/spec/rubocop/formatter/base_formatter_spec.rb +12 -11
  166. data/spec/rubocop/formatter/colorizable_spec.rb +107 -0
  167. data/spec/rubocop/formatter/disabled_config_formatter_spec.rb +2 -0
  168. data/spec/rubocop/formatter/formatter_set_spec.rb +1 -1
  169. data/spec/rubocop/formatter/json_formatter_spec.rb +4 -3
  170. data/spec/rubocop/formatter/progress_formatter_spec.rb +2 -2
  171. data/spec/rubocop/options_spec.rb +3 -1
  172. data/spec/rubocop/target_finder_spec.rb +13 -11
  173. data/spec/spec_helper.rb +5 -1
  174. data/spec/support/shared_examples.rb +2 -2
  175. data/spec/support/statement_modifier_helper.rb +41 -0
  176. metadata +88 -30
  177. data/lib/rubocop/cop/check_assignment.rb +0 -43
  178. data/lib/rubocop/cop/style/array_syntax.rb +0 -22
  179. data/lib/rubocop/cop/style/autocorrect_alignment.rb +0 -78
  180. data/lib/rubocop/cop/style/code_length.rb +0 -35
  181. data/lib/rubocop/cop/style/configurable_enforced_style.rb +0 -51
  182. data/lib/rubocop/cop/style/configurable_max.rb +0 -17
  183. data/lib/rubocop/cop/style/configurable_naming.rb +0 -41
  184. data/lib/rubocop/cop/style/favor_modifier.rb +0 -118
  185. data/lib/rubocop/cop/style/if_then_else.rb +0 -27
  186. data/lib/rubocop/cop/style/space_after_comma_etc.rb +0 -73
  187. data/lib/rubocop/cop/style/space_inside.rb +0 -33
  188. data/lib/rubocop/cop/style/string_help.rb +0 -30
  189. data/lib/rubocop/cop/style/surrounding_space.rb +0 -44
@@ -3,6 +3,8 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Rubocop::Cop::Style::IfUnlessModifier do
6
+ include StatementModifierHelper
7
+
6
8
  subject(:cop) { described_class.new(config) }
7
9
  let(:config) do
8
10
  hash = { 'LineLength' => { 'Max' => 79 } }
@@ -21,7 +23,7 @@ describe Rubocop::Cop::Style::IfUnlessModifier do
21
23
  " #{body}",
22
24
  ' end'])
23
25
  expect(cop.messages).to eq(
24
- ['Favor modifier if/unless usage when you have a single-line' +
26
+ ['Favor modifier if usage when you have a single-line' +
25
27
  ' body. Another good alternative is the usage of control flow' +
26
28
  ' &&/||.'])
27
29
  end
@@ -57,7 +59,7 @@ describe Rubocop::Cop::Style::IfUnlessModifier do
57
59
  ' b',
58
60
  'end'])
59
61
  expect(cop.messages).to eq(
60
- ['Favor modifier if/unless usage when you have a single-line' +
62
+ ['Favor modifier unless usage when you have a single-line' +
61
63
  ' body. Another good alternative is the usage of control flow' +
62
64
  ' &&/||.'])
63
65
  end
@@ -124,112 +126,3 @@ describe Rubocop::Cop::Style::IfUnlessModifier do
124
126
  end
125
127
  end
126
128
  end
127
-
128
- describe Rubocop::Cop::Style::WhileUntilModifier do
129
- subject(:cop) { described_class.new(config) }
130
- let(:config) do
131
- hash = { 'LineLength' => { 'Max' => 79 } }
132
- Rubocop::Config.new(hash)
133
- end
134
-
135
- it "accepts multiline unless that doesn't fit on one line" do
136
- check_too_long(cop, 'unless')
137
- end
138
-
139
- it 'accepts multiline unless whose body is more than one line' do
140
- check_short_multiline(cop, 'unless')
141
- end
142
-
143
- it 'registers an offence for multiline while that fits on one line' do
144
- check_really_short(cop, 'while')
145
- end
146
-
147
- it "accepts multiline while that doesn't fit on one line" do
148
- check_too_long(cop, 'while')
149
- end
150
-
151
- it 'accepts multiline while whose body is more than one line' do
152
- check_short_multiline(cop, 'while')
153
- end
154
-
155
- it 'accepts oneline while when condition has local variable assignment' do
156
- inspect_source(cop, ['lines = %w{first second third}',
157
- 'while (line = lines.shift)',
158
- ' puts line',
159
- 'end'])
160
- expect(cop.offences).to be_empty
161
- end
162
-
163
- it 'registers an offence for oneline while when assignment is in body' do
164
- inspect_source(cop, ['while true',
165
- ' x = 0',
166
- 'end'])
167
- expect(cop.offences.size).to eq(1)
168
- end
169
-
170
- it 'registers an offence for multiline until that fits on one line' do
171
- check_really_short(cop, 'until')
172
- end
173
-
174
- it "accepts multiline until that doesn't fit on one line" do
175
- check_too_long(cop, 'until')
176
- end
177
-
178
- it 'accepts multiline until whose body is more than one line' do
179
- check_short_multiline(cop, 'until')
180
- end
181
-
182
- it 'accepts an empty condition' do
183
- check_empty(cop, 'while')
184
- check_empty(cop, 'until')
185
- end
186
-
187
- it 'accepts modifier while' do
188
- inspect_source(cop, ['ala while bala'])
189
- expect(cop.offences).to be_empty
190
- end
191
-
192
- it 'accepts modifier until' do
193
- inspect_source(cop, ['ala until bala'])
194
- expect(cop.offences).to be_empty
195
- end
196
- end
197
-
198
- def check_empty(cop, keyword)
199
- inspect_source(cop, ["#{keyword} cond",
200
- 'end'])
201
- expect(cop.offences).to be_empty
202
- end
203
-
204
- def check_really_short(cop, keyword)
205
- inspect_source(cop, ["#{keyword} a",
206
- ' b',
207
- 'end'])
208
- expect(cop.messages).to eq(
209
- ['Favor modifier while/until usage when you have a single-line ' +
210
- 'body.'])
211
- expect(cop.offences.map { |o| o.location.source }).to eq([keyword])
212
- end
213
-
214
- def check_too_long(cop, keyword)
215
- # This statement is one character too long to fit.
216
- condition = 'a' * (40 - keyword.length)
217
- body = 'b' * 36
218
- expect(" #{body} #{keyword} #{condition}".length).to eq(80)
219
-
220
- inspect_source(cop,
221
- [" #{keyword} #{condition}",
222
- " #{body}",
223
- ' end'])
224
-
225
- expect(cop.offences).to be_empty
226
- end
227
-
228
- def check_short_multiline(cop, keyword)
229
- inspect_source(cop,
230
- ["#{keyword} ENV['COVERAGE']",
231
- " require 'simplecov'",
232
- ' SimpleCov.start',
233
- 'end'])
234
- expect(cop.messages).to be_empty
235
- end
@@ -0,0 +1,490 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Rubocop::Cop::Style::IndentationConsistency do
6
+ subject(:cop) { described_class.new }
7
+
8
+ context 'with if statement' do
9
+ it 'registers an offence for bad indentation in an if body' do
10
+ inspect_source(cop,
11
+ ['if cond',
12
+ ' func',
13
+ ' func',
14
+ 'end'])
15
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
16
+ end
17
+
18
+ it 'registers an offence for bad indentation in an else body' do
19
+ inspect_source(cop,
20
+ ['if cond',
21
+ ' func1',
22
+ 'else',
23
+ ' func2',
24
+ ' func2',
25
+ 'end'])
26
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
27
+ end
28
+
29
+ it 'registers an offence for bad indentation in an elsif body' do
30
+ inspect_source(cop,
31
+ ['if a1',
32
+ ' b1',
33
+ 'elsif a2',
34
+ ' b2',
35
+ 'b3',
36
+ 'else',
37
+ ' c',
38
+ 'end'])
39
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
40
+ end
41
+
42
+ it 'accepts a one line if statement' do
43
+ inspect_source(cop,
44
+ ['if cond then func1 else func2 end'])
45
+ expect(cop.offences).to be_empty
46
+ end
47
+
48
+ it 'accepts a correctly aligned if/elsif/else/end' do
49
+ inspect_source(cop,
50
+ ['if a1',
51
+ ' b1',
52
+ 'elsif a2',
53
+ ' b2',
54
+ 'else',
55
+ ' c',
56
+ 'end'])
57
+ expect(cop.offences).to be_empty
58
+ end
59
+
60
+ it 'accepts if/elsif/else/end laid out as a table' do
61
+ inspect_source(cop,
62
+ ['if @io == $stdout then str << "$stdout"',
63
+ 'elsif @io == $stdin then str << "$stdin"',
64
+ 'elsif @io == $stderr then str << "$stderr"',
65
+ 'else str << @io.class.to_s',
66
+ 'end'])
67
+ expect(cop.offences).to be_empty
68
+ end
69
+
70
+ it 'accepts if/then/else/end laid out as another table' do
71
+ inspect_source(cop,
72
+ ["if File.exist?('config.save')",
73
+ 'then ConfigTable.load',
74
+ 'else ConfigTable.new',
75
+ 'end'])
76
+ expect(cop.offences).to be_empty
77
+ end
78
+
79
+ it 'accepts an empty if' do
80
+ inspect_source(cop,
81
+ ['if a',
82
+ 'else',
83
+ 'end'])
84
+ expect(cop.offences).to be_empty
85
+ end
86
+
87
+ it 'accepts an if in assignment with end aligned with variable' do
88
+ inspect_source(cop,
89
+ ['var = if a',
90
+ ' 0',
91
+ 'end',
92
+ '@var = if a',
93
+ ' 0',
94
+ 'end',
95
+ '$var = if a',
96
+ ' 0',
97
+ 'end',
98
+ 'var ||= if a',
99
+ ' 0',
100
+ 'end',
101
+ 'var &&= if a',
102
+ ' 0',
103
+ 'end',
104
+ 'var -= if a',
105
+ ' 0',
106
+ 'end',
107
+ 'VAR = if a',
108
+ ' 0',
109
+ 'end'])
110
+ expect(cop.offences).to be_empty
111
+ end
112
+
113
+ it 'accepts an if/else in assignment with end aligned with variable' do
114
+ inspect_source(cop,
115
+ ['var = if a',
116
+ ' 0',
117
+ 'else',
118
+ ' 1',
119
+ 'end'])
120
+ expect(cop.offences).to be_empty
121
+ end
122
+
123
+ it 'accepts an if/else in assignment with end aligned with variable ' +
124
+ 'and chaining after the end' do
125
+ inspect_source(cop,
126
+ ['var = if a',
127
+ ' 0',
128
+ 'else',
129
+ ' 1',
130
+ 'end.abc.join("")'])
131
+ expect(cop.offences).to be_empty
132
+ end
133
+
134
+ it 'accepts an if/else in assignment with end aligned with variable ' +
135
+ 'and chaining with a block after the end' do
136
+ inspect_source(cop,
137
+ ['var = if a',
138
+ ' 0',
139
+ 'else',
140
+ ' 1',
141
+ 'end.abc.tap {}'])
142
+ expect(cop.offences).to be_empty
143
+ end
144
+
145
+ it 'accepts an if in assignment with end aligned with if' do
146
+ inspect_source(cop,
147
+ ['var = if a',
148
+ ' 0',
149
+ ' end'])
150
+ expect(cop.offences).to be_empty
151
+ end
152
+
153
+ it 'accepts an if/else in assignment with end aligned with if' do
154
+ inspect_source(cop,
155
+ ['var = if a',
156
+ ' 0',
157
+ ' else',
158
+ ' 1',
159
+ ' end'])
160
+ expect(cop.offences).to be_empty
161
+ end
162
+
163
+ it 'accepts an if/else in assignment on next line with end aligned ' +
164
+ 'with if' do
165
+ inspect_source(cop,
166
+ ['var =',
167
+ ' if a',
168
+ ' 0',
169
+ ' else',
170
+ ' 1',
171
+ ' end'])
172
+ expect(cop.offences).to be_empty
173
+ end
174
+
175
+ it 'accepts an if/else branches with rescue clauses' do
176
+ # Because of how the rescue clauses come out of Parser, these are
177
+ # special and need to be tested.
178
+ inspect_source(cop,
179
+ ['if a',
180
+ ' a rescue nil',
181
+ 'else',
182
+ ' a rescue nil',
183
+ 'end'])
184
+ expect(cop.offences).to be_empty
185
+ end
186
+ end
187
+
188
+ context 'with unless' do
189
+ it 'registers an offence for bad indentation in an unless body' do
190
+ inspect_source(cop,
191
+ ['unless cond',
192
+ ' func',
193
+ ' func',
194
+ 'end'])
195
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
196
+ end
197
+
198
+ it 'accepts an empty unless' do
199
+ inspect_source(cop,
200
+ ['unless a',
201
+ 'else',
202
+ 'end'])
203
+ expect(cop.offences).to be_empty
204
+ end
205
+ end
206
+
207
+ context 'with case' do
208
+ it 'registers an offence for bad indentation in a case/when body' do
209
+ inspect_source(cop,
210
+ ['case a',
211
+ 'when b',
212
+ ' c',
213
+ ' d',
214
+ 'end'])
215
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
216
+ end
217
+
218
+ it 'registers an offence for bad indentation in a case/else body' do
219
+ inspect_source(cop,
220
+ ['case a',
221
+ 'when b',
222
+ ' c',
223
+ 'when d',
224
+ ' e',
225
+ 'else',
226
+ ' f',
227
+ ' g',
228
+ 'end'])
229
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
230
+ end
231
+
232
+ it 'accepts correctly indented case/when/else' do
233
+ inspect_source(cop,
234
+ ['case a',
235
+ 'when b',
236
+ ' c',
237
+ ' c',
238
+ 'when d',
239
+ 'else',
240
+ ' f',
241
+ 'end'])
242
+ expect(cop.offences).to be_empty
243
+ end
244
+
245
+ it 'accepts case/when/else laid out as a table' do
246
+ inspect_source(cop,
247
+ ['case sexp.loc.keyword.source',
248
+ "when 'if' then cond, body, _else = *sexp",
249
+ "when 'unless' then cond, _else, body = *sexp",
250
+ 'else cond, body = *sexp',
251
+ 'end'])
252
+ expect(cop.offences).to be_empty
253
+ end
254
+
255
+ it 'accepts case/when/else with then beginning a line' do
256
+ inspect_source(cop,
257
+ ['case sexp.loc.keyword.source',
258
+ "when 'if'",
259
+ 'then cond, body, _else = *sexp',
260
+ 'end'])
261
+ expect(cop.offences).to be_empty
262
+ end
263
+
264
+ it 'accepts indented when/else plus indented body' do
265
+ # "Indent when as deep as case" is the job of another cop.
266
+ inspect_source(cop,
267
+ ['case code_type',
268
+ " when 'ruby', 'sql', 'plain'",
269
+ ' code_type',
270
+ " when 'erb'",
271
+ " 'ruby; html-script: true'",
272
+ ' when "html"',
273
+ " 'xml'",
274
+ ' else',
275
+ " 'plain'",
276
+ 'end'])
277
+ expect(cop.offences).to be_empty
278
+ end
279
+ end
280
+
281
+ context 'with while/until' do
282
+ it 'registers an offence for bad indentation in a while body' do
283
+ inspect_source(cop,
284
+ ['while cond',
285
+ ' func',
286
+ ' func',
287
+ 'end'])
288
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
289
+ end
290
+
291
+ it 'registers an offence for bad indentation in begin/end/while' do
292
+ inspect_source(cop,
293
+ ['something = begin',
294
+ ' func1',
295
+ ' func2',
296
+ 'end while cond'])
297
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
298
+ end
299
+
300
+ it 'registers an offence for bad indentation in an until body' do
301
+ inspect_source(cop,
302
+ ['until cond',
303
+ ' func',
304
+ ' func',
305
+ 'end'])
306
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
307
+ end
308
+
309
+ it 'accepts an empty while' do
310
+ inspect_source(cop,
311
+ ['while a',
312
+ 'end'])
313
+ expect(cop.offences).to be_empty
314
+ end
315
+ end
316
+
317
+ context 'with for' do
318
+ it 'registers an offence for bad indentation in a for body' do
319
+ inspect_source(cop,
320
+ ['for var in 1..10',
321
+ ' func',
322
+ 'func',
323
+ 'end'])
324
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
325
+ end
326
+
327
+ it 'accepts an empty for' do
328
+ inspect_source(cop,
329
+ ['for var in 1..10',
330
+ 'end'])
331
+ expect(cop.offences).to be_empty
332
+ end
333
+ end
334
+
335
+ context 'with def/defs' do
336
+ it 'registers an offence for bad indentation in a def body' do
337
+ inspect_source(cop,
338
+ ['def test',
339
+ ' func1',
340
+ ' func2',
341
+ 'end'])
342
+ expect(cop.messages)
343
+ .to eq(['Inconsistent indentation detected.'])
344
+ end
345
+
346
+ it 'registers an offence for bad indentation in a defs body' do
347
+ inspect_source(cop,
348
+ ['def self.test',
349
+ ' func',
350
+ ' func',
351
+ 'end'])
352
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
353
+ end
354
+
355
+ it 'accepts an empty def body' do
356
+ inspect_source(cop,
357
+ ['def test',
358
+ 'end'])
359
+ expect(cop.offences).to be_empty
360
+ end
361
+
362
+ it 'accepts an empty defs body' do
363
+ inspect_source(cop,
364
+ ['def self.test',
365
+ 'end'])
366
+ expect(cop.offences).to be_empty
367
+ end
368
+ end
369
+
370
+ context 'with class' do
371
+ it 'registers an offence for bad indentation in a class body' do
372
+ inspect_source(cop,
373
+ ['class Test',
374
+ ' def func1',
375
+ ' end',
376
+ ' def func2',
377
+ ' end',
378
+ 'end'])
379
+ expect(cop.messages)
380
+ .to eq(['Inconsistent indentation detected.'])
381
+ end
382
+
383
+ it 'accepts an empty class body' do
384
+ inspect_source(cop,
385
+ ['class Test',
386
+ 'end'])
387
+ expect(cop.offences).to be_empty
388
+ end
389
+
390
+ it 'accepts indented public, protected, and private' do
391
+ inspect_source(cop,
392
+ ['class Test',
393
+ ' public',
394
+ '',
395
+ ' def e',
396
+ ' end',
397
+ '',
398
+ ' protected',
399
+ '',
400
+ ' def f',
401
+ ' end',
402
+ '',
403
+ ' private',
404
+ '',
405
+ ' def g',
406
+ ' end',
407
+ 'end'])
408
+ expect(cop.offences).to be_empty
409
+ end
410
+
411
+ it 'registers an offence for bad indentation in def but not for ' +
412
+ 'outdented public, protected, and private' do
413
+ inspect_source(cop,
414
+ ['class Test',
415
+ 'public',
416
+ '',
417
+ ' def e',
418
+ ' end',
419
+ '',
420
+ 'protected',
421
+ '',
422
+ ' def f',
423
+ ' end',
424
+ '',
425
+ 'private',
426
+ '',
427
+ ' def g',
428
+ ' end',
429
+ 'end'])
430
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
431
+ expect(cop.highlights).to eq([' '])
432
+ end
433
+ end
434
+
435
+ context 'with module' do
436
+ it 'registers an offence for bad indentation in a module body' do
437
+ inspect_source(cop,
438
+ ['module Test',
439
+ ' def func1',
440
+ ' end',
441
+ ' def func2',
442
+ ' end',
443
+ 'end'])
444
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
445
+ end
446
+
447
+ it 'accepts an empty module body' do
448
+ inspect_source(cop,
449
+ ['module Test',
450
+ 'end'])
451
+ expect(cop.offences).to be_empty
452
+ end
453
+ end
454
+
455
+ context 'with block' do
456
+ it 'registers an offence for bad indentation in a do/end body' do
457
+ inspect_source(cop,
458
+ ['a = func do',
459
+ ' b',
460
+ ' c',
461
+ 'end'])
462
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
463
+ end
464
+
465
+ it 'registers an offence for bad indentation in a {} body' do
466
+ inspect_source(cop,
467
+ ['func {',
468
+ ' b',
469
+ ' c',
470
+ '}'])
471
+ expect(cop.messages).to eq(['Inconsistent indentation detected.'])
472
+ end
473
+
474
+ it 'accepts a correctly indented block body' do
475
+ inspect_source(cop,
476
+ ['a = func do',
477
+ ' b',
478
+ ' c',
479
+ 'end'])
480
+ expect(cop.offences).to be_empty
481
+ end
482
+
483
+ it 'accepts an empty block body' do
484
+ inspect_source(cop,
485
+ ['a = func do',
486
+ 'end'])
487
+ expect(cop.offences).to be_empty
488
+ end
489
+ end
490
+ end