rubocop 0.25.0 → 0.26.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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +37 -0
  4. data/README.md +2 -2
  5. data/assets/output.html.erb +190 -0
  6. data/config/default.yml +14 -2
  7. data/config/disabled.yml +7 -0
  8. data/config/enabled.yml +132 -5
  9. data/lib/rubocop.rb +5 -0
  10. data/lib/rubocop/cop/commissioner.rb +4 -10
  11. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -1
  12. data/lib/rubocop/cop/lint/end_in_method.rb +3 -8
  13. data/lib/rubocop/cop/lint/ensure_return.rb +2 -2
  14. data/lib/rubocop/cop/lint/space_before_first_arg.rb +8 -1
  15. data/lib/rubocop/cop/lint/useless_assignment.rb +35 -0
  16. data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -3
  17. data/lib/rubocop/cop/metrics/block_nesting.rb +3 -3
  18. data/lib/rubocop/cop/metrics/class_length.rb +1 -2
  19. data/lib/rubocop/cop/mixin/access_modifier_node.rb +5 -1
  20. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +2 -2
  21. data/lib/rubocop/cop/mixin/configurable_naming.rb +2 -2
  22. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -4
  23. data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -3
  24. data/lib/rubocop/cop/rails/delegate.rb +1 -1
  25. data/lib/rubocop/cop/rails/validation.rb +25 -2
  26. data/lib/rubocop/cop/style/alias.rb +1 -1
  27. data/lib/rubocop/cop/style/and_or.rb +12 -2
  28. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +19 -12
  29. data/lib/rubocop/cop/style/documentation.rb +1 -1
  30. data/lib/rubocop/cop/style/dot_position.rb +20 -0
  31. data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +5 -1
  32. data/lib/rubocop/cop/style/encoding.rb +4 -4
  33. data/lib/rubocop/cop/style/format_string.rb +12 -2
  34. data/lib/rubocop/cop/style/if_unless_modifier.rb +8 -11
  35. data/lib/rubocop/cop/style/infinite_loop.rb +57 -0
  36. data/lib/rubocop/cop/style/multiline_block_chain.rb +15 -16
  37. data/lib/rubocop/cop/style/multiline_if_then.rb +10 -0
  38. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -3
  39. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -1
  40. data/lib/rubocop/cop/style/predicate_name.rb +23 -5
  41. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  42. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  43. data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +4 -8
  44. data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +9 -11
  45. data/lib/rubocop/cop/style/space_inside_range_literal.rb +58 -0
  46. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  47. data/lib/rubocop/cop/style/symbol_proc.rb +71 -0
  48. data/lib/rubocop/cop/style/tab.rb +11 -3
  49. data/lib/rubocop/cop/style/unneeded_capital_w.rb +6 -2
  50. data/lib/rubocop/cop/style/variable_name.rb +4 -14
  51. data/lib/rubocop/cop/style/while_until_modifier.rb +12 -8
  52. data/lib/rubocop/cop/variable_force.rb +17 -30
  53. data/lib/rubocop/cop/variable_force/assignment.rb +15 -23
  54. data/lib/rubocop/cop/variable_force/locatable.rb +29 -8
  55. data/lib/rubocop/cop/variable_force/scope.rb +34 -23
  56. data/lib/rubocop/cop/variable_force/variable.rb +7 -10
  57. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
  58. data/lib/rubocop/formatter/formatter_set.rb +1 -0
  59. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  60. data/lib/rubocop/formatter/html_formatter.rb +90 -0
  61. data/lib/rubocop/formatter/progress_formatter.rb +1 -1
  62. data/lib/rubocop/options.rb +1 -0
  63. data/lib/rubocop/processed_source.rb +10 -1
  64. data/lib/rubocop/string_util.rb +153 -0
  65. data/lib/rubocop/target_finder.rb +1 -1
  66. data/lib/rubocop/version.rb +1 -1
  67. data/relnotes/v0.26.0.md +89 -0
  68. data/rubocop.gemspec +1 -0
  69. data/spec/rubocop/cli_spec.rb +60 -34
  70. data/spec/rubocop/config_loader_spec.rb +19 -15
  71. data/spec/rubocop/cop/commissioner_spec.rb +2 -2
  72. data/spec/rubocop/cop/lint/block_alignment_spec.rb +74 -58
  73. data/spec/rubocop/cop/lint/space_before_first_arg_spec.rb +7 -0
  74. data/spec/rubocop/cop/lint/useless_assignment_spec.rb +173 -0
  75. data/spec/rubocop/cop/rails/validation_spec.rb +9 -2
  76. data/spec/rubocop/cop/style/access_modifier_indentation_spec.rb +26 -0
  77. data/spec/rubocop/cop/style/and_or_spec.rb +52 -61
  78. data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +26 -8
  79. data/spec/rubocop/cop/style/case_indentation_spec.rb +8 -8
  80. data/spec/rubocop/cop/style/def_with_parentheses_spec.rb +6 -2
  81. data/spec/rubocop/cop/style/dot_position_spec.rb +39 -0
  82. data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +12 -2
  83. data/spec/rubocop/cop/style/encoding_spec.rb +16 -28
  84. data/spec/rubocop/cop/style/format_string_spec.rb +12 -0
  85. data/spec/rubocop/cop/style/infinite_loop_spec.rb +48 -0
  86. data/spec/rubocop/cop/style/method_def_parentheses_spec.rb +3 -1
  87. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +9 -0
  88. data/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb +21 -1
  89. data/spec/rubocop/cop/style/predicate_name_spec.rb +44 -13
  90. data/spec/rubocop/cop/style/redundant_begin_spec.rb +32 -0
  91. data/spec/rubocop/cop/style/space_inside_range_literal_spec.rb +52 -0
  92. data/spec/rubocop/cop/style/symbol_proc_spec.rb +76 -0
  93. data/spec/rubocop/cop/style/tab_spec.rb +30 -0
  94. data/spec/rubocop/cop/style/trailing_whitespace_spec.rb +2 -1
  95. data/spec/rubocop/cop/style/unneeded_capital_w_spec.rb +18 -5
  96. data/spec/rubocop/cop/style/variable_name_spec.rb +5 -5
  97. data/spec/rubocop/cop/style/when_then_spec.rb +3 -1
  98. data/spec/rubocop/cop/style/while_until_do_spec.rb +4 -2
  99. data/spec/rubocop/cop/util_spec.rb +1 -9
  100. data/spec/rubocop/cop/variable_force/assignment_spec.rb +2 -15
  101. data/spec/rubocop/cop/variable_force/locatable_spec.rb +2 -37
  102. data/spec/rubocop/cop/variable_force/scope_spec.rb +156 -49
  103. data/spec/rubocop/cop/variable_force/variable_spec.rb +2 -1
  104. data/spec/rubocop/cop/variable_force_spec.rb +2 -1
  105. data/spec/rubocop/formatter/emacs_style_formatter_spec.rb +2 -1
  106. data/spec/rubocop/formatter/html_formatter_spec.rb +145 -0
  107. data/spec/rubocop/formatter/simple_text_formatter_spec.rb +18 -6
  108. data/spec/rubocop/options_spec.rb +1 -0
  109. data/spec/rubocop/path_util_spec.rb +6 -4
  110. data/spec/rubocop/processed_source_spec.rb +17 -1
  111. data/spec/rubocop/string_util_spec.rb +46 -0
  112. metadata +33 -4
  113. data/spec/support/ast_helper.rb +0 -15
