rubocop 0.8.1 → 0.8.2

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9d32a48395898e975b6e30a1e0c135d327b637d5
4
- data.tar.gz: 95923132f5031a94cea48306ba714e3510dd1f7a
3
+ metadata.gz: 43b3fd45d2ec7b330eca4a19651aa31157cef44a
4
+ data.tar.gz: d78bab05023a9fd28e0139d93e2f91be8b6bc972
5
5
  SHA512:
6
- metadata.gz: 5c1d467dc759961b51256357d3e3ba49d1476cb1dc2ed8c69d4b755092e19b20c78746595fc0e532fee545646e36061fbaec8f5a597374be0085fc4dee600f1c
7
- data.tar.gz: 51e01dbff570f1ffa8394a64cb7e2193f6717fad24fc5e6ce57468cb99c1385f8a8efc48433fbd25914dd6694bb978fca4edeed418e78738b7970a8536569972
6
+ metadata.gz: 35216ea2ef307f78e6867f982c09f66cb668777ddef1040fb18559053994cdbd9cbf05d5b45c2b98ae5467317d795e6c07be281a35dcc7b18cd49755cfda4a17
7
+ data.tar.gz: b6443382ef46eeea4490d1d74263b4d01b8afa671b56699373a61d627b17504887f1f36c7bfc526edd9048f0d4304621adb7b210dbdc3b59ce690b2eddfde3ba
@@ -4,10 +4,15 @@
4
4
 
5
5
  ### New features
6
6
 
7
+ * New cop `BlockNesting` checks for excessive block nesting
8
+
7
9
  ### Changes
8
10
 
9
11
  ### Bug fixes
10
12
 
13
+ * Correct calculation of whether a modifier version of a conditional statement will fit.
14
+ * Fix an error in `MultilineIfThen` cop that occurred in some special cases.
15
+
11
16
  ## 0.8.1 (05/30/2013)
12
17
 
13
18
  ### New features
@@ -44,3 +44,7 @@ SpaceInsideHashLiteralBraces:
44
44
  # Symbol literals should use snake_case.
45
45
  SymbolName:
46
46
  AllowCamelCase: true
47
+
48
+ # Avoid more than `Max` levels of nesting.
49
+ BlockNesting:
50
+ Max: 3
@@ -323,4 +323,8 @@ AccessControl:
323
323
 
324
324
  # Use Kernel#loop with break rather than begin/end/until or begin/end/while for post-loop tests.
325
325
  Loop:
326
- Enabled: true
326
+ Enabled: true
327
+
328
+ # Avoid excessive block nesting
329
+ BlockNesting:
330
+ Enabled: true
@@ -77,6 +77,7 @@ require 'rubocop/cop/not'
77
77
  require 'rubocop/cop/eval'
78
78
  require 'rubocop/cop/access_control'
79
79
  require 'rubocop/cop/loop'
80
+ require 'rubocop/cop/block_nesting'
80
81
 
81
82
  require 'rubocop/report/report'
82
83
  require 'rubocop/report/plain_text'
@@ -50,15 +50,15 @@ module Rubocop
50
50
  syntax_cop.debug = @options[:debug]
51
51
  syntax_cop.inspect_file(file)
52
52
 
53
- if syntax_cop.offences.map(&:severity).include?(:error)
54
- # In case of a syntax error we just report that error and do
55
- # no more checking in the file.
56
- report << syntax_cop
57
- @total_offences += syntax_cop.offences.count
58
- else
53
+ # In case of a syntax error we just report that error and do
54
+ # no more checking in the file.
55
+ unless syntax_cop.offences.map(&:severity).include?(:error)
59
56
  inspect_file(file, config, report)
60
57
  end
61
58
 
59
+ report << syntax_cop
60
+ @total_offences += syntax_cop.offences.count
61
+
62
62
  @processed_file_count += 1
63
63
  report.display unless report.empty?
64
64
  end
@@ -5,8 +5,12 @@ module Rubocop
5
5
  class AsciiComments < Cop
6
6
  MSG = 'Use only ascii symbols in comments.'
7
7
 
8
- def on_comment(c)
9
- add_offence(:convention, c.loc.line, MSG) if c.text =~ /[^\x00-\x7f]/
8
+ def inspect(source, tokens, ast, comments)
9
+ comments.each do |comment|
10
+ if comment.text =~ /[^\x00-\x7f]/
11
+ add_offence(:convention, comment.loc.line, MSG)
12
+ end
13
+ end
10
14
  end
