rubocop 0.27.0 → 0.27.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/.rubocop_todo.yml +1 -1
  3. data/CHANGELOG.md +17 -0
  4. data/README.md +14 -11
  5. data/config/enabled.yml +5 -5
  6. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  7. data/lib/rubocop/cop/lint/rescue_exception.rb +2 -12
  8. data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -1
  9. data/lib/rubocop/cop/style/else_alignment.rb +15 -12
  10. data/lib/rubocop/cop/style/empty_literal.rb +3 -3
  11. data/lib/rubocop/cop/style/if_with_semicolon.rb +1 -1
  12. data/lib/rubocop/cop/style/multiline_if_then.rb +6 -25
  13. data/lib/rubocop/cop/style/multiline_operation_indentation.rb +5 -1
  14. data/lib/rubocop/cop/style/space_after_method_name.rb +1 -1
  15. data/lib/rubocop/cop/style/space_inside_range_literal.rb +7 -2
  16. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +6 -4
  17. data/lib/rubocop/cop/style/unless_else.rb +1 -1
  18. data/lib/rubocop/cop/style/when_then.rb +1 -1
  19. data/lib/rubocop/cop/style/while_until_do.rb +1 -1
  20. data/lib/rubocop/path_util.rb +13 -1
  21. data/lib/rubocop/runner.rb +1 -1
  22. data/lib/rubocop/target_finder.rb +19 -6
  23. data/lib/rubocop/version.rb +1 -1
  24. data/relnotes/v0.27.1.md +66 -0
  25. data/rubocop.gemspec +1 -1
  26. data/spec/rubocop/cli_spec.rb +63 -18
  27. data/spec/rubocop/cop/lint/rescue_exception_spec.rb +0 -36
  28. data/spec/rubocop/cop/style/else_alignment_spec.rb +12 -0
  29. data/spec/rubocop/cop/style/empty_literal_spec.rb +6 -6
  30. data/spec/rubocop/cop/style/if_with_semicolon_spec.rb +1 -1
  31. data/spec/rubocop/cop/style/multiline_if_then_spec.rb +22 -2
  32. data/spec/rubocop/cop/style/multiline_operation_indentation_spec.rb +9 -0
  33. data/spec/rubocop/cop/style/space_inside_range_literal_spec.rb +12 -0
  34. data/spec/rubocop/cop/style/string_literals_in_interpolation_spec.rb +37 -1
  35. metadata +5 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30651383f11c3dcaac288e77b0055e6523b509fe
4
- data.tar.gz: 245cd91aaf840d894118ed9f0530c1d3019b9c1f
3
+ metadata.gz: 31c46dfc62c89c6d6c760fca39e95d4ddbc6d86a
4
+ data.tar.gz: a341a023513b18cf578c889b4f563e656ce0d762
5
5
  SHA512:
6
- metadata.gz: 56e26bc6f778104eae7226a633e6eca1f5302d263c1ae4d8a208031c08bc688011817dc55272a8962c586cc436639749b504b208f4ac415d87f11aaedda40a49
7
- data.tar.gz: f457149f614495b72eabfc4fece9f96007aa18f6debb384bc4dadb6bd580b45ac3bcf0818d8241cf3a5524f04ca881324c0c7ee4238f03973b41148f74e21f76
6
+ metadata.gz: d924beb2cc52e477d0a9283cb23ffd269e64236c3ed454e29069c7f6eac037ecf512b8a670732c6dbb8335323f3c0aa527e169fc4b2abc24ec444f804689c628
7
+ data.tar.gz: 3494d55e372c564d29f33cfe6fe6af6d6071262ba5bd80298a735d7963f1accd84c769716c688b21489bf47325e804b0e1a8a2c3b4afc34f3263b7107a4da0a3
@@ -7,7 +7,7 @@
7
7
 
8
8
  # Offense count: 116
9
9
  Metrics/AbcSize:
10
- Max: 33
10
+ Max: 38
11
11
 
12
12
  # Offense count: 10
13
13
  # Configuration parameters: CountComments.
@@ -2,6 +2,22 @@
2
2
 
3
3
  ## master (unreleased)
4
4
 