@@ -51,10 +51,10 @@ describe RuboCop::Cop::Style::VariableName, :config do
51
51
  expect(cop.highlights).to eq(['@myAttribute'])
52
52
  end
53
53
 
54
- it 'registers an offense for camel case in setter name' do
55
- inspect_source(cop, 'self.mySetter = 2')
54
+ it 'registers an offense for camel case in class variable name' do
55
+ inspect_source(cop, '@@myAttr = 2')
56
56
  expect(cop.offenses.size).to eq(1)
57
- expect(cop.highlights).to eq(['mySetter'])
57
+ expect(cop.highlights).to eq(['@@myAttr'])
58
58
  end
59
59
 
60
60
  include_examples 'always accepted'
@@ -88,8 +88,8 @@ describe RuboCop::Cop::Style::VariableName, :config do
88
88
  expect(cop.offenses).to be_empty
89
89
  end
90
90
 
91
- it 'accepts camel case in setter name' do
92
- inspect_source(cop, 'self.mySetter = 2')
91
+ it 'accepts camel case in class variable name' do
92
+ inspect_source(cop, '@@myAttr = 2')
93
93
  expect(cop.offenses).to be_empty
94
94
  end
95
95
 
@@ -35,6 +35,8 @@ describe RuboCop::Cop::Style::WhenThen do
35
35
  new_source = autocorrect_source(cop, ['case a',
36
36
  'when b; c',
37
37
  'end'])
