rubocop 0.3.0 → 0.3.1

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.

data/.rubocop.yml CHANGED
@@ -6,6 +6,7 @@ Encoding:
6
6
 
7
7
  LineLength:
8
8
  Enabled: true
9
+ Max: 79
9
10
 
10
11
  Tab:
11
12
  Enabled: true
@@ -87,3 +88,15 @@ NestedTernaryOperator:
87
88
 
88
89
  UnlessElse:
89
90
  Enabled: true
91
+
92
+ AmpersandsPipesVsAndOr:
93
+ Enabled: true
94
+
95
+ WhenThen:
96
+ Enabled: true
97
+
98
+ IfUnlessModifier:
99
+ Enabled: true
100
+
101
+ WhileUntilModifier:
102
+ Enabled: true
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.1
data/lib/rubocop.rb CHANGED
@@ -25,6 +25,7 @@ require 'rubocop/cop/ternary_operator'
25
25
  require 'rubocop/cop/unless_else'
26
26
  require 'rubocop/cop/ampersands_pipes_vs_and_or'
27
27
  require 'rubocop/cop/when_then'
28
+ require 'rubocop/cop/favor_modifier'
28
29
 
29
30
  require 'rubocop/report/report'
30
31
  require 'rubocop/report/plain_text'
data/lib/rubocop/cli.rb CHANGED
@@ -44,11 +44,12 @@ module Rubocop
44
44
  end
45
45
 
46
46
  tokens, sexp, correlations = CLI.rip_source(source)
47
+ config = $options[:config] || config_from_dotfile(File.dirname(file))
47
48
 
48
49
  cops.each do |cop_klass|
49
- config = $options[:config] || config_from_dotfile(File.dirname(file))
50
50
  cop_config = config[cop_klass.name.split('::').last] if config
51
51
  if cop_config.nil? || cop_config['Enabled']
52
+ cop_klass.config = cop_config
52
53
  cop = cop_klass.new
53
54
  cop.correlations = correlations
54
55
  cop.inspect(file, source, tokens, sexp)
@@ -7,9 +7,7 @@ module Rubocop
7
7
 
8
8
  def inspect(file, source, tokens, sexp)
9
9
  source.each_with_index do |line, index|
10
- if line =~ /\r$/
11
- add_offence(:convention, index + 1, ERROR_MESSAGE)
12
- end
10
+ add_offence(:convention, index + 1, ERROR_MESSAGE) if line =~ /\r$/
13
11
  end
14
12
  end
15
13
  end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+