5
+ ## 0.27.1 (08/11/2014)
6
+
7
+ ### Changes
8
+
9
+ * [#1343](https://github.com/bbatsov/rubocop/issues/1343): Remove auto-correct from `RescueException` cop. ([@bbatsov][])
10
+ * [#1425](https://github.com/bbatsov/rubocop/issues/1425): `AllCops/Include` configuration parameters are only taken from the project `.rubocop.yml` and files it inherits from, not from `.rubocop.yml` files in subdirectories. ([@jonas054][])
11
+
12
+ ### Bugs fixed
13
+
14
+ * [#1411](https://github.com/bbatsov/rubocop/issues/1411): Handle lambda calls without a selector in `MultilineOperationIndentation`. ([@bbatsov][])
15
+ * [#1401](https://github.com/bbatsov/rubocop/issues/1401): Files in hidden directories, i.e. ones beginning with dot, can now be selected through configuration, but are still not included by default. ([@jonas054][])
16
+ * [#1415](https://github.com/bbatsov/rubocop/issues/1415): String literals concatenated with backslashes are now handled correctly by `StringLiteralsInInterpolation`. ([@jonas054][])
17
+ * [#1416](https://github.com/bbatsov/rubocop/issues/1416): Fix handling of `begin/rescue/else/end` in `ElseAlignment`. ([@jonas054][])
18
+ * [#1413](https://github.com/bbatsov/rubocop/issues/1413): Support empty elsif branches in `MultilineIfThen`. ([@janraasch][], [@jonas054][])
19
+ * [#1406](https://github.com/bbatsov/rubocop/issues/1406): Allow a newline in `SpaceInsideRangeLiteral`. ([@bbatsov][])
20
+
5
21
  ## 0.27.0 (30/10/2014)
6
22
 
7
23
  ### New features
@@ -1133,3 +1149,4 @@
1133
1149
  [@smangelsdorf]: https://github.com/smangelsdorf
1134
1150
  [@mvz]: https://github.com/mvz
1135
1151
  [@jfelchner]: https://github.com/jfelchner
1152
+ [@janraasch]: https://github.com/janraasch
data/README.md CHANGED
@@ -275,11 +275,14 @@ directory, `config/default.yml` will be used.
275
275
 
276
276
  ### Including/Excluding files
277
277
 
278
- RuboCop checks all files recursively within the directory it is run
279
- on. However, it only recognizes files ending with `.rb` or
280
- extensionless files with a `#!.*ruby` declaration as Ruby files. If
281
- you'd like it to check other files you'll need to manually pass them
282
- in, or to add entries for them under `AllCops`/`Include`. Files and
278
+ RuboCop checks all files found by a recursive search starting from the
279
+ directory it is run in, or directories given as command line
280
+ arguments. However, it only recognizes files ending with `.rb` or
281
+ extensionless files with a `#!.*ruby` declaration as Ruby files.
282
+ Hidden directories (i.e., directories whose names start with a dot)
283
+ are not searched by default. If you'd like it to check files that are
284
+ not included by default, you'll need to pass them in on the command
285
+ line, or to add entries for them under `AllCops`/`Include`. Files and
283
286
  directories can also be ignored through `AllCops`/`Exclude`.
284
287
 
285
288
  Here is an example that might be used for a Rails project:
@@ -310,12 +313,12 @@ correct way to match the file in any directory, including the current, is
310
313
  `config`, but this pattern style is deprecated and should be replaced by
311
314
  `config/**/*`.
312
315
 
313
- **Note**: The `Exclude` parameter is special. It is valid for the
314
- directory tree starting where it is defined. It is not shadowed by the
315
- setting of `Exclude` in other `.rubocop.yml` files in
316
- subdirectories. This is different from all other parameters, who
317
- follow RuboCop's general principle that configuration for an inspected
318
- file is taken from the nearest `.rubocop.yml`, searching upwards.
316
+ **Note**: The `Include` and `Exclude` parameters are special. They are
317
+ valid for the directory tree starting where they are defined. They are not
318
+ shadowed by the setting of `Include` and `Exclude` in other `.rubocop.yml`
319
+ files in subdirectories. This is different from all other parameters, who
320
+ follow RuboCop's general principle that configuration for an inspected file
321
+ is taken from the nearest `.rubocop.yml`, searching upwards.
319
322
 
320
323
  Cops can be run only on specific sets of files when that's needed (for
321
324
  instance you might want to run some Rails model checks only on files whose
@@ -271,7 +271,7 @@ Style/IfUnlessModifier:
271
271
  Enabled: true
272
272
 
273
273
  Style/IfWithSemicolon:
274
- Description: 'Never use if x; .... Use the ternary operator instead.'
274
+ Description: 'Do not use if x; .... Use the ternary operator instead.'
275
275
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-semicolon-ifs'
276
276
  Enabled: true
277
277
 
@@ -352,7 +352,7 @@ Style/MultilineBlockLayout:
352
352
  Enabled: true
353
353
 
354
354
  Style/MultilineIfThen:
355
- Description: 'Never use then for multi-line if/unless.'
355
+ Description: 'Do not use then for multi-line if/unless.'
356
356
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-then'
357
357
  Enabled: true
358
358
 
@@ -544,7 +544,7 @@ Style/SpaceAfterControlKeyword:
544
544
 
545
545
  Style/SpaceAfterMethodName:
546
546
  Description: >-
547
- Never put a space between a method name and the opening
547
+ Do not put a space between a method name and the opening
548
548
  parenthesis in a method definition.
549
549
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parens-no-spaces'
550
550
  Enabled: true
@@ -670,7 +670,7 @@ Style/TrivialAccessors:
670
670
 
671
671
  Style/UnlessElse:
672
672
  Description: >-
673
- Never use unless with else. Rewrite these with the positive
673
+ Do not use unless with else. Rewrite these with the positive
674
674
  case first.
675
675
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-else-with-unless'
676
676
  Enabled: true
@@ -832,7 +832,7 @@ Lint/EndInMethod:
832
832
  Enabled: true
833
833
 
834
834
  Lint/EnsureReturn:
835
- Description: 'Never use return in an ensure block.'
835
+ Description: 'Do not use return in an ensure block.'
836
836
  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-return-ensure'
837
837
  Enabled: true
838
838
 
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for *return* from an *ensure* block.
7
7
  class EnsureReturn < Cop
8
- MSG = 'Never return from an `ensure` block.'
8
+ MSG = 'Do not return from an `ensure` block.'
9
9
 
10
10
  def on_ensure(node)
11
11
  _body, ensure_body = *node
@@ -5,7 +5,8 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for *rescue* blocks targeting the Exception class.
7
7
  class RescueException < Cop
8
- MSG = 'Avoid rescuing the `Exception` class.'
8
+ MSG = 'Avoid rescuing the `Exception` class. ' \
9
+ 'Perhaps you meant to rescue `StandardError`?'
9
10
 
10
11
  def on_resbody(node)
11
12
  return unless node.children.first
@@ -18,17 +19,6 @@ module RuboCop
18
19
  def targets_exception?(rescue_arg_node)
19
20
  Util.const_name(rescue_arg_node) == 'Exception'
20
21
  end
21
-
22
- def autocorrect(node)
23
- @corrections << lambda do |corrector|
24
- corrector.remove(
25
- range_with_surrounding_space(
26
- node.children.first.children.first.loc.expression,
27
- :left
28
- )
29
- )
30
- end
31
- end
32
22
  end
33
23
  end
34
24
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module RuboCop
4
4
  module Cop
5
- # Common functionality for cops checking if and unless statements.
5
+ # Common functionality for cops checking if and unless expressions.
6
6
  module OnNormalIfUnless
7
7
  include IfNode
8
8
 
@@ -37,18 +37,12 @@ module RuboCop
37
37
  def on_rescue(node)
38
38
  return unless node.loc.else
39
39
 
40
- grandparent = node.parent.parent
41
- base = case node.parent.type
42
- when :def, :defs
43
- if grandparent && grandparent.type == :send
44
- grandparent.loc.selector
45
- else
46
- node.parent.loc.keyword
47
- end
48
- when :ensure
49
- grandparent.loc.begin
50
- else
51
- node.loc.keyword
40
+ parent = node.parent
41
+ base = case parent.type
42
+ when :def, :defs then base_for_method_definition(parent)
43
+ when :kwbegin then parent.loc.begin
44
+ when :ensure then parent.parent.loc.begin
45
+ else node.loc.keyword
52
46
  end
53
47
  check_alignment(base, node.loc.else)
54
48
  end
@@ -61,6 +55,15 @@ module RuboCop
61
55
 
62
56
  private
63
57
 
58
+ def base_for_method_definition(node)
59
+ parent = node.parent
60
+ if parent && parent.type == :send
61
+ parent.loc.selector # For example "private def ..."
62
+ else
63
+ node.loc.keyword
64
+ end
65
+ end
66
+
64
67
  def check_assignment(node, rhs)
65
68
  # If there are method calls chained to the right hand side of the
66
69
  # assignment, we let rhs be the receiver of those method calls before
@@ -6,9 +6,9 @@ module RuboCop
6
6
  # This cop checks for the use of a method, the result of which
7
7
  # would be a literal, like an empty array, hash or string.
8
8
  class EmptyLiteral < Cop
9
- ARR_MSG = 'Use array literal [] instead of Array.new.'
10
- HASH_MSG = 'Use hash literal {} instead of Hash.new.'
11
- STR_MSG = "Use string literal '' instead of String.new."
9
+ ARR_MSG = 'Use array literal `[]` instead of `Array.new`.'
10
+ HASH_MSG = 'Use hash literal `{}` instead of `Hash.new`.'
11
+ STR_MSG = "Use string literal `''` instead of `String.new`."
12
12
 
13
13
  # Empty array node
14
14
  #
@@ -7,7 +7,7 @@ module RuboCop
7
7
  class IfWithSemicolon < Cop
8
8
  include OnNormalIfUnless
9
9
 
10
- MSG = 'Never use if x; Use the ternary operator instead.'
10
+ MSG = 'Do not use if x; Use the ternary operator instead.'
11
11
 
12
12
  def on_normal_if_unless(node)
13
13
  beginning = node.loc.begin
@@ -20,38 +20,19 @@ module RuboCop
20
20
  include OnNormalIfUnless
21
21
 
22
22
  def on_normal_if_unless(node)
23
- condition, body, else_clause = *node
24
- next_thing = if body && body.loc.expression
25
- body.loc.expression.begin
26
- elsif else_clause && else_clause.loc.expression
27
- else_clause.loc.expression.begin
28
- else
29
- node.loc.end # No body, use "end".
30
- end
31
- right_after_cond =
32
- Parser::Source::Range.new(next_thing.source_buffer,
33
- end_position(condition),
34
- next_thing.begin_pos)
35
- return unless right_after_cond.source =~ /\A\s*then\s*(#.*)?\s*\n/
36
-
37
- add_offense(node, :expression, message(node))
38
- end
39
-
40
- def end_position(conditional_node)
41
- conditional_node.loc.expression.end.end_pos
23
+ return unless node.loc.begin
24
+ return unless node.loc.begin.source_line =~ /then\s*(#.*)?$/
25
+ add_offense(node, :begin)
42
26
  end
43
27
 
44
28
  def message(node)
45
- "Never use `then` for multi-line `#{node.loc.keyword.source}`."
29
+ "Do not use `then` for multi-line `#{node.loc.keyword.source}`."
46
30
  end
47
31
 
48
32
  def autocorrect(node)
49
33
  @corrections << lambda do |corrector|
50
- condition_node, = *node
51
- end_of_condition_range = condition_node.loc.expression.end
52
- then_range = node.loc.begin
53
- whitespaces_and_then_range = end_of_condition_range.join(then_range)
54
- corrector.remove(whitespaces_and_then_range)
34
+ corrector.remove(range_with_surrounding_space(node.loc.begin,
35
+ :left))
55
36
  end
56
37
  end
57
38
  end
@@ -114,10 +114,14 @@ module RuboCop
114
114
  if operator?(method_name) && args.any?
115
115
  args.first.loc.expression
116
116
  elsif send_node.loc.dot &&
117
+ send_node.loc.selector &&
117
118
  send_node.loc.dot.line == send_node.loc.selector.line
118
119
  send_node.loc.dot.join(send_node.loc.selector)
119
- else
120
+ elsif send_node.loc.selector
120
121
  send_node.loc.selector
122
+ elsif send_node.loc.dot.line == send_node.loc.begin.line
123
+ # lambda.(args)
124
+ send_node.loc.dot.join(send_node.loc.begin)
121
125
  end
122
126
  end
123
127
 
@@ -15,7 +15,7 @@ module RuboCop
15
15
  class SpaceAfterMethodName < Cop
16
16
  include OnMethodDef
17
17
 
18
- MSG = 'Never put a space between a method name and the opening ' \
18
+ MSG = 'Do not put a space between a method name and the opening ' \
19
19
  'parenthesis.'
20
20
 
21
21
  def on_method_def(_node, _method_name, args, _body)
@@ -4,6 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Checks for spaces inside range literals.
7
+ #
7
8
  # @example
8
9
  # # bad
9
10
  # 1 .. 3
@@ -31,9 +32,13 @@ module RuboCop
31
32
 
32
33
  def check(node)
33
34
  expression = node.loc.expression.source
34
- operator = node.loc.operator.source.gsub(/\./, '\.')
35
+ op = node.loc.operator.source
36
+ escaped_op = op.gsub(/\./, '\.')
37
+
38
+ # account for multiline range literals
39
+ expression.sub!(/#{escaped_op}\n\s*/, op)
35
40
 
36
- return unless expression =~ /(\s#{operator})|(#{operator}\s)/
41
+ return unless expression =~ /(\s#{escaped_op})|(#{escaped_op}\s)/
37
42
 
38
43
  add_offense(node, :expression)
39
44
  end
@@ -18,11 +18,13 @@ module RuboCop
18
18
  end
19
19
 
20
20
  def offense?(node)
21
- # If it's not a string within a dynamic string, i.e. part of an
22
- # expression in an interpolation, then it's not an offense for this
23
- # cop.
21
+ # If it's not a string within an interpolation, then it's not an
22
+ # offense for this cop. A :begin node inside a :dstr node is an
23
+ # interpolation.
24
+ begin_found = false
24
25
  return false unless node.each_ancestor.find do |a|
25
- a.type == :dstr && within_node?(node, a)
26
+ begin_found = true if a.type == :begin
27
+ begin_found && a.type == :dstr
26
28
  end
27
29
 
28
30
  wrong_quotes?(node, style)
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Style
6
6
  # This cop looks for *unless* expressions with *else* clauses.
7
7
  class UnlessElse < Cop
8
- MSG = 'Never use `unless` with `else`. Rewrite these with the ' \
8
+ MSG = 'Do not use `unless` with `else`. Rewrite these with the ' \
9
9
  'positive case first.'
10
10
 
11
11
  def on_if(node)
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Style
6
6
  # This cop checks for *when;* uses in *case* expressions.
7
7
  class WhenThen < Cop
8
- MSG = 'Never use `when x;`. Use `when x then` instead.'
8
+ MSG = 'Do not use `when x;`. Use `when x then` instead.'
9
9
 
10
10
  def on_when(node)
11
11
  return unless node.loc.begin && node.loc.begin.is?(';')
@@ -24,7 +24,7 @@ module RuboCop
24
24
  private
25
25
 
26
26
  def error_message(node_type)
27
- format('Never use `do` with multi-line `%s`.', node_type)
27
+ format('Do not use `do` with multi-line `%s`.', node_type)
28
28
  end
29
29
 
30
30
  def autocorrect(node)
@@ -21,7 +21,19 @@ module RuboCop
21
21
  old_match = basename == pattern || File.fnmatch?(pattern, path)
22
22
  new_match = File.fnmatch?(pattern, path, File::FNM_PATHNAME)
23
23
  if old_match && !new_match
24
- issue_deprecation_warning(basename, pattern, config_path)
24
+ # Patterns like dir/**/* will produce an old match for files
25
+ # beginning with dot, but not a new match. That's a special case,
26
+ # though. Not what we want to handle here. And this is a match that
27
+ # we overrule. Only patterns like dir/**/.* can be used to match dot
28
+ # files.
29
+ return false if basename.start_with?('.')
30
+
31
+ # Hidden directories (starting with a dot) will also produce an old
32
+ # match, just like hidden files. A deprecation warning would be wrong
33
+ # for these.
34
+ if path.split(File::SEPARATOR).none? { |s| s.start_with?('.') }
35
+ issue_deprecation_warning(basename, pattern, config_path)
36
+ end
25
37
  end
26
38
  old_match || new_match
27
39
  when Regexp
@@ -109,7 +109,7 @@ module RuboCop
109
109
  # filter out Rails cops unless requested
110
110
  cop_classes.reject!(&:rails?) unless run_rails_cops?(config)
111
111
 
112
- # filter out style cops when --lint is passed
112
+ # select only lint cops when --lint is passed
113
113
  cop_classes.select!(&:lint?) if @options[:lint]
114
114
  end
115
115
 
@@ -1,5 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'set'
4
+
3
5
  module RuboCop
4
6
  # This class finds target files to inspect by scanning the directory tree
5
7
  # and picking ruby files.
@@ -55,14 +57,12 @@ module RuboCop
55
57
  if File::ALT_SEPARATOR
56
58
  base_dir.gsub!(File::ALT_SEPARATOR, File::SEPARATOR)
57
59
  end
58
- files = Dir["#{base_dir}/**/*"].select { |path| FileTest.file?(path) }
60
+ all_files = find_files(base_dir, File::FNM_DOTMATCH)
61
+ hidden_files = Set.new(all_files - find_files(base_dir, 0))
59
62
  base_dir_config = @config_store.for(base_dir)
60
63
 
61
- target_files = files.select do |file|
62
- next false if base_dir_config.file_to_exclude?(file)
63
- next true if File.extname(file) == '.rb'
64
- next true if ruby_executable?(file)
65
- @config_store.for(file).file_to_include?(file)
64
+ target_files = all_files.select do |file|
65
+ to_inspect?(file, hidden_files, base_dir_config)
66
66
  end
67
67
 
68
68
  # Most recently modified file first.
@@ -71,6 +71,19 @@ module RuboCop
71
71
  target_files
72
72
  end
73
73
 
74
+ def to_inspect?(file, hidden_files, base_dir_config)
75
+ return false if base_dir_config.file_to_exclude?(file)
76
+ unless hidden_files.include?(file)
77
+ return true if File.extname(file) == '.rb'
78
+ return true if ruby_executable?(file)
79
+ end
80
+ base_dir_config.file_to_include?(file)
81
+ end
82
+
83
+ def find_files(base_dir, flags)
84
+ Dir.glob("#{base_dir}/**/*", flags).select { |path| FileTest.file?(path) }
85
+ end
86
+
74
87
  def ruby_executable?(file)
75
88
  return false unless File.extname(file).empty?
76
89
  first_line = File.open(file) { |f| f.readline }
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '0.27.0'
6
+ STRING = '0.27.1'
7
7
 
8
8
  MSG = '%s (using Parser %s, running on %s %s %s)'
9
9
 
@@ -0,0 +1,66 @@
1
+ ### Changes
2
+
3
+ * [#1343](https://github.com/bbatsov/rubocop/issues/1343): Remove auto-correct from `RescueException` cop. ([@bbatsov][])
4
+ * [#1425](https://github.com/bbatsov/rubocop/issues/1425): `AllCops/Include` configuration parameters are only taken from the project `.rubocop.yml` and files it inherits from, not from `.rubocop.yml` files in subdirectories. ([@jonas054][])
5
+
6
+ ### Bugs fixed
7
+
8
+ * [#1411](https://github.com/bbatsov/rubocop/issues/1411): Handle lambda calls without a selector in `MultilineOperationIndentation`. ([@bbatsov][])
9
+ * [#1401](https://github.com/bbatsov/rubocop/issues/1401): Files in hidden directories, i.e. ones beginning with dot, can now be selected through configuration, but are still not included by default. ([@jonas054][])
10
+ * [#1415](https://github.com/bbatsov/rubocop/issues/1415): String literals concatenated with backslashes are now handled correctly by `StringLiteralsInInterpolation`. ([@jonas054][])
11
+ * [#1416](https://github.com/bbatsov/rubocop/issues/1416): Fix handling of `begin/rescue/else/end` in `ElseAlignment`. ([@jonas054][])
12
+ * [#1413](https://github.com/bbatsov/rubocop/issues/1413): Support empty elsif branches in `MultilineIfThen`. ([@janraasch][], [@jonas054][])
13
+ * [#1406](https://github.com/bbatsov/rubocop/issues/1406): Allow a newline in `SpaceInsideRangeLiteral`. ([@bbatsov][])
14
+
15
+ [@bbatsov]: https://github.com/bbatsov
16
+ [@jonas054]: https://github.com/jonas054
17
+ [@yujinakayama]: https://github.com/yujinakayama
18
+ [@dblock]: https://github.com/dblock
19
+ [@nevir]: https://github.com/nevir
20
+ [@daviddavis]: https://github.com/daviddavis
21
+ [@sds]: https://github.com/sds
22
+ [@fancyremarker]: https://github.com/fancyremarker
23
+ [@sinisterchipmunk]: https://github.com/sinisterchipmunk
24
+ [@vonTronje]: https://github.com/vonTronje
25
+ [@agrimm]: https://github.com/agrimm
26
+ [@pmenglund]: https://github.com/pmenglund
27
+ [@chulkilee]: https://github.com/chulkilee
28
+ [@codez]: https://github.com/codez
29
+ [@emou]: https://github.com/emou
30
+ [@skanev]: http://github.com/skanev
31
+ [@claco]: http://github.com/claco
32
+ [@rifraf]: http://github.com/rifraf
33
+ [@scottmatthewman]: https://github.com/scottmatthewman
34
+ [@ma2gedev]: http://github.com/ma2gedev
35
+ [@jeremyolliver]: https://github.com/jeremyolliver
36
+ [@hannestyden]: https://github.com/hannestyden
37
+ [@geniou]: https://github.com/geniou
38
+ [@jkogara]: https://github.com/jkogara
39
+ [@tmorris-fiksu]: https://github.com/tmorris-fiksu
40
+ [@mockdeep]: https://github.com/mockdeep
41
+ [@hiroponz]: https://github.com/hiroponz
42
+ [@tamird]: https://github.com/tamird
43
+ [@fshowalter]: https://github.com/fshowalter
44
+ [@cschramm]: https://github.com/cschramm
45
+ [@bquorning]: https://github.com/bquorning
46
+ [@bcobb]: https://github.com/bcobb
47
+ [@irrationalfab]: https://github.com/irrationalfab
48
+ [@tommeier]: https://github.com/tommeier
49
+ [@sfeldon]: https://github.com/sfeldon
50
+ [@biinari]: https://github.com/biinari
51
+ [@barunio]: https://github.com/barunio
52
+ [@molawson]: https://github.com/molawson
53
+ [@wndhydrnt]: https://github.com/wndhydrnt
54
+ [@ggilder]: https://github.com/ggilder
55
+ [@salbertson]: https://github.com/salbertson
56
+ [@camilleldn]: https://github.com/camilleldn
57
+ [@mcls]: https://github.com/mcls
58
+ [@yous]: https://github.com/yous
59
+ [@vrthra]: https://github.com/vrthra
60
+ [@SkuliOskarsson]: https://github.com/SkuliOskarsson
61
+ [@jspanjers]: https://github.com/jspanjers
62
+ [@sch1zo]: https://github.com/sch1zo
63
+ [@smangelsdorf]: https://github.com/smangelsdorf
64
+ [@mvz]: https://github.com/mvz
65
+ [@jfelchner]: https://github.com/jfelchner
66
+ [@janraasch]: https://github.com/janraasch
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.summary = 'Automatic Ruby code style checking tool.'
28
28
 
29
29
  s.add_runtime_dependency('rainbow', '>= 1.99.1', '< 3.0')
30
- s.add_runtime_dependency('parser', '>= 2.2.0.pre.6', '< 3.0')
30
+ s.add_runtime_dependency('parser', '>= 2.2.0.pre.7', '< 3.0')
31
31
  s.add_runtime_dependency('powerpack', '~> 0.0.6')
32
32
  s.add_runtime_dependency('astrolabe', '~> 1.3')
33
33
  s.add_runtime_dependency('ruby-progressbar', '~> 1.4')
@@ -528,7 +528,7 @@ describe RuboCop::CLI, :isolated_environment do
528
528
  ''].join("\n"))
529
529
  expect($stdout.string)
530
530
  .to eq(["#{abs('example.rb')}:2:1: C: [Corrected] Use hash " \
531
- 'literal {} instead of Hash.new.',
531
+ 'literal `{}` instead of `Hash.new`.',
532
532
  "#{abs('example.rb')}:2:9: C: [Corrected] Do not use " \
533
533
  'parentheses for method calls with no arguments.',
534
534
  ''].join("\n"))
@@ -1777,23 +1777,23 @@ describe RuboCop::CLI, :isolated_environment do
1777
1777
  end
1778
1778
 
1779
1779
  it 'finds included files' do
1780
- create_file('example', ['# encoding: utf-8',
1781
- 'x = 0',
1782
- 'puts x'
1783
- ])
1784
- create_file('regexp', ['# encoding: utf-8',
1785
- 'x = 0',
1786
- 'puts x'
1787
- ])
1780
+ create_file('file.rb', 'x=0') # Included by default
1781
+ create_file('example', 'x=0')
1782
+ create_file('regexp', 'x=0')
1783
+ create_file('.dot1/file.rb', 'x=0') # Hidden but explicitly included
1784
+ create_file('.dot2/file.rb', 'x=0') # Hidden, excluded by default
1788
1785
  create_file('.rubocop.yml', ['AllCops:',
1789
1786
  ' Include:',
1790
1787
  ' - example',
1791
- ' - !ruby/regexp /regexp$/'
1788
+ ' - !ruby/regexp /regexp$/',
1789
+ ' - .dot1/**/*'
1792
1790
  ])
1793
- expect(cli.run(%w(--format simple))).to eq(0)
1794
- expect($stdout.string)
1795
- .to eq(['', '2 files inspected, no offenses detected',
1796
- ''].join("\n"))
1791
+ expect(cli.run(%w(--format files))).to eq(1)
1792
+ expect($stderr.string).to eq('')
1793
+ expect($stdout.string.split($RS).sort).to eq([abs('.dot1/file.rb'),
1794
+ abs('example'),
1795
+ abs('file.rb'),
1796
+ abs('regexp')])
1797
1797
  end
1798
1798
 
1799
1799
  it 'ignores excluded files' do
@@ -1822,6 +1822,48 @@ describe RuboCop::CLI, :isolated_environment do
1822
1822
  ''].join("\n"))
1823
1823
  end
1824
1824
 
1825
+ it 'only reads configuration in explicitly included hidden directories' do
1826
+ create_file('.hidden/example.rb', ['# encoding: utf-8',
1827
+ 'x=0'])
1828
+ # This file contains configuration for an unknown cop. This would cause a
1829
+ # warning to be printed on stderr if the file was read. But it's in a
1830
+ # hidden directory, so it's not read.
1831
+ create_file('.hidden/.rubocop.yml', ['SymbolName:',
1832
+ ' Enabled: false'])
1833
+
1834
+ create_file('.other/example.rb', ['# encoding: utf-8',
1835
+ 'x=0'])
1836
+ # The .other directory is explicitly included, so the configuration file
1837
+ # is read, and modifies the behavior.
1838
+ create_file('.other/.rubocop.yml', ['Style/SpaceAroundOperators:',
1839
+ ' Enabled: false'])
1840
+ create_file('.rubocop.yml', ['AllCops:',
1841
+ ' Include:',
1842
+ ' - .other/**/*'])
1843
+ expect(cli.run(%w(--format simple))).to eq(1)
1844
+ expect($stderr.string).to eq('')
1845
+ expect($stdout.string)
1846
+ .to eq(['== .other/example.rb ==',
1847
+ 'W: 2: 1: Useless assignment to variable - x.',
1848
+ '',
1849
+ '1 file inspected, 1 offense detected',
1850
+ ''].join("\n"))
1851
+ end
1852
+
1853
+ it 'does not consider Include parameters in subdirectories' do
1854
+ create_file('dir/example.ruby', ['# encoding: utf-8',
1855
+ 'x=0'])
1856
+ create_file('dir/.rubocop.yml', ['AllCops:',
1857
+ ' Include:',
1858
+ ' - "*.ruby"'])
1859
+ expect(cli.run(%w(--format simple))).to eq(0)
1860
+ expect($stderr.string).to eq('')
1861
+ expect($stdout.string)
1862
+ .to eq(['',
1863
+ '0 files inspected, no offenses detected',
1864
+ ''].join("\n"))
1865
+ end
1866
+
1825
1867
  it 'matches included/excluded files corectly when . argument is given' do
1826
1868
  create_file('example.rb', 'x = 0')
1827
1869
  create_file('special.dsl', ['# encoding: utf-8',
@@ -2071,10 +2113,13 @@ describe RuboCop::CLI, :isolated_environment do
2071
2113
  it 'can exclude directories relative to .rubocop.yml' do
2072
2114
  %w(src etc/test etc/spec tmp/test tmp/spec).each do |dir|
2073
2115
  create_file("example/#{dir}/example1.rb", ['# encoding: utf-8',
2074
- '#' * 90
2075
- ])
2116
+ '#' * 90])
2076
2117
  end
2077
2118
 
2119
+ # Hidden subdirectories should also be excluded.
2120
+ create_file('example/etc/.dot/example1.rb', ['# encoding: utf-8',
2121
+ '#' * 90])
2122
+
2078
2123
  create_file('example/.rubocop.yml', ['AllCops:',
2079
2124
  ' Exclude:',
2080
2125
  ' - src/**',
@@ -2082,8 +2127,8 @@ describe RuboCop::CLI, :isolated_environment do
2082
2127
  ' - tmp/spec/**'])
2083
2128
 
2084
2129
  expect(cli.run(%w(--format simple example))).to eq(1)
2085
- expect($stdout.string).to eq(
2086
- ['== example/tmp/test/example1.rb ==',
2130
+ expect($stderr.string).to eq('')
2131
+ expect($stdout.string).to eq(['== example/tmp/test/example1.rb ==',
2087
2132
  'C: 2: 81: Line is too long. [90/80]',
2088
2133
  '',
2089
2134
  '1 file inspected, 1 offense detected',
@@ -120,40 +120,4 @@ describe RuboCop::Cop::Lint::RescueException do
120
120
  'end'])
121
121
  expect(cop.offenses).to be_empty
122
122
  end
123
-
124
- context 'without exception capture' do
125
- let(:source) do
126
- ['begin',
127
- 'rescue Exception',
128
- 'end']
129
- end
130
-
131
- let(:corrected_source) do
132
- ['begin', # rubocop:disable Style/WordArray
133
- 'rescue',
134
- 'end'].join("\n")
135
- end
136
-
137
- it 'autocorrects by unspecifying the exception class' do
138
- expect(autocorrect_source(cop, source)).to eq(corrected_source)
139
- end
140
- end
141
-
142
- context 'with exception capture' do
143
- let(:source) do
144
- ['begin',
145
- 'rescue Exception => e',
146
- 'end']
147
- end
148
-
149
- let(:corrected_source) do
150
- ['begin',
151
- 'rescue => e',
152
- 'end'].join("\n")
153
- end
154
-
155
- it 'autocorrects by unspecifying the exception class' do
156
- expect(autocorrect_source(cop, source)).to eq(corrected_source)
157
- end
158
- end
159
123
  end
@@ -417,6 +417,18 @@ describe RuboCop::Cop::Style::ElseAlignment do
417
417
  'end'])
418
418
  expect(cop.messages).to eq(['Align `else` with `begin`.'])
419
419
  end
420
+
421
+ it 'accepts a correctly aligned else' do
422
+ inspect_source(cop,
423
+ ['begin',
424
+ " raise StandardError.new('Fail') if rand(2).odd?",
425
+ 'rescue StandardError => error',
426
+ ' $stderr.puts error.message',
427
+ 'else',
428
+ " $stdout.puts 'Lucky you!'",
429
+ 'end'])
430
+ expect(cop.offenses).to be_empty
431
+ end
420
432
  end
421
433
 
422
434
  context 'with def/rescue/else/end' do
@@ -11,7 +11,7 @@ describe RuboCop::Cop::Style::EmptyLiteral do
11
11
  ['test = Array.new()'])
12
12
  expect(cop.offenses.size).to eq(1)
13
13
  expect(cop.messages)
14
- .to eq(['Use array literal [] instead of Array.new.'])
14
+ .to eq(['Use array literal `[]` instead of `Array.new`.'])
15
15
  end
16
16
 
17
17
  it 'registers an offense for Array.new' do
@@ -19,7 +19,7 @@ describe RuboCop::Cop::Style::EmptyLiteral do
19
19
  ['test = Array.new'])
20
20
  expect(cop.offenses.size).to eq(1)
21
21
  expect(cop.messages)
22
- .to eq(['Use array literal [] instead of Array.new.'])
22
+ .to eq(['Use array literal `[]` instead of `Array.new`.'])
23
23
  end
24
24
 
25
25
  it 'does not register an offense for Array.new(3)' do
@@ -40,7 +40,7 @@ describe RuboCop::Cop::Style::EmptyLiteral do
40
40
  ['test = Hash.new()'])
41
41
  expect(cop.offenses.size).to eq(1)
42
42
  expect(cop.messages)
43
- .to eq(['Use hash literal {} instead of Hash.new.'])
43
+ .to eq(['Use hash literal `{}` instead of `Hash.new`.'])
44
44
  end
45
45
 
46
46
  it 'registers an offense for Hash.new' do
@@ -48,7 +48,7 @@ describe RuboCop::Cop::Style::EmptyLiteral do
48
48
  ['test = Hash.new'])
49
49
  expect(cop.offenses.size).to eq(1)
50
50
  expect(cop.messages)
51
- .to eq(['Use hash literal {} instead of Hash.new.'])
51
+ .to eq(['Use hash literal `{}` instead of `Hash.new`.'])
52
52
  end
53
53
 
54
54
  it 'does not register an offense for Hash.new(3)' do
@@ -75,7 +75,7 @@ describe RuboCop::Cop::Style::EmptyLiteral do
75
75
  ['test = String.new()'])
76
76
  expect(cop.offenses.size).to eq(1)
77
77
  expect(cop.messages)
78
- .to eq(["Use string literal '' instead of String.new."])
78
+ .to eq(["Use string literal `''` instead of `String.new`."])
79
79
  end
80
80
 
81
81
  it 'registers an offense for String.new' do
@@ -83,7 +83,7 @@ describe RuboCop::Cop::Style::EmptyLiteral do
83
83
  ['test = String.new'])
84
84
  expect(cop.offenses.size).to eq(1)
85
85
  expect(cop.messages)
86
- .to eq(["Use string literal '' instead of String.new."])
86
+ .to eq(["Use string literal `''` instead of `String.new`."])
87
87
  end
88
88
 
89
89
  it 'does not register an offense for String.new("top")' do
@@ -8,7 +8,7 @@ describe RuboCop::Cop::Style::IfWithSemicolon do
8
8
  it 'registers an offense for one line if/;/end' do
9
9
  inspect_source(cop, ['if cond; run else dont end'])
10
10
  expect(cop.messages).to eq(
11
- ['Never use if x; Use the ternary operator instead.'])
11
+ ['Do not use if x; Use the ternary operator instead.'])
12
12
  end
13
13
 
14
14
  it 'accepts one line if/then/end' do
@@ -7,6 +7,13 @@ describe RuboCop::Cop::Style::MultilineIfThen do
7
7
 
8
8
  # if
9
9
 
10
+ it 'does not get confused by empty elsif branch' do
11
+ inspect_source(cop, ['if cond',
12
+ 'elsif cond',
13
+ 'end'])
14
+ expect(cop.offenses).to be_empty
15
+ end
16
+
10
17
  it 'registers an offense for then in multiline if' do
11
18
  inspect_source(cop, ['if cond then',
12
19
  'end',
@@ -19,7 +26,20 @@ describe RuboCop::Cop::Style::MultilineIfThen do
19
26
  'end',
20
27
  'if cond then # bad',
21
28
  'end'])
22
- expect(cop.offenses.map(&:line)).to eq([1, 3, 5, 7, 10])
29
+ expect(cop.offenses.map(&:line)).to eq([1, 3, 5, 8, 10])
30
+ expect(cop.highlights).to eq(['then'] * 5)
31
+ expect(cop.messages).to eq(['Do not use `then` for multi-line `if`.'] * 5)
32
+ end
33
+
34
+ it 'registers an offense for then in multiline elsif' do
35
+ inspect_source(cop, ['if cond1',
36
+ ' a',
37
+ 'elsif cond2 then',
38
+ ' b',
39
+ 'end'])
40
+ expect(cop.offenses.map(&:line)).to eq([3])
41
+ expect(cop.highlights).to eq(['then'])
42
+ expect(cop.messages).to eq(['Do not use `then` for multi-line `elsif`.'])
23
43
  end
24
44
 
25
45
  it 'accepts multiline if without then' do
@@ -72,7 +92,7 @@ describe RuboCop::Cop::Style::MultilineIfThen do
72
92
  inspect_source(cop, ['unless cond then',
73
93
  'end'])
74
94
  expect(cop.messages).to eq(
75
- ['Never use `then` for multi-line `unless`.'])
95
+ ['Do not use `then` for multi-line `unless`.'])
76
96
  end
77
97
 
78
98
  it 'accepts multiline unless without then' do
@@ -40,6 +40,15 @@ describe RuboCop::Cop::Style::MultilineOperationIndentation do
40
40
  expect(cop.highlights).to eq(['.b'])
41
41
  end
42
42
 
43
+ it 'registers an offense for proc call without a selector' do
44
+ inspect_source(cop,
45
+ ['a',
46
+ ' .(args)'])
47
+ expect(cop.messages).to eq(['Use 2 (not 1) spaces for indenting an ' \
48
+ 'expression spanning multiple lines.'])
49
+ expect(cop.highlights).to eq(['.('])
50
+ end
51
+
43
52
  it 'registers an offense for three spaces indentation of second line' do
44
53
  inspect_source(cop,
45
54
  ['a ||',
@@ -40,6 +40,18 @@ describe RuboCop::Cop::Style::SpaceInsideRangeLiteral do
40
40
  expect(cop.offenses).to be_empty
41
41
  end
42
42
 
43
+ it 'accepts multiline range literal with no space in it' do
44
+ inspect_source(cop, ['x = 0..',
45
+ ' 10'])
46
+ expect(cop.offenses).to be_empty
47
+ end
48
+
49
+ it 'registers an offense in multiline range literal with space in it' do
50
+ inspect_source(cop, ['x = 0 ..',
51
+ ' 10'])
52
+ expect(cop.offenses.size).to eq(1)
53
+ end
54
+
43
55
  it 'autocorrects space around .. literal' do
44
56
  corrected = autocorrect_source(cop, ['1 .. 2'])
45
57
  expect(corrected).to eq '1..2'
@@ -8,19 +8,45 @@ describe RuboCop::Cop::Style::StringLiteralsInInterpolation, :config do
8
8
  context 'configured with single quotes preferred' do
9
9
  let(:cop_config) { { 'EnforcedStyle' => 'single_quotes' } }
10
10
 
11
- it 'detects unneeded double quotes within embedded expression' do
11
+ it 'registers an offense for double quotes within embedded expression' do
12
12
  src = ['"#{"A"}"']
13
13
  inspect_source(cop, src)
14
14
  expect(cop.messages)
15
15
  .to eq(['Prefer single-quoted strings inside interpolations.'])
16
16
  end
17
17
 
18
+ it 'registers an offense for double quotes within embedded expression in ' \
19
+ 'a heredoc string' do
20
+ src = ['<<END',
21
+ '#{"A"}',
22
+ 'END']
23
+ inspect_source(cop, src)
24
+ expect(cop.messages)
25
+ .to eq(['Prefer single-quoted strings inside interpolations.'])
26
+ end
27
+
18
28
  it 'accepts double quotes on a static string' do
19
29
  src = ['"A"']
20
30
  inspect_source(cop, src)
21
31
  expect(cop.offenses).to be_empty
22
32
  end
23
33
 
34
+ it 'accepts double quotes on a broken static string' do
35
+ src = ['"A" \\',
36
+ ' "B"']
37
+ inspect_source(cop, src)
38
+ expect(cop.offenses).to be_empty
39
+ end
40
+
41
+ it 'accepts double quotes on static strings within a method' do
42
+ src = ['def m',
43
+ ' puts "A"',
44
+ ' puts "B"',
45
+ 'end']
46
+ inspect_source(cop, src)
47
+ expect(cop.offenses).to be_empty
48
+ end
49
+
24
50
  it 'can handle a built-in constant parsed as string' do
25
51
  # Parser will produce str nodes for constants such as __FILE__.
26
52
  src = ['if __FILE__ == $PROGRAM_NAME',
@@ -50,6 +76,16 @@ describe RuboCop::Cop::Style::StringLiteralsInInterpolation, :config do
50
76
  expect(cop.messages)
51
77
  .to eq(['Prefer double-quoted strings inside interpolations.'])
52
78
  end
79
+
80
+ it 'registers an offense for single quotes within embedded expression in ' \
81
+ 'a heredoc string' do
82
+ src = ['<<END',
83
+ '#{\'A\'}',
84
+ 'END']
85
+ inspect_source(cop, src)
86
+ expect(cop.messages)
87
+ .to eq(['Prefer double-quoted strings inside interpolations.'])
88
+ end
53
89
  end
54
90
 
55
91
  context 'when configured with a bad value' do
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.27.0
4
+ version: 0.27.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-10-30 00:00:00.000000000 Z
13
+ date: 2014-11-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rainbow
@@ -38,7 +38,7 @@ dependencies:
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 2.2.0.pre.6
41
+ version: 2.2.0.pre.7
42
42
  - - "<"
43
43
  - !ruby/object:Gem::Version
44
44
  version: '3.0'
@@ -48,7 +48,7 @@ dependencies:
48
48
  requirements:
49
49
  - - ">="
50
50
  - !ruby/object:Gem::Version
51
- version: 2.2.0.pre.6
51
+ version: 2.2.0.pre.7
52
52
  - - "<"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
@@ -481,6 +481,7 @@ files:
481
481
  - relnotes/v0.26.0.md
482
482
  - relnotes/v0.26.1.md
483
483
  - relnotes/v0.27.0.md
484
+ - relnotes/v0.27.1.md
484
485
  - rubocop.gemspec
485
486
  - spec/.rubocop.yml
486
487
  - spec/fixtures/html_formatter/expected.html