38
- expect(new_source).to eq("case a\nwhen b then c\nend")
38
+ expect(new_source).to eq(['case a',
39
+ 'when b then c',
40
+ 'end'].join("\n"))
39
41
  end
40
42
  end
@@ -42,12 +42,14 @@ describe RuboCop::Cop::Style::WhileUntilDo do
42
42
  it 'auto-corrects the usage of "do" in multiline while' do
43
43
  new_source = autocorrect_source(cop, ['while cond do',
44
44
  'end'])
45
- expect(new_source).to eq("while cond\nend")
45
+ expect(new_source).to eq(['while cond',
46
+ 'end'].join("\n"))
46
47
  end
47
48
 
48
49
  it 'auto-corrects the usage of "do" in multiline until' do
49
50
  new_source = autocorrect_source(cop, ['until cond do',
50
51
  'end'])
51
- expect(new_source).to eq("until cond\nend")
52
+ expect(new_source).to eq(['until cond',
53
+ 'end'].join("\n"))
52
54
  end
53
55
  end
@@ -4,8 +4,6 @@ require 'spec_helper'
4
4
 
5
5
  describe RuboCop::Cop::Util do
6
6
  describe '#line_range' do
7
- include ASTHelper
8
-
9
7
  let(:source) do
10
8
  <<-END
11
9
  foo = 1
@@ -24,13 +22,7 @@ describe RuboCop::Cop::Util do
24
22
  processed_source.ast
25
23
  end
26
24
 
27
- let(:node) do
28
- target_node = scan_node(ast) do |node|
29
- break node if node.type == :class
30
- end
31
- fail 'No target node found!' unless target_node
32
- target_node
33
- end
25
+ let(:node) { ast.each_node.find(&:class_type?) }
34
26
 
35
27
  context 'when Source::Range object is passed' do
36
28
  it 'returns line range of that' do
@@ -3,7 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe RuboCop::Cop::VariableForce::Assignment do
6
- include ASTHelper
7
6
  include AST::Sexp
8
7
 
9
8
  let(:ast) do
@@ -25,21 +24,9 @@ describe RuboCop::Cop::VariableForce::Assignment do
25
24
  END
26
25
  end
27
26
 
28
- let(:def_node) do
29
- found_node = scan_node(ast, include_origin_node: true) do |node|
30
- break node if node.type == :def
31
- end
32
- fail 'No def node found!' unless found_node
33
- found_node
34
- end
27
+ let(:def_node) { ast.each_node.find(&:def_type?) }
35
28
 
36
- let(:lvasgn_node) do
37
- found_node = scan_node(ast) do |node|
38
- break node if node.type == :lvasgn
39
- end
40
- fail 'No lvasgn node found!' unless found_node
41
- found_node
42
- end
29
+ let(:lvasgn_node) { ast.each_node.find(&:lvasgn_type?) }
43
30
 
44
31
  let(:name) { lvasgn_node.children.first }