11
15
  end
12
16
  end
@@ -5,9 +5,11 @@ module Rubocop
5
5
  class BlockComments < Cop
6
6
  MSG = 'Do not use block comments.'
7
7
 
8
- def on_comment(comment)
9
- if comment.text.start_with?('=begin')
10
- add_offence(:convention, comment.loc.line, MSG)
8
+ def inspect(source, tokens, ast, comments)
9
+ comments.each do |comment|
10
+ if comment.text.start_with?('=begin')
11
+ add_offence(:convention, comment.loc.line, MSG)
12
+ end
11
13
  end
12
14
  end
13
15
  end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ class BlockNesting < Cop
6
+ NESTING_BLOCKS = [:case, :if, :while, :until, :for, :resbody]
7
+
8
+ def inspect(source, tokens, ast, comments)
9
+ max = BlockNesting.config['Max']
10
+ check_nesting_level(ast, max, 0)
11
+ end
12
+
13
+ private
14
+
15
+ def check_nesting_level(node, max, current_level)
16
+ if NESTING_BLOCKS.include?(node.type)
17
+ current_level += 1
18
+ if current_level == max + 1
19
+ add_offence(:convention, node.location.line, message(max))
20
+ return
21
+ end
22
+ end
23
+ node.children.each do |child|
24
+ if child.is_a?(Parser::AST::Node)
25
+ check_nesting_level(child, max, current_level)
26
+ end
27
+ end
28
+ end
29
+
30
+ def message(max)
31
+ "Avoid more than #{max} levels of block nesting."
32
+ end
33
+ end
34
+ end
35
+ end
@@ -48,10 +48,6 @@ module Rubocop
48
48
 
49
49
  def inspect(source, tokens, ast, comments)
50
50
  process(ast)
51
- comments.each { |c| on_comment(c) }
52
- end
53
-
54
- def on_comment(comment)
55
51
  end
56
52
 
57
53
  def ignore_node(node)
@@ -76,7 +72,7 @@ module Rubocop
76
72
  return if Array(excludes).include?(sexp.type)
77
73
 
78
74
  sexp.children.each do |elem|
79
- if Parser::AST::Node === elem
75
+ if elem.is_a?(Parser::AST::Node)
80
76
  on_node(syms, elem, excludes) { |s| yield s }
81
77
  end
82
78
  end
@@ -5,11 +5,6 @@ module Rubocop
5
5
  module FavorModifier
6
6
  # TODO extremely ugly solution that needs lots of polish
7
7
  def check(sexp)
8
- # discard if/then/else
9
- return false if sexp.loc.respond_to?(:else) && sexp.loc.else
10
- # discard modifier while/until
11
- return false if [:while, :until].include?(sexp.type) && !sexp.loc.end
12
-
13
8
  case sexp.loc.keyword.source
14
9
  when 'if' then cond, body, _else = *sexp
15
10
  when 'unless' then cond, _else, body = *sexp
@@ -19,20 +14,22 @@ module Rubocop
19
14
  if length(sexp) > 3
20
15
  false
21
16
  else
17
+ indentation = sexp.loc.keyword.column
22
18
  cond_length = sexp.loc.keyword.size + cond.loc.expression.size + 1
23
19
  body_length = body_length(body)
24
20
 
25
- body_length > 0 && (cond_length + body_length) <= LineLength.max
21
+ body_length > 0 &&
22
+ (indentation + cond_length + body_length) <= LineLength.max
26
23
  end
27
24
  end
28
25
 
29
26
  def length(sexp)
30
- sexp.loc.expression.source.split("\n").size
27
+ sexp.loc.expression.source.lines.to_a.size
31
28
  end
32
29
 
33
30
  def body_length(body)
34
31
  if body && body.loc.expression
35
- body.loc.expression.column + body.loc.expression.size
32
+ body.loc.expression.size
36
33
  else
37
34
  0
38
35
  end
@@ -48,14 +45,32 @@ module Rubocop
48
45
  end
49
46
 
50
47
  def on_if(node)
51
- # discard ternary ops and modifier if/unless nodes
52
- return unless node.loc.respond_to?(:keyword) &&
53
- node.loc.respond_to?(:else)
48
+ # discard ternary ops, if/else and modifier if/unless nodes
49
+ return if ternary_op?(node)
50
+ return if modifier_if?(node)
51
+ return if elsif?(node)
52
+ return if if_else?(node)
54
53
 
