rubocop 0.9.0 → 0.9.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.

Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +1 -0
  4. data/config/default.yml +12 -0
  5. data/config/enabled.yml +0 -1
  6. data/lib/rubocop.rb +3 -0
  7. data/lib/rubocop/cli.rb +7 -1
  8. data/lib/rubocop/cop/cop.rb +20 -5
  9. data/lib/rubocop/cop/lint/end_alignment.rb +51 -42
  10. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  11. data/lib/rubocop/cop/lint/literal_in_condition.rb +59 -9
  12. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -0
  13. data/lib/rubocop/cop/rails/validation.rb +0 -4
  14. data/lib/rubocop/cop/style/collection_methods.rb +28 -10
  15. data/lib/rubocop/cop/style/dot_position.rb +14 -4
  16. data/lib/rubocop/cop/style/if_then_else.rb +0 -51
  17. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -0
  18. data/lib/rubocop/cop/style/multiline_if_then.rb +47 -0
  19. data/lib/rubocop/cop/style/one_line_conditional.rb +20 -0
  20. data/lib/rubocop/cop/style/op_method.rb +16 -14
  21. data/lib/rubocop/cop/util.rb +4 -0
  22. data/lib/rubocop/cop/variable_inspector.rb +32 -13
  23. data/lib/rubocop/version.rb +1 -1
  24. data/rubocop.gemspec +1 -1
  25. data/spec/rubocop/cli_spec.rb +21 -0
  26. data/spec/rubocop/cops/lint/end_alignment_spec.rb +206 -299
  27. data/spec/rubocop/cops/lint/ensure_return_spec.rb +11 -0
  28. data/spec/rubocop/cops/lint/literal_in_condition_spec.rb +37 -3
  29. data/spec/rubocop/cops/lint/shadowing_outer_local_variable_spec.rb +63 -0
  30. data/spec/rubocop/cops/lint/unused_local_variable_spec.rb +68 -0
  31. data/spec/rubocop/cops/offence_spec.rb +2 -2
  32. data/spec/rubocop/cops/style/collection_methods_spec.rb +32 -28
  33. data/spec/rubocop/cops/style/dot_position_spec.rb +46 -11
  34. data/spec/rubocop/cops/style/multiline_if_then_spec.rb +16 -0
  35. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35c6cb48366134b80f6d3f42fc1486a99ed49a7f
4
- data.tar.gz: d4375b85c570dee03df158ca32485af07784cf3e
3
+ metadata.gz: 2ad204405cb1d04fa810d54f45d8b01725f3fb1c
4
+ data.tar.gz: 1240e7d221d6ae7e05ec4dc59bcc633afa96c3cc
5
5
  SHA512:
6
- metadata.gz: f48afa6ead4a29e196af51a92e1c5d248fe02272782edbe0b3d18e866a5707d1b0d1bd258c137ca751ab9fdc08dff713e9cb2c830679a8b987d8294cee561ffc
7
- data.tar.gz: 5fb1c77cb3960f39e1b7edbd5b6babfe8227b6801feff13f3ab04a0768693916275f30c77a083d934b69f02733fe87da15c720b55fd11b4d22632b8bb9e1b4a1
6
+ metadata.gz: 1c8a7da40e56a46adb7a668379062a17fcf978a6df0d7c975b911e0aa1ff700ae38365aab8b1a0dbad0a70c2f2c05b461f5c49ca3c36ebc8825d04d654c90eb0
7
+ data.tar.gz: a180b2850a1946a6fb9b693be6ebe04ae3930fad2b1d341bbb2791347a2c32872a21ca518c277331fc3136c0e483070ea70717f46fd5f54fb426cda27b6dd373
data/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  ## master (unreleased)
4
4
 
5
+ ## 0.9.1 (05/07/2013)
6
+
7
+ ### New features
8
+
9
+ * Added `-l/--lint` option to allow doing only linting with no style checks (similar to running `ruby -wc`).
10
+
11
+ ### Changes
12
+
13
+ * Removed the `BlockAlignSchema` configuration option from `EndAlignment`. We now support only the default alignment schema - `StartOfAssignment`.
14
+ * Made the preferred collection methods in `CollectionMethods` configurable.
15
+ * Made the `DotPosition` cop configurable - now both `leading` and `trailing` styles are supported.
16
+
17
+ ### Bugs fixed
18
+
19
+ * [#318](https://github.com/bbatsov/rubocop/issues/318) - correct some special cases of block end alignment
20
+ * [#317](https://github.com/bbatsov/rubocop/issues/317) - fix a false positive in `LiteralInCondition`
21
+ * [#321](https://github.com/bbatsov/rubocop/issues/321) - Ignore variables whose name start with `_` in `ShadowingOuterLocalVariable`
22
+ * [#322](https://github.com/bbatsov/rubocop/issues/322) - Fix exception of `UnusedLocalVariable` and `ShadowingOuterLocalVariable` when inspecting keyword splat argument
23
+ * [#316](https://github.com/bbatsov/rubocop/issues/316) - Correct nested postfix unless in `MultilineIfThen`
24
+ * [#327](https://github.com/bbatsov/rubocop/issues/327) - Fix false offences for block expression that span on two lines in `EndAlignment`
25
+ * [#332](https://github.com/bbatsov/rubocop/issues/332) - Fix exception of `UnusedLocalVariable` and `ShadowingOuterLocalVariable` when inspecting named captures
26
+ * [#333](https://github.com/bbatsov/rubocop/issues/333) - Fix a case that `EnsureReturn` throws an exception when ensure has no body
27
+
5
28
  ## 0.9.0 (01/07/2013)
6
29
 
7
30
  ### New features
data/README.md CHANGED
@@ -49,6 +49,7 @@ Command flag | Description
49
49
  `-o/--out` | Write output to a file instead of STDOUT
50
50
  `-r/--require` | Require Ruby file
51
51
  `-R/--rails` | Run extra Rails cops
52
+ `-l/--lint` | Run only lint cops
52
53
  `-a/--auto-correct` | Auto-correct certain offences.
53
54
  `-s/--silent` | Suppress the final summary
54
55
  `--only` | Run only the specified cop
data/config/default.yml CHANGED
@@ -56,3 +56,15 @@ BlockNesting:
56
56
  # character.
57
57
  RegexpLiteral:
58
58
  MaxSlashes: 1
59
+
60
+ # Align with the style guide.
61
+ CollectionMethods:
62
+ PreferredMethods:
63
+ collect: 'map'
64
+ inject: 'reduce'
65
+ detect: 'find'
66
+ find_all: 'select'
67
+
68
+ # Muli-line method chaining should be done with leading dots.
69
+ DotPosition:
70
+ Style: 'leading'
data/config/enabled.yml CHANGED
@@ -362,7 +362,6 @@ AssignmentInCondition:
362
362
  # Align ends correctly.
363
363
  EndAlignment:
364
364
  Enabled: true
365
- BlockAlignSchema: StartOfAssignment
366
365
 
367
366
  # Possible use of operator/literal/variable in void context.
368
367
  Void:
data/lib/rubocop.rb CHANGED
@@ -63,6 +63,9 @@ require 'rubocop/cop/style/favor_sprintf'
63
63
  require 'rubocop/cop/style/favor_unless_over_negated_if'
64
64
  require 'rubocop/cop/style/hash_syntax'
65
65
  require 'rubocop/cop/style/if_then_else'
66
+ require 'rubocop/cop/style/if_with_semicolon'
67
+ require 'rubocop/cop/style/multiline_if_then'
68
+ require 'rubocop/cop/style/one_line_conditional'
66
69
  require 'rubocop/cop/style/lambda'
67
70
  require 'rubocop/cop/style/leading_comment_space'
68
71
  require 'rubocop/cop/style/line_continuation'
data/lib/rubocop/cli.rb CHANGED
@@ -37,7 +37,10 @@ module Rubocop
37
37
  end
38
38
 
39
39
  # filter out Rails cops unless requested
40
- @cops.reject! { |cop_klass| cop_klass.rails? } unless @options[:rails]
40
+ @cops.reject!(&:rails?) unless @options[:rails]
41
+
42
+ # filter out style cops when --lint is passed
43
+ @cops.select!(&:lint?) if @options[:lint]
41
44
 
42
45
  target_files = target_files(args)
43
46
  target_files.each(&:freeze).freeze
@@ -181,6 +184,9 @@ module Rubocop
181
184
  opts.on('-R', '--rails', 'Run extra Rails cops.') do |r|
182
185
  @options[:rails] = r
183
186
  end
187
+ opts.on('-l', '--lint', 'Run only lint cops.') do |l|
188
+ @options[:lint] = l
189
+ end
184
190
  opts.on('-a', '--auto-correct', 'Auto-correct offences.') do |a|
185
191
  @options[:autocorrect] = a
186
192
  end
@@ -32,20 +32,35 @@ module Rubocop
32
32
  @config = {}
33
33
 
34
34
  class << self
35
- attr_accessor :all
36
35
  attr_accessor :config
37
36
  end
38
37
 
38
+ def self.all
39
+ @all.clone
40
+ end
41
+
39
42
  def self.inherited(subclass)
40
- all << subclass
43
+ @all << subclass
41
44
  end
42
45
 
43
46
  def self.cop_name
44
47
  name.to_s.split('::').last
45
48
  end
46
49
 
50
+ def self.cop_type
51
+ name.to_s.split('::')[-2].downcase.to_sym
52
+ end
53
+
54
+ def self.style?
55
+ cop_type == :style
56
+ end
57
+
58
+ def self.lint?
59
+ cop_type == :lint
60
+ end
61
+
47
62
  def self.rails?
48
- false
63
+ cop_type == :rails
49
64
  end
50
65
 
51
66
  def initialize
@@ -116,8 +131,8 @@ module Rubocop
116
131
  column_count)
117
132
  newline_length = 1
118
133
  begin_pos = preceding_lines.reduce(0) do |a, e|
119
- a + e.length + newline_length
120
- end + begin_column
134
+ a + e.length + newline_length
135
+ end + begin_column
121
136
  Parser::Source::Range.new(source_buffer, begin_pos,
122
137
  begin_pos + column_count)
123
138
  end
@@ -5,23 +5,19 @@ module Rubocop
5
5
  module Lint
6
6
  # This cop checks whether the end keywords are aligned properly.
7
7
  #
8
- # There are two ways to align the end of a block.
9
- # Set BlockAlignSchema to StartOfAssignment if you want to
10
- # align the end to the beginning of assignment expression.
11
- # This is the default behavior.
8
+ # For keywords (if, def, etc.) the end is aligned with the start
9
+ # of the keyword.
10
+ # For blocks - with the start of the expression where the block
11
+ # is defined.
12
+ #
12
13
  # @example
13
14
  #
15
+ # variable = if true
16
+ # end
17
+ #
14
18
  # variable = lambda do |i|
15
19
  # i
16
20
  # end
17
- #
18
- # Set BlockAlignSchema to StartOfBlockCommand if you want to
19
- # align the end to the beginning of the expression that called the block.
20
- # @example
21
- #
22
- # variable = lambda do |i|
23
- # i
24
- # end
25
21
  class EndAlignment < Cop
26
22
  MSG = 'end at %d, %d is not aligned with %s at %d, %d'
27
23
 
@@ -78,14 +74,25 @@ module Rubocop
78
74
  super
79
75
  end
80
76
 
81
- def on_lvasgn(node)
82
- if align_with_start_of_assignment?
83
- _, children = *node
84
- process_block_assignment(node, children)
77
+ def on_and(node)
78
+ return if already_processed_node?(node)
79
+
80
+ _left, right = *node
81
+ if right.type == :block
82
+ check_block_alignment(node.loc.expression, right.loc)
83
+ @inspected_blocks << right
85
84
  end
86
85
  super
87
86
  end
88
87
 
88
+ alias_method :on_or, :on_and
89
+
90
+ def on_lvasgn(node)
91
+ _, children = *node
92
+ process_block_assignment(node, children)
93
+ super
94
+ end
95
+
89
96
  alias_method :on_ivasgn, :on_lvasgn
90
97
  alias_method :on_cvasgn, :on_lvasgn
91
98
  alias_method :on_gvasgn, :on_lvasgn
@@ -93,43 +100,50 @@ module Rubocop
93
100
  alias_method :on_or_asgn, :on_lvasgn
94
101
 
95
102
  def on_casgn(node)
96
- if align_with_start_of_assignment?
97
- _, _, children = *node
98
- process_block_assignment(node, children)
99
- end
103
+ _, _, children = *node
104
+ process_block_assignment(node, children)
100
105
  super
101
106
  end
102
107
 
103
108
  def on_op_asgn(node)
104
- if align_with_start_of_assignment?
105
- variable, _op, args = *node
106
- process_block_assignment(variable, args)
107
- end
109
+ variable, _op, args = *node
110
+ process_block_assignment(variable, args)
108
111
  super
109
112
  end
110
113
 
111
114
  def on_send(node)
112
- if align_with_start_of_assignment?
113
- receiver, method, args = *node
114
- if attribute_writer?(method)
115
- process_block_assignment(receiver, args)
116
- end
117
- end
115
+ _receiver, _method, *args = *node
116
+ process_block_assignment(node, args.last)
118
117
  super
119
118
  end
120
119
 
121
120
  def on_masgn(node)
122
- if align_with_start_of_assignment?
123
- variables, args = *node
124
- process_block_assignment(variables, args)
125
- end
121
+ variables, args = *node
122
+ process_block_assignment(variables, args)
126
123
  super
127
124
  end
128
125
 
129
126
  private
130
127
 
131
128
  def process_block_assignment(begin_node, block_node)
132
- if block_node && block_node.type == :block
129
+ return unless block_node
130
+ return if already_processed_node?(block_node)
131
+
132
+ while block_node.type == :send
133
+ receiver, _method, args = *block_node
134
+ if receiver && [:block, :send].include?(receiver.type)
135
+ block_node = receiver
136
+ elsif args && [:block, :send].include?(args.type)
137
+ block_node = args
138
+ else
139
+ break
140
+ end
141
+ end
142
+ if block_node.type == :block
143
+ # Align with the expression that is on the same line
144
+ # where the block is defined
145
+ return if block_is_on_next_line?(begin_node, block_node)
146
+
133
147
  @inspected_blocks << block_node
134
148
  check_block_alignment(begin_node.loc.expression, block_node.loc)
135
149
  end
@@ -137,7 +151,6 @@ module Rubocop
137
151
 
138
152
  def check_block_alignment(start_loc, block_loc)
139
153
  end_loc = block_loc.end
140
-
141
154
  if block_loc.begin.line != end_loc.line &&
142
155
  start_loc.column != end_loc.column
143
156
  add_offence(:warning,
@@ -167,12 +180,8 @@ module Rubocop
167
180
  @inspected_blocks.include?(node)
168
181
  end
169
182
 
170
- def attribute_writer?(method)
171
- method.to_s[-1] == '='
172
- end
173
-
174
- def align_with_start_of_assignment?
175
- EndAlignment.config['BlockAlignSchema'] == 'StartOfAssignment'
183
+ def block_is_on_next_line?(begin_node, block_node)
184
+ begin_node.loc.line != block_node.loc.line
176
185
  end
177
186
  end
178
187
  end
@@ -12,7 +12,7 @@ module Rubocop
12
12
 
13
13
  on_node(:return, ensure_body) do |e|
14
14
  add_offence(:warning, e.loc.expression, MSG)
15
- end
15
+ end if ensure_body
16
16
 
17
17
  super
18
18
  end
@@ -3,8 +3,20 @@
3
3
  module Rubocop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for literals used as operands in and/or
7
- # expressions in the conditions of if/while/until.
6
+ # This cop checks for literals used as the conditions or as
7
+ # operands in and/or expressions serving as the conditions of
8
+ # if/while/until.
9
+ #
10
+ # @example
11
+ #
12
+ # if 20
13
+ # do_something
14
+ # end
15
+ #
16
+ # if some_var && true
17
+ # do_something
18
+ # end
19
+ #
8
20
  class LiteralInCondition < Cop
9
21
  MSG = 'Literal %s appeared in a condition.'
10
22
 
@@ -46,15 +58,53 @@ module Rubocop
46
58
  def check_for_literal(node)
47
59
  cond, = *node
48
60
 
49
- on_node([:and, :or], cond) do |logic_node|
50
- *operands = *logic_node
51
- operands.each do |op|
52
- if LITERALS.include?(op.type)
53
- add_offence(:warning, op.loc.expression,
54
- format(MSG, op.loc.expression.source))
61
+ # if the cond node is literal we obviously have a problem
62
+ if literal?(cond)
63
+ add_offence(:warning, cond.loc.expression,
64
+ format(MSG, cond.loc.expression.source))
65
+ else
66
+ # alternatively we have to consider a logical node with a
67
+ # literal argument
68
+ check_node(cond)
69
+ end
70
+ end
71
+
72
+ def not?(node)
73
+ return false unless node && node.type == :send
55
74
 
56
- end
75
+ _receiver, method_name, *_args = *node
76
+
77
+ method_name == :!
78
+ end
79
+
80
+ def literal?(node)
81
+ LITERALS.include?(node.type)
82
+ end
83
+
84
+ def check_node(node)
85
+ return unless node
86
+
87
+ if not?(node)
88
+ receiver, = *node
89
+
90
+ handle_node(receiver)
91
+ elsif [:and, :or].include?(node.type)
92
+ *operands = *node
93
+ operands.each do |op|
94
+ handle_node(op)
57
95
  end
96
+ elsif node.type == :begin && node.children.size == 1
97
+ child_node = node.children.first
98
+ handle_node(child_node)
99
+ end
100
+ end
101
+
102
+ def handle_node(node)
103
+ if literal?(node)
104
+ add_offence(:warning, node.loc.expression,
105
+ format(MSG, node.loc.expression.source))
106
+ elsif [:send, :and, :or, :begin].include?(node.type)
107
+ check_node(node)
58
108
  end
59
109
  end
60
110
  end
@@ -20,6 +20,7 @@ module Rubocop
20
20
  # Only block scope can reference outer local variables.
21
21
  return unless variable_table.current_scope.node.type == :block
22
22
  return unless ARGUMENT_DECLARATION_TYPES.include?(entry.node.type)
23
+ return if entry.name.to_s.start_with?('_')
23
24
 
24
25
  outer_local_variable = variable_table.find_variable_entry(entry.name)
25
26
  return unless outer_local_variable
@@ -17,10 +17,6 @@ module Rubocop
17
17
  :validates_presence_of,
18
18
  :validates_size_of]
19
19
 
20
- def self.rails?
21
- true
22
- end
23
-
24
20
  def on_send(node)
25
21
  receiver, method_name, *_args = *node
26
22
 
@@ -12,22 +12,40 @@ module Rubocop
12
12
  class CollectionMethods < Cop
13
13
  MSG = 'Prefer %s over %s.'
14
14
 
15
- PREFERRED_METHODS = {
16
- collect: 'map',
17
- inject: 'reduce',
18
- detect: 'find',
19
- find_all: 'select'
20
- }
15
+ def self.preferred_methods
16
+ Util.symbolize_keys(config['PreferredMethods'])
17
+ end
18
+
19
+ def on_block(node)
20
+ method, _args, _body = *node
21
+
22
+ check_method_node(method)
23
+
24
+ super
25
+ end
21
26
 
22
27
  def on_send(node)
23
- receiver, method_name, *_args = *node
28
+ _receiver, _method_name, *args = *node
29
+
30
+ if args.size == 1 && args.first.type == :block_pass
31
+ check_method_node(node)
32
+ end
33
+
34
+ super
35
+ end
36
+
37
+ private
38
+
39
+ def check_method_node(node)
40
+ _receiver, method_name, *_args = *node
24
41
 
25
- # a simple(but flawed way) to reduce false positives
26
- if receiver && PREFERRED_METHODS[method_name]
42
+ if self.class.preferred_methods[method_name]
27
43
  add_offence(
28
44
  :convention,
29
45
  node.loc.selector,
30
- sprintf(MSG, PREFERRED_METHODS[method_name], method_name)
46
+ sprintf(MSG,
47
+ self.class.preferred_methods[method_name],
48
+ method_name)
31
49
  )
32
50
  end
33
51
  end