45
32
  let(:scope) { RuboCop::Cop::VariableForce::Scope.new(def_node) }
@@ -3,7 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe RuboCop::Cop::VariableForce::Locatable do
6
- include ASTHelper
7
6
  include AST::Sexp
8
7
 
9
8
  class LocatableObject
@@ -22,46 +21,12 @@ describe RuboCop::Cop::VariableForce::Locatable do
22
21
  processed_source.ast
23
22
  end
24
23
 
25
- let(:def_node) do
26
- found_node = scan_node(ast, include_origin_node: true) do |node|
27
- break node if node.type == :def
28
- end
29
- fail 'No def node found!' unless found_node
30
- found_node
31
- end
32
-
33
- let(:lvasgn_node) do
34
- found_node = scan_node(ast) do |node|
35
- break node if node.type == :lvasgn
36
- end
37
- fail 'No lvasgn node found!' unless found_node
38
- found_node
39
- end
24
+ let(:def_node) { ast.each_node.find(&:def_type?) }
25
+ let(:lvasgn_node) { ast.each_node.find(&:lvasgn_type?) }
40
26
 
41
27
  let(:scope) { RuboCop::Cop::VariableForce::Scope.new(def_node) }
42
28
  let(:assignment) { LocatableObject.new(lvasgn_node, scope) }
43
29
 
44
- describe '#ancestor_nodes_in_scope' do
45
- let(:source) do
46
- <<-END
47
- class SomeClass
48
- def some_method(flag)
49
- puts 'Hello World!'
50
-
51
- if flag > 0
52
- foo = 1
53
- end
54
- end
55
- end
56
- END
57
- end
58
-
59
- it 'returns its ancestor nodes in the scope excluding scope node' do
60
- ancestor_types = assignment.ancestor_nodes_in_scope.map(&:type)
61
- expect(ancestor_types).to eq([:begin, :if])
62
- end
63
- end
64
-
65
30
  describe '#branch_point_node' do
66
31
  context 'when it is not in branch' do
67
32
  let(:source) do
@@ -3,7 +3,6 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe RuboCop::Cop::VariableForce::Scope do
6
- include ASTHelper
7
6
  include AST::Sexp
8
7
 
9
8
  describe '.new' do
@@ -24,18 +23,12 @@ describe RuboCop::Cop::VariableForce::Scope do
24
23
 
25
24
  let(:ast) do
26
25
  ast = RuboCop::ProcessedSource.new(source).ast
27
- RuboCop::Cop::VariableForce.wrap_with_top_level_node(ast)
26
+ RuboCop::Cop::VariableForce.wrap_with_top_level_scope_node(ast)
28
27
  end
29
28
 
30
29
  let(:scope_node_type) { :def }
31
30
 
32
- let(:scope_node) do
33
- found_node = scan_node(ast, include_origin_node: true) do |node|
34
- break node if node.type == scope_node_type
35
- end
36
- fail 'No scope node found!' unless found_node
37
- found_node
38
- end
31
+ let(:scope_node) { ast.each_node(scope_node_type).first }
39
32
 
40
33
  subject(:scope) { described_class.new(scope_node) }
41
34
 
@@ -67,45 +60,6 @@ describe RuboCop::Cop::VariableForce::Scope do
67
60
  end
68
61
  end
69
62
 
70
- describe '#ancestors_of_node' do
71
- let(:source) do
72
- <<-END
73
- puts 1
74
-
75
- class SomeClass
76
- def some_method
77
- foo = 1
78
-
79
- if foo > 0
80
- while foo < 10
81
- this_is_target
82
- foo += 1
83
- end
84
- else
85
- do_something
86
- end
87
- end
88
- end
89
- END
90
- end
91
-
92
- let(:target_node) do
93
- found_node = scan_node(ast) do |node|
94
- next unless node.type == :send
95
- _receiver_node, method_name = *node
96
- break node if method_name == :this_is_target
97
- end
98
- fail 'No target node found!' unless found_node
99
- found_node
100
- end
101
-
102
- it 'returns nodes in between the scope node and the passed node' do
103
- ancestor_nodes = scope.ancestors_of_node(target_node)
104
- ancestor_types = ancestor_nodes.map(&:type)
105
- expect(ancestor_types).to eq([:begin, :if, :while, :begin])
106
- end
107
- end
108
-
109
63
  describe '#body_node' do