55
54
  add_offence(:convention, node.loc.line, error_message) if check(node)
56
55
 
57
56
  super
58
57
  end
58
+
59
+ def ternary_op?(node)
60
+ node.loc.respond_to?(:question)
61
+ end
62
+
63
+ def modifier_if?(node)
64
+ node.loc.end.nil?
65
+ end
66
+
67
+ def elsif?(node)
68
+ node.loc.keyword.source == 'elsif'
69
+ end
70
+
71
+ def if_else?(node)
72
+ node.loc.respond_to?(:else) && node.loc.else
73
+ end
59
74
  end
60
75
 
61
76
  class WhileUntilModifier < Cop
@@ -66,6 +81,9 @@ module Rubocop
66
81
 
67
82
  def inspect(source, tokens, ast, comments)
68
83
  on_node([:while, :until], ast) do |node|
84
+ # discard modifier while/until
85
+ next unless node.loc.end
86
+
69
87
  add_offence(:convention, node.loc.line, MSG) if check(node)
70
88
  end
71
89
  end
@@ -40,8 +40,18 @@ module Rubocop
40
40
  include IfThenElse
41
41
 
42
42
  def offending_line(node)
43
- if node.loc.expression.source =~ /\bthen\s*(#.*)?\s*$/
44
- node.loc.begin.line
43
+ condition, body = *node
44
+ next_thing = if body && body.loc.expression
45
+ body.loc.expression.begin
46
+ else
47
+ node.loc.end # No body, use "end".
48
+ end
49
+ right_after_cond =
50
+ Parser::Source::Range.new(next_thing.source_buffer,
51
+ condition.loc.expression.end.end_pos,
52
+ next_thing.begin_pos)
53
+ if right_after_cond.source =~ /\A\s*then\s*(#.*)?\s*\n/
54
+ node.loc.expression.begin.line
45
55
  end
46
56
  end
47
57
 
@@ -5,10 +5,12 @@ module Rubocop
5
5
  class LeadingCommentSpace < Cop
6
6
  MSG = 'Missing space after #.'
7
7
 
8
- def on_comment(c)
9
- if c.text =~ /^#+[^#\s]/
10
- unless c.text.start_with?('#!') && c.loc.line == 1
11
- add_offence(:convention, c.loc.line, MSG)
8
+ def inspect(source, tokens, ast, comments)
9
+ comments.each do |comment|
10
+ if comment.text =~ /^#+[^#\s]/
11
+ unless comment.text.start_with?('#!') && comment.loc.line == 1
12
+ add_offence(:convention, comment.loc.line, MSG)
13
+ end
12
14
  end
13
15
  end
14
16
  end
@@ -4,7 +4,7 @@ module Rubocop
4
4
  module Cop
5
5
  class ParenthesesAroundCondition < Cop
6
6
  MSG = "Don't use parentheses around the condition of an " +
7
- 'if/unless/while/until, unless the condition contains an assignment.'
7
+ 'if/unless/while/until'
8
8
 
9
9
  def on_if(node)
10
10
  process_control_op(node)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rubocop
4
4
  module Version
5
- STRING = '0.8.1'
5
+ STRING = '0.8.2'
6
6
  end
7
7
  end
@@ -0,0 +1,148 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Rubocop
6
+ module Cop
7
+ describe BlockNesting do
8
+ let(:block_nesting) { BlockNesting.new }
9
+ before { BlockNesting.config = { 'Max' => 2 } }
10
+
11
+ it 'accepts `Max` levels of nesting' do
12
+ source = ['if a',
13
+ ' if b',
14
+ ' puts b',
15
+ ' end',
16
+ 'end']
17
+ expect_nesting_offences(source, [])
18
+ end
19
+
20
+ it 'registers an offence for `Max + 1` levels of `if` nesting' do
21
+ source = ['if a',
22
+ ' if b',
23
+ ' if c',
24
+ ' puts c',
25
+ ' end',
26
+ ' end',
27
+ 'end']
28
+ expect_nesting_offences(source, [3])
29
+ end
30
+
31
+ it 'registers a single offence for `Max + 2` levels of `if` nesting' do
32
+ source = ['if a',
33
+ ' if b',
34
+ ' if c',
35
+ ' if d',
36
+ ' puts d',
37
+ ' end',
38
+ ' end',
39
+ ' end',
40
+ 'end']
41
+ expect_nesting_offences(source, [3])
42
+ end
43
+
44
+ it 'registers 2 offences' do
45
+ source = ['if a',
46
+ ' if b',
47
+ ' if c',
48
+ ' puts c',
49
+ ' end',
50
+ ' end',
51
+ ' if d',
52
+ ' if e',
53
+ ' puts e',
54
+ ' end',
55
+ ' end',
56
+ 'end']
57
+ expect_nesting_offences(source, [3, 8])
58
+ end
59
+
60
+ it 'registers an offence for nested `case`' do
61
+ source = ['if a',
62
+ ' if b',
63
+ ' case c',
64
+ ' when C',
65
+ ' puts C',
66
+ ' end',
67
+ ' end',
68
+ 'end']
69
+ expect_nesting_offences(source, [3])
70
+ end
71
+
72
+ it 'registers an offence for nested `while`' do
73
+ source = ['if a',
74
+ ' if b',
75
+ ' while c',
76
+ ' puts c',
77
+ ' end',
78
+ ' end',
79
+ 'end']
80
+ expect_nesting_offences(source, [3])
81
+ end
82
+
83
+ it 'registers an offence for nested modifier `while`' do
84
+ source = ['if a',
85
+ ' if b',
86
+ ' begin',
87
+ ' puts c',
88
+ ' end while c',
89
+ ' end',
90
+ 'end']
91
+ expect_nesting_offences(source, [3])
92
+ end
93
+
94
+ it 'registers an offence for nested `until`' do
95
+ source = ['if a',
96
+ ' if b',
97
+ ' until c',
98
+ ' puts c',
99
+ ' end',
100
+ ' end',
101
+ 'end']
102
+ expect_nesting_offences(source, [3])
103
+ end
104
+
105
+ it 'registers an offence for nested modifier `until`' do
106
+ source = ['if a',
107
+ ' if b',
108
+ ' begin',
109
+ ' puts c',
110
+ ' end until c',
111
+ ' end',
112
+ 'end']
113
+ expect_nesting_offences(source, [3])
114
+ end
115
+
116
+ it 'registers an offence for nested `for`' do
117
+ source = ['if a',
118
+ ' if b',
119
+ ' for c in [1,2] do',
120
+ ' puts c',
121
+ ' end',
122
+ ' end',
123
+ 'end']
124
+ expect_nesting_offences(source, [3])
125
+ end
126
+
127
+ it 'registers an offence for nested `rescue`' do
128
+ source = ['if a',
129
+ ' if b',
130
+ ' begin',
131
+ ' puts c',
132
+ ' rescue',
133
+ ' puts x',
134
+ ' end',
135
+ ' end',
136
+ 'end']
137
+ expect_nesting_offences(source, [5])
138
+ end
139
+
140
+ def expect_nesting_offences(source, lines)
141
+ inspect_source(block_nesting, source)
142
+ expect(block_nesting.offences.map(&:line_number)).to eq(lines)
143
+ expect(block_nesting.messages).to eq(
144
+ ['Avoid more than 2 levels of block nesting.'] * lines.length)
145
+ end
146
+ end
147
+ end
148
+ end
@@ -9,8 +9,7 @@ module Rubocop
9
9
  let(:while_until) { WhileUntilModifier.new }
10
10
  before { LineLength.config = { 'Max' => 79 } }
11
11
 
12
- it 'registers an offence for multiline if that fits on one line',
13
- broken: true do
12
+ it 'registers an offence for multiline if that fits on one line' do
14
13
  # This if statement fits exactly on one line if written as a modifier.
15
14
  inspect_source(if_unless,
16
15
  ['if a_condition_that_is_just_short_enough',
@@ -92,6 +91,15 @@ module Rubocop
92
91
  check_empty(while_until, 'until')
93
92
  end
94
93
 
94
+ it 'accepts if/elsif' do
95
+ inspect_source(if_unless, ['if test',
96
+ ' something',
97
+ 'elsif test2',
98
+ ' something_else',
99
+ 'end'])
100
+ expect(if_unless.offences).to be_empty
101
+ end
102
+
95
103
  it 'accepts modifier while' do
96
104
  inspect_source(while_until, ['ala while bala'])
97
105
  expect(while_until.offences).to be_empty
@@ -16,15 +16,18 @@ module Rubocop
16
16
  'end',
17
17
  'if cond then ',
18
18
  'end',
19
+ 'if cond',
20
+ 'then',
21
+ 'end',
19
22
  'if cond then # bad',
20
23
  'end'])
21
- expect(mit.offences.map(&:line_number)).to eq([1, 3, 5, 7])
24
+ expect(mit.offences.map(&:line_number)).to eq([1, 3, 5, 7, 10])
22
25
  end
23
26
 
24
27
  it 'accepts multiline if without then' do
25
28
  inspect_source(mit, ['if cond',
26
29
  'end'])
27
- expect(mit.offences.map(&:message)).to be_empty
30
+ expect(mit.offences).to be_empty
28
31
  end
29
32
 
30
33
  it 'accepts table style if/then/elsif/ends' do
@@ -34,7 +37,27 @@ module Rubocop
34
37
  'elsif @io == $stderr then str << "$stderr"',
35
38
  'else str << @io.class.to_s',
36
39
  'end'])
37
- expect(mit.offences.map(&:message)).to be_empty
40
+ expect(mit.offences).to be_empty
41
+ end
42
+
43
+ it 'does not get confused by a then in a when' do
44
+ inspect_source(mit,
45
+ ['if a',
46
+ ' case b',
47
+ ' when c then',
48
+ ' end',
49
+ 'end'])
50
+ expect(mit.offences).to be_empty
51
+ end
52
+
53
+ it 'does not get confused by a commented-out then' do
54
+ inspect_source(mit,
55
+ ['if a # then',
56
+ ' b',
57
+ 'end',
58
+ 'if c # then',
59
+ 'end'])
60
+ expect(mit.offences).to be_empty
38
61
  end
39
62
 
40
63
  # unless
@@ -49,7 +72,7 @@ module Rubocop
49
72
  it 'accepts multiline unless without then' do
50
73
  inspect_source(mit, ['unless cond',
51
74
  'end'])
52
- expect(mit.offences.map(&:message)).to be_empty
75
+ expect(mit.offences).to be_empty
53
76
  end
54
77
  end
55
78
  end
@@ -8,22 +8,17 @@ module Rubocop
8
8
  let(:a) { Not.new }
9
9
 
10
10
  it 'registers an offence for not' do
11
- inspect_source(a,
12
- ['not test'])
11
+ inspect_source(a, ['not test'])
13
12
  expect(a.offences.size).to eq(1)
14
- expect(a.offences.map(&:message))
15
- .to eq([Not::MSG])
16
13
  end
17
14
 
18
15
  it 'does not register an offence for !' do
19
- inspect_source(a,
20
- ['!test'])
16
+ inspect_source(a, ['!test'])
21
17
  expect(a.offences).to be_empty
22
18
  end
23
19
 
24
20
  it 'does not register an offence for :not' do
25
- inspect_source(a,
26
- ['[:not, :if, :else]'])
21
+ inspect_source(a, ['[:not, :if, :else]'])
27
22
  expect(a.offences).to be_empty
28
23
  end
29
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -155,6 +155,7 @@ files:
155
155
  - lib/rubocop/cop/avoid_perl_backrefs.rb
156
156
  - lib/rubocop/cop/avoid_perlisms.rb
157
157
  - lib/rubocop/cop/block_comments.rb
158
+ - lib/rubocop/cop/block_nesting.rb
158
159
  - lib/rubocop/cop/blocks.rb
159
160
  - lib/rubocop/cop/case_indentation.rb
160
161
  - lib/rubocop/cop/class_and_module_camel_case.rb
@@ -236,6 +237,7 @@ files:
236
237
  - spec/rubocop/cops/avoid_perl_backrefs_spec.rb
237
238
  - spec/rubocop/cops/avoid_perlisms_spec.rb
238
239
  - spec/rubocop/cops/block_comments_spec.rb
240
+ - spec/rubocop/cops/block_nesting_spec.rb
239
241
  - spec/rubocop/cops/blocks_spec.rb
240
242
  - spec/rubocop/cops/case_indentation_spec.rb
241
243
  - spec/rubocop/cops/class_and_module_camel_case_spec.rb
@@ -352,6 +354,7 @@ test_files:
352
354
  - spec/rubocop/cops/avoid_perl_backrefs_spec.rb
353
355
  - spec/rubocop/cops/avoid_perlisms_spec.rb
354
356
  - spec/rubocop/cops/block_comments_spec.rb
357
+ - spec/rubocop/cops/block_nesting_spec.rb
355
358
  - spec/rubocop/cops/blocks_spec.rb
356
359
  - spec/rubocop/cops/case_indentation_spec.rb
357
360
  - spec/rubocop/cops/class_and_module_camel_case_spec.rb