3
+ module Rubocop
4
+ module Cop
5
+ module FavorModifier
6
+ def check(kind, tokens, sexp)
7
+ token_positions = tokens.map(&:pos)
8
+ token_texts = tokens.map(&:text)
9
+ each(kind, sexp) do |s|
10
+ # If it contains an else, it can't be written as a modifier.
11
+ next if s[3] && s[3][0] == :else
12
+
13
+ sexp_positions = all_positions(s)
14
+ ix = token_positions.index(sexp_positions.first)
15
+ if_ix = token_texts[0..ix].rindex(kind.to_s) # index of if/unless/...
16
+ ix = token_positions.index(sexp_positions.last)
17
+ end_ix = ix + token_texts[ix..-1].index('end')
18
+
19
+ # If there's a comment anywhere between
20
+ # if/unless/while/until and end, we don't report. It's
21
+ # possible that the comment will be less clear if put above
22
+ # a one liner rather than inside.
23
+ next if tokens[if_ix...end_ix].map(&:type).include?(:on_comment)
24
+
25
+ if token_positions[end_ix].lineno - token_positions[if_ix].lineno > 2
26
+ next # not a single-line body
27
+ end
28
+ # The start ix is the index of the leftmost token on the
29
+ # line of the if/unless, i.e. the index of if/unless itself,
30
+ # or of the indentation space.
31
+ start_ix = if_ix.downto(0).find do |ix|
32
+ ix == 0 || tokens[ix - 1].text =~ /\n/
33
+ end
34
+ # The stop index is the index of the token just before
35
+ # 'end', not counting whitespace tokens.
36
+ stop_ix = (end_ix - 1).downto(0).find do |ix|
37
+ tokens[ix].text !~ /\s/
38
+ end
39
+ if length(tokens, start_ix, stop_ix) <= LineLength.max
40
+ add_offence(:convention, token_positions[if_ix].lineno,
41
+ error_message)
42
+ end
43
+ end
44
+ end
45
+
46
+ def length(tokens, start_ix, stop_ix)
47
+ (start_ix..stop_ix).inject(0) do |acc, ix|
48
+ acc + if ix > start_ix && tokens[ix - 1].text =~ /\n/
49
+ 0
50
+ else
51
+ tokens[ix].text.length
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ class IfUnlessModifier < Cop
58
+ include FavorModifier
59
+
60
+ def error_message
61
+ 'Favor modifier if/unless usage when you have a single-line body. ' +
62
+ 'Another good alternative is the usage of control flow and/or.'
63
+ end
64
+
65
+ def inspect(file, source, tokens, sexp)
66
+ [:if, :unless].each { |kind| check(kind, tokens, sexp) }
67
+ end
68
+ end
69
+
70
+ class WhileUntilModifier < Cop
71
+ include FavorModifier
72
+
73
+ def error_message
74
+ 'Favor modifier while/until usage when you have a single-line body.'
75
+ end
76
+
77
+ def inspect(file, source, tokens, sexp)
78
+ [:while, :until].each { |kind| check(kind, tokens, sexp) }
79
+ end
80
+ end
81
+ end
82
+ end
@@ -4,16 +4,20 @@ module Rubocop
4
4
  module Cop
5
5
  class LineLength < Cop
6
6
  ERROR_MESSAGE = 'Line is too long. [%d/%d]'
7
- MAX_LINE_LENGTH = 79
8
7
 
9
8
  def inspect(file, source, tokens, sexp)
10
9
  source.each_with_index do |line, index|
11
- if line.length > MAX_LINE_LENGTH
12
- message = sprintf(ERROR_MESSAGE, line.length, MAX_LINE_LENGTH)
10
+ max = LineLength.max
11
+ if line.length > max
12
+ message = sprintf(ERROR_MESSAGE, line.length, max)
13
13
  add_offence(:convention, index + 1, message)
14
14
  end
15
15
  end
16
16
  end
17
+
18
+ def self.max
19
+ LineLength.config ? LineLength.config['Max'] || 79 : 79
20
+ end
17
21
  end
18
22
  end
19
23
  end
@@ -7,9 +7,7 @@ module Rubocop
7
7
 
8
8
  def inspect(file, source, tokens, sexp)
9
9
  source.each_with_index do |line, index|
10
- if line =~ /^ *\t/
11
- add_offence(:convention, index + 1, ERROR_MESSAGE)
12
- end
10
+ add_offence(:convention, index + 1, ERROR_MESSAGE) if line =~ /^ *\t/
13
11
  end
14
12
  end
15
13
  end
data/rubocop.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "rubocop"
8
- s.version = "0.3.0"
8
+ s.version = "0.3.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bozhidar Batsov"]
12
- s.date = "2013-02-11"
12
+ s.date = "2013-02-28"
13
13
  s.description = "Automatic Ruby code style checking tool. Aims to enforce the community-driven Ruby Style Guide."
14
14
  s.email = "bozhidar@batsov.com"
15
15
  s.executables = ["rubocop"]
@@ -45,6 +45,7 @@ Gem::Specification.new do |s|
45
45
  "lib/rubocop/cop/empty_lines.rb",
46
46
  "lib/rubocop/cop/encoding.rb",
47
47
  "lib/rubocop/cop/end_of_line.rb",
48
+ "lib/rubocop/cop/favor_modifier.rb",
48
49
  "lib/rubocop/cop/grammar.rb",
49
50
  "lib/rubocop/cop/hash_syntax.rb",
50
51
  "lib/rubocop/cop/if_then_else.rb",
@@ -75,6 +76,7 @@ Gem::Specification.new do |s|
75
76
  "spec/rubocop/cops/empty_lines_spec.rb",
76
77
  "spec/rubocop/cops/encoding_spec.rb",
77
78
  "spec/rubocop/cops/end_of_line_spec.rb",
79
+ "spec/rubocop/cops/favor_modifier_spec.rb",
78
80
  "spec/rubocop/cops/grammar_spec.rb",
79
81
  "spec/rubocop/cops/hash_syntax_spec.rb",
80
82
  "spec/rubocop/cops/if_with_semicolon_spec.rb",
@@ -137,6 +137,28 @@ module Rubocop
137
137
  end
138
138
  end
139
139
 
140
+ it 'can use an alternative max line length from a config file' do
141
+ FileUtils.mkdir 'example_src'
142
+ File.open('example_src/example1.rb', 'w') { |f| f.puts '#' * 90 }
143
+ File.open('example_src/.rubocop.yml', 'w') do |f|
144
+ f.puts('LineLength:',
145
+ ' Enabled: true',
146
+ ' Max: 100')
147
+ end
148
+ begin
149
+ return_code = cli.run(['example_src/example1.rb'])
150
+ $stdout.string.should ==
151
+ ['== example_src/example1.rb ==',
152
+ 'C: 1: Missing encoding comment.',
153
+ '',
154
+ '1 files inspected, 1 offences detected',
155
+ ''].join("\n")
156
+ return_code.should == 1
157
+ ensure
158
+ FileUtils.rm_rf 'example_src'
159
+ end
160
+ end
161
+
140
162
  it 'finds no violations when checking the rubocop source code' do
141
163
  cli.run
142
164
  $stdout.string.should =~ /files inspected, 0 offences detected\n/
@@ -153,6 +175,13 @@ module Rubocop
153
175
  File.delete 'example.rb'
154
176
  end
155
177
  end
178
+
179
+ it 'has configuration for all cops in .rubocop.yml' do
180
+ cop_names = Cop::Cop.all.map do |cop_class|
181
+ cop_class.name.split('::').last
182
+ end
183
+ YAML.load_file('.rubocop.yml').keys.sort.should == cop_names.sort
184
+ end
156
185
  end
157
186
  end
158
187
  end