110
64
  shared_examples 'returns the body node' do
111
65
  it 'returns the body node' do
@@ -204,9 +158,162 @@ describe RuboCop::Cop::VariableForce::Scope do
204
158
  END
205
159
  end
206
160
 
207
- let(:scope_node_type) { :top_level }
161
+ let(:scope_node_type) { :begin }
208
162
 
209
163
  include_examples 'returns the body node'
210
164
  end
211
165
  end
166
+
167
+ describe '#each_node' do
168
+ shared_examples 'yields' do |description|
169
+ it "yields #{description}" do
170
+ yielded_types = []
171
+
172
+ scope.each_node do |node|
173
+ yielded_types << node.type
174
+ end
175
+
176
+ expect(yielded_types).to eq(expected_types.map(&:to_sym))
177
+ end
178
+ end
179
+
180
+ describe 'outer scope boundary handling' do
181
+ context 'when the scope is instance method' do
182
+ let(:source) { <<-END }
183
+ def some_method(arg1, arg2)
184
+ :body
185
+ end
186
+ END
187
+
188
+ let(:scope_node_type) { :def }
189
+ let(:expected_types) { %w(args arg arg sym) }
190
+ include_examples 'yields', 'the argument and the body nodes'
191
+ end
192
+
193
+ context 'when the scope is singleton method' do
194
+ let(:source) { <<-END }
195
+ def self.some_method(arg1, arg2)
196
+ :body
197
+ end
198
+ END
199
+
200
+ let(:scope_node_type) { :defs }
201
+ let(:expected_types) { %w(args arg arg sym) }
202
+ include_examples 'yields', 'the argument and the body nodes'
203
+ end
204
+
205
+ context 'when the scope is module' do
206
+ let(:source) { <<-END }
207
+ module SomeModule
208
+ :body
209
+ end
210
+ END
211
+
212
+ let(:scope_node_type) { :module }
213
+ let(:expected_types) { %w(sym) }
214
+ include_examples 'yields', 'the body nodes'
215
+ end
216
+
217
+ context 'when the scope is class' do
218
+ let(:source) { <<-END }
219
+ some_super_class = Class.new
220
+
221
+ class SomeClass < some_super_class
222
+ :body
223
+ end
224
+ END
225
+
226
+ let(:scope_node_type) { :class }
227
+ let(:expected_types) { %w(sym) }
228
+ include_examples 'yields', 'the body nodes'
229
+ end
230
+
231
+ context 'when the scope is singleton class' do
232
+ let(:source) { <<-END }
233
+ some_object = Object.new
234
+
235
+ class << some_object
236
+ :body
237
+ end
238
+ END
239
+
240
+ let(:scope_node_type) { :sclass }
241
+ let(:expected_types) { %w(sym) }
242
+ include_examples 'yields', 'the body nodes'
243
+ end
244
+
245
+ context 'when the scope is block' do
246
+ let(:source) { <<-END }
247
+ 1.times do |arg1, arg2|
248
+ :body
249
+ end
250
+ END
251
+
252
+ let(:scope_node_type) { :block }
253
+ let(:expected_types) { %w(args arg arg sym) }
254
+ include_examples 'yields', 'the argument and the body nodes'
255
+ end
256
+
257
+ context 'when the scope is top level' do
258
+ let(:source) { <<-END }
259
+ :body
260
+ END
261
+
262
+ let(:scope_node_type) { :begin }
263
+ let(:expected_types) { %w(sym) }
264
+ include_examples 'yields', 'the body nodes'
265
+ end
266
+ end
267
+
268
+ describe 'inner scope boundary handling' do
269
+ context "when there's a method invocation with block" do
270
+ let(:source) { <<-END }
271
+ foo = 1
272
+
273
+ do_something(1, 2) do |arg|
274
+ :body
275
+ end
276
+
277
+ foo
278
+ END
279
+
280
+ let(:scope_node_type) { :begin }
281
+ let(:expected_types) { %w(lvasgn int block send int int lvar) }
282
+ include_examples 'yields', 'only the block node and the child send node'
283
+ end
284
+
285
+ context "when there's a singleton method definition" do
286
+ let(:source) { <<-END }
287
+ foo = 1
288
+
289
+ def self.some_method(arg1, arg2)
290
+ :body
291
+ end
292
+
293
+ foo
294
+ END
295
+
296
+ let(:scope_node_type) { :begin }
297
+ let(:expected_types) { %w(lvasgn int defs self lvar) }
298
+ include_examples 'yields', 'only the defs node and the method host node'
299
+ end
300
+
301
+ context 'when there are grouped nodes with a begin node' do
302
+ let(:source) { <<-END }
303
+ foo = 1
304
+
305
+ if true
306
+ do_something
307
+ do_anything
308
+ end
309
+
310
+ foo
311
+ END
312
+
313
+ let(:scope_node_type) { :begin }
314
+ let(:expected_types) { %w(lvasgn int if true begin send send lvar) }
315
+ include_examples 'yields', 'them without confused with top level scope'
316
+ end
317
+ end
318
+ end
212
319
  end
@@ -1,9 +1,10 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
+ require 'astrolabe/sexp'
4
5
 
5
6
  describe RuboCop::Cop::VariableForce::Variable do
6
- include AST::Sexp
7
+ include Astrolabe::Sexp
7
8
 
8
9
  describe '.new' do
9
10
  context 'when non variable declaration node is passed' do
@@ -1,9 +1,10 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
+ require 'astrolabe/sexp'
4
5
 
5
6
  describe RuboCop::Cop::VariableForce do
6
- include AST::Sexp
7
+ include Astrolabe::Sexp
7
8
 
8
9
  subject(:force) { described_class.new([]) }
9
10
 
@@ -24,7 +24,8 @@ module RuboCop
24
24
 
25
25
  formatter.file_finished('test', cop.offenses)
26
26
  expect(output.string).to eq ['test:1:1: C: message 1',
27
- "test:3:6: C: message 2\n"].join("\n")
27
+ 'test:3:6: C: message 2',
28
+ ''].join("\n")
28
29
  end
29
30
 
30
31
  context 'when the offense is automatically corrected' do
@@ -0,0 +1,145 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'stringio'
5
+
6
+ module RuboCop
7
+ describe Formatter::HTMLFormatter do
8
+ subject(:formatter) { described_class.new(output) }
9
+ let(:output) { StringIO.new }
10
+ let(:files) { %w(/path/to/file1 /path/to/file2) }
11
+ let(:location) do
12
+ source_buffer = Parser::Source::Buffer.new('test', 1)
13
+ source_buffer.source = %w(a b cdefghi).join("\n")
14
+ Parser::Source::Range.new(source_buffer, 9, 10)
15
+ end
16
+ let(:offense) do
17
+ Cop::Offense.new(:convention, location,
18
+ 'This is message', 'CopName', true)
19
+ end
20
+
21
+ describe '#started' do
22
+ let(:summary) { formatter.output_hash[:summary] }
23
+
24
+ it 'sets target file count in summary' do
25
+ expect(summary[:target_file_count]).to be_nil
26
+ formatter.started(%w(/path/to/file1 /path/to/file2))
27
+ expect(summary[:target_file_count]).to eq(2)
28
+ end
29
+ end
30
+
31
+ describe '#file_finished' do
32
+ before do
33
+ count = 0
34
+ allow(formatter).to receive(:hash_for_file) do
35
+ count += 1
36
+ end
37
+ end
38
+
39
+ let(:summary) { formatter.output_hash[:summary] }
40
+
41
+ it 'adds detected offense count in summary' do
42
+ expect(summary[:offense_count]).to eq(0)
43
+
44
+ formatter.file_started(files[0], {})
45
+ expect(summary[:offense_count]).to eq(0)
46
+ formatter.file_finished(files[0], [
47
+ double('offense1'), double('offense2')
48
+ ])
49
+ expect(summary[:offense_count]).to eq(2)
50
+ end
51
+
52
+ it 'adds value of #hash_for_file to #output_hash[:files]' do
53
+ expect(formatter.output_hash[:files]).to be_empty
54
+
55
+ formatter.file_started(files[0], {})
56
+ expect(formatter.output_hash[:files]).to be_empty
57
+ formatter.file_finished(files[0], [])
58
+ expect(formatter.output_hash[:files]).to eq([1])
59
+
60
+ formatter.file_started(files[1], {})
61
+ expect(formatter.output_hash[:files]).to eq([1])
62
+ formatter.file_finished(files[1], [])
63
+ expect(formatter.output_hash[:files]).to eq([1, 2])
64
+ end
65
+ end
66
+
67
+ describe '#finished' do
68
+ let(:summary) { formatter.output_hash[:summary] }
69
+
70
+ it 'sets inspected file count in summary' do
71
+ expect(summary[:inspected_file_count]).to be_nil
72
+ formatter.finished(%w(/path/to/file1 /path/to/file2))
73
+ expect(summary[:inspected_file_count]).to eq(2)
74
+ end
75
+ end
76
+
77
+ describe '#hash_for_file' do
78
+ subject(:hash) { formatter.hash_for_file(file, offenses) }
79
+ let(:file) { File.expand_path('spec/spec_helper.rb') }
80
+ let(:offenses) { [double('offense1'), double('offense2')] }
81
+
82
+ it 'sets relative file path for :path key' do
83
+ expect(hash[:path]).to eq('spec/spec_helper.rb')
84
+ end
85
+
86
+ before do
87
+ count = 0
88
+ allow(formatter).to receive(:hash_for_offense) do
89
+ count += 1
90
+ end
91
+ end
92
+
93
+ it 'sets an array of #hash_for_offense values for :offenses key' do
94
+ expect(hash[:offenses]).to eq([1, 2])
95
+ end
96
+ end
97
+
98
+ describe '#hash_for_offense' do
99
+ subject(:hash) { formatter.hash_for_offense(offense) }
100
+
101
+ it 'sets Offense#severity value for :severity key' do
102
+ expect(hash[:severity]).to eq(:convention)
103
+ end
104
+
105
+ it 'sets Offense#message value for :message key' do
106
+ expect(hash[:message]).to eq('This is message')
107
+ end
108
+
109
+ it 'sets Offense#cop_name value for :cop_name key' do
110
+ expect(hash[:cop_name]).to eq('CopName')
111
+ end
112
+
113
+ it 'sets Offense#corrected? value for :corrected key' do
114
+ expect(hash[:corrected]).to be_truthy
115
+ end
116
+
117
+ before do
118
+ allow(formatter)
119
+ .to receive(:hash_for_location).and_return(location_hash)
120
+ end
121
+
122
+ let(:location_hash) { { line: 1, column: 2 } }
123
+
124
+ it 'sets value of #hash_for_location for :location key' do
125
+ expect(hash[:location]).to eq(location_hash)
126
+ end
127
+ end
128
+
129
+ describe '#hash_for_location' do
130
+ subject(:hash) { formatter.hash_for_location(offense) }
131
+
132
+ it 'sets line value for :line key' do
133
+ expect(hash[:line]).to eq(3)
134
+ end
135
+
136
+ it 'sets column value for :column key' do
137
+ expect(hash[:column]).to eq(6)
138
+ end
139
+
140
+ it 'sets length value for :length key' do
141
+ expect(hash[:length]).to eq(1)
142
+ end
143
+ end
144
+ end
145
+ end