@@ -0,0 +1,112 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Rubocop
6
+ module Cop
7
+ describe FavorModifier do
8
+ let (:if_until) { IfUnlessModifier.new }
9
+ let (:while_until) { WhileUntilModifier.new }
10
+
11
+ it 'registers an offence for multiline if that fits on one line' do
12
+ # This if statement fits exactly on one line if written as a modifier.
13
+ inspect_source(if_until, 'file.rb',
14
+ ['if a_condition_that_is_just_short_enough',
15
+ ' some_long_metod_name(followed_by_args)',
16
+ 'end'])
17
+ if_until.offences.map(&:message).should ==
18
+ ['Favor modifier if/unless usage when you have a single-line body.' +
19
+ ' Another good alternative is the usage of control flow and/or.']
20
+ end
21
+
22
+ it "accepts multiline if that doesn't fit on one line" do
23
+ check_too_long(if_until, 'if')
24
+ end
25
+
26
+ it 'accepts multiline if whose body is more than one line' do
27
+ check_short_multiline(if_until, 'if')
28
+ end
29
+
30
+ it 'registers an offence for multiline unless that fits on one line' do
31
+ inspect_source(if_until, 'file.rb', ['unless a',
32
+ ' b',
33
+ 'end'])
34
+ if_until.offences.map(&:message).should ==
35
+ ['Favor modifier if/unless usage when you have a single-line body.' +
36
+ ' Another good alternative is the usage of control flow and/or.']
37
+ end
38
+
39
+ it 'accepts code with EOL comment since user might want to keep it' do
40
+ inspect_source(if_until, 'file.rb', ['unless a',
41
+ ' b # A comment',
42
+ 'end'])
43
+ if_until.offences.map(&:message).should == []
44
+ end
45
+
46
+ it 'accepts if-else-end' do
47
+ inspect_source(if_until, 'file.rb',
48
+ ['if args.last.is_a? Hash then args.pop else ' +
49
+ 'Hash.new end'])
50
+ if_until.offences.map(&:message).should == []
51
+ end
52
+
53
+ it "accepts multiline unless that doesn't fit on one line" do
54
+ check_too_long(while_until, 'unless')
55
+ end
56
+
57
+ it 'accepts multiline unless whose body is more than one line' do
58
+ check_short_multiline(while_until, 'unless')
59
+ end
60
+
61
+ it 'registers an offence for multiline while that fits on one line' do
62
+ check_really_short(while_until, 'while')
63
+ end
64
+
65
+ it "accepts multiline while that doesn't fit on one line" do
66
+ check_too_long(while_until, 'while')
67
+ end
68
+
69
+ it 'accepts multiline while whose body is more than one line' do
70
+ check_short_multiline(while_until, 'while')
71
+ end
72
+
73
+ it 'registers an offence for multiline until that fits on one line' do
74
+ check_really_short(while_until, 'until')
75
+ end
76
+
77
+ it "accepts multiline until that doesn't fit on one line" do
78
+ check_too_long(while_until, 'until')
79
+ end
80
+
81
+ it 'accepts multiline until whose body is more than one line' do
82
+ check_short_multiline(while_until, 'until')
83
+ end
84
+
85
+ def check_really_short(cop, keyword)
86
+ inspect_source(cop, 'file.rb', ["#{keyword} a",
87
+ ' b',
88
+ 'end'])
89
+ cop.offences.map(&:message).should ==
90
+ ['Favor modifier while/until usage when you have a single-line ' +
91
+ 'body.']
92
+ end
93
+
94
+ def check_too_long(cop, keyword)
95
+ inspect_source(cop, 'file.rb',
96
+ [" #{keyword} a_lengthy_condition_that_goes_on_and_on",
97
+ ' some_long_metod_name(followed_by_args)',
98
+ ' end'])
99
+ cop.offences.map(&:message).should == []
100
+ end
101
+
102
+ def check_short_multiline(cop, keyword)
103
+ inspect_source(cop, 'file.rb',
104
+ ["#{keyword} ENV['COVERAGE']",
105
+ " require 'simplecov'",
106
+ ' SimpleCov.start',
107
+ 'end'])
108
+ cop.offences.map(&:message).should == []
109
+ end
110
+ end
111
+ end
112
+ 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.3.0
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-11 00:00:00.000000000 Z
12
+ date: 2013-02-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -144,6 +144,7 @@ files:
144
144
  - lib/rubocop/cop/empty_lines.rb
145
145
  - lib/rubocop/cop/encoding.rb
146
146
  - lib/rubocop/cop/end_of_line.rb
147
+ - lib/rubocop/cop/favor_modifier.rb
147
148
  - lib/rubocop/cop/grammar.rb
148
149
  - lib/rubocop/cop/hash_syntax.rb
149
150
  - lib/rubocop/cop/if_then_else.rb
@@ -174,6 +175,7 @@ files:
174
175
  - spec/rubocop/cops/empty_lines_spec.rb
175
176
  - spec/rubocop/cops/encoding_spec.rb
176
177
  - spec/rubocop/cops/end_of_line_spec.rb
178
+ - spec/rubocop/cops/favor_modifier_spec.rb
177
179
  - spec/rubocop/cops/grammar_spec.rb
178
180
  - spec/rubocop/cops/hash_syntax_spec.rb
179
181
  - spec/rubocop/cops/if_with_semicolon_spec.rb
@@ -217,7 +219,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
217
219
  version: '0'
218
220
  segments:
219
221
  - 0
220
- hash: 1293678541270492107
222
+ hash: -1525847250123006446
221
223
  required_rubygems_version: !ruby/object:Gem::Requirement
222
224
  none: false
223
225
  requirements: