rubocop 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +18 -2
  4. data/lib/rubocop.rb +1 -0
  5. data/lib/rubocop/cli/command/execute_runner.rb +26 -11
  6. data/lib/rubocop/config_regeneration.rb +1 -1
  7. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
  8. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
  9. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +77 -7
  10. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  11. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
  12. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  13. data/lib/rubocop/cop/lint/missing_super.rb +7 -4
  14. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +13 -4
  15. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  16. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  17. data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
  18. data/lib/rubocop/cop/style/documentation.rb +12 -1
  19. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
  20. data/lib/rubocop/cop/style/redundant_argument.rb +73 -0
  21. data/lib/rubocop/cop/util.rb +1 -1
  22. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  23. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  24. data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
  25. data/lib/rubocop/options.rb +5 -0
  26. data/lib/rubocop/rake_task.rb +2 -2
  27. data/lib/rubocop/runner.rb +1 -1
  28. data/lib/rubocop/version.rb +1 -1
  29. metadata +4 -8
  30. data/assets/logo.png +0 -0
  31. data/assets/output.html.erb +0 -261
  32. data/bin/console +0 -10
  33. data/bin/rubocop-profile +0 -32
  34. data/bin/setup +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4238df3546a63ce2c279ced4bba228a61c137b083a3fad76b45365954555f690
4
- data.tar.gz: bf3bd7a2409203b911212906d013aec7219f1a21825352bc92e0b897faafbd66
3
+ metadata.gz: 840dbd224c26defdcf3fe6d5c48f6e495f4288141a38f5e79de74552a0a1d9d8
4
+ data.tar.gz: 381215eaceb9e62bdb1ba0df04880b4b8c702bfd4e11df78d0683b539451fb3c
5
5
  SHA512:
6
- metadata.gz: a87bd4426855a7278963b8c3e4373b7c995994b5685318aad04bc2b0832c0db44e705d50d4ea21d81eb47074137fde56665f8317121caae8a81e208e044ce4a7
7
- data.tar.gz: 3bb4cb7794129ac95c70876bc009a4ed07425a7a346acaf77279c4e0fc8b1c20f31e82e9590e1d880fa011ddddc08c93bb3851f6f815718b9de8ff7a0dd78c6f
6
+ metadata.gz: d3a563aeb426e7ae74dcc9dbc28d153e3b672d0abcae22bea62ff6077bb2bb7eff78cdacf3f4f9a384d09ddc417744135c3a47536145052bbbca985008514b5e
7
+ data.tar.gz: 0c832cf607fa6fe0bd5513dc82f315638285f225c7456a2a884830cd173bb740ca741b4ea2279e908b8a00ecb94e60f40c7b2064841efa2152f50ce6a40477a2
data/README.md CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
51
51
  in your `Gemfile`:
52
52
 
53
53
  ```rb
54
- gem 'rubocop', '~> 1.3', require: false
54
+ gem 'rubocop', '~> 1.4', require: false
55
55
  ```
56
56
 
57
57
  See [versioning](https://docs.rubocop.org/rubocop/1.0/versioning.html) for further details.
@@ -463,6 +463,10 @@ Layout/EmptyLineBetweenDefs:
463
463
  StyleGuide: '#empty-lines-between-methods'
464
464
  Enabled: true
465
465
  VersionAdded: '0.49'
466
+ VersionChanged: '1.4'
467
+ EmptyLineBetweenMethodDefs: true
468
+ EmptyLineBetweenClassDefs: true
469
+ EmptyLineBetweenModuleDefs: true
466
470
  # If `true`, this parameter means that single line method definitions don't
467
471
  # need an empty line between them.
468
472
  AllowAdjacentOneLineDefs: false
@@ -891,8 +895,8 @@ Layout/LineLength:
891
895
  StyleGuide: '#max-line-length'
892
896
  Enabled: true
893
897
  VersionAdded: '0.25'
894
- VersionChanged: '1.3'
895
- AutoCorrect: false
898
+ VersionChanged: '1.4'
899
+ AutoCorrect: true
896
900
  Max: 120
897
901
  # To make it possible to copy or click on URIs in the code, we allow lines
898
902
  # containing a URI to be longer than Max.
@@ -1684,6 +1688,7 @@ Lint/MissingSuper:
1684
1688
  without calls to `super`'.
1685
1689
  Enabled: true
1686
1690
  VersionAdded: '0.89'
1691
+ VersionChanged: '1.4'
1687
1692
 
1688
1693
  Lint/MixedRegexpCaptureTypes:
1689
1694
  Description: 'Do not mix named captures and numbered captures in a Regexp literal.'
@@ -3976,6 +3981,17 @@ Style/RandomWithOffset:
3976
3981
  Enabled: true
3977
3982
  VersionAdded: '0.52'
3978
3983
 
3984
+ Style/RedundantArgument:
3985
+ Description: 'Check for a redundant argument passed to certain methods.'
3986
+ Enabled: pending
3987
+ Safe: false
3988
+ VersionAdded: '1.4'
3989
+ Methods:
3990
+ # Array#join
3991
+ join: ''
3992
+ # String#split
3993
+ split: ' '
3994
+
3979
3995
  Style/RedundantAssignment:
3980
3996
  Description: 'Checks for redundant assignment before returning.'
3981
3997
  Enabled: true
@@ -529,6 +529,7 @@ require_relative 'rubocop/cop/style/preferred_hash_methods'
529
529
  require_relative 'rubocop/cop/style/proc'
530
530
  require_relative 'rubocop/cop/style/raise_args'
531
531
  require_relative 'rubocop/cop/style/random_with_offset'
532
+ require_relative 'rubocop/cop/style/redundant_argument'
532
533
  require_relative 'rubocop/cop/style/redundant_begin'
533
534
  require_relative 'rubocop/cop/style/redundant_capital_w'
534
535
  require_relative 'rubocop/cop/style/redundant_condition'
@@ -22,12 +22,13 @@ module RuboCop
22
22
  def execute_runner(paths)
23
23
  runner = Runner.new(@options, @config_store)
24
24
 
25
- all_passed = runner.run(paths)
26
- display_warning_summary(runner.warnings)
27
- display_error_summary(runner.errors)
28
- maybe_print_corrected_source
25
+ all_pass_or_excluded = with_redirect do
26
+ all_passed = runner.run(paths)
27
+ display_summary(runner)
28
+ all_passed || @options[:auto_gen_config]
29
+ end
29
30
 
30
- all_pass_or_excluded = all_passed || @options[:auto_gen_config]
31
+ maybe_print_corrected_source
31
32
 
32
33
  if runner.aborting?
33
34
  STATUS_INTERRUPTED
@@ -38,6 +39,25 @@ module RuboCop
38
39
  end
39
40
  end
40
41
 
42
+ def with_redirect
43
+ if @options[:stderr]
44
+ orig_stdout = $stdout.dup
45
+ $stdout.reopen($stderr)
46
+
47
+ result = yield
48
+
49
+ $stdout.reopen(orig_stdout)
50
+ result
51
+ else
52
+ yield
53
+ end
54
+ end
55
+
56
+ def display_summary(runner)
57
+ display_warning_summary(runner.warnings)
58
+ display_error_summary(runner.errors)
59
+ end
60
+
41
61
  def display_warning_summary(warnings)
42
62
  return if warnings.empty?
43
63
 
@@ -69,14 +89,9 @@ module RuboCop
69
89
  # See: https://github.com/rubocop-hq/rubocop/issues/8673
70
90
  return if INTEGRATION_FORMATTERS.include?(@options[:format])
71
91
 
72
- # If we are asked to autocorrect source code read from stdin, the only
73
- # reasonable place to write it is to stdout
74
- # Unfortunately, we also write other information to stdout
75
- # So a delimiter is needed for tools to easily identify where the
76
- # autocorrected source begins
77
92
  return unless @options[:stdin] && @options[:auto_correct]
78
93
 
79
- puts '=' * 20
94
+ (@options[:stderr] ? $stderr : $stdout).puts '=' * 20
80
95
  print @options[:stdin]
81
96
  end
82
97
  end
@@ -16,7 +16,7 @@ module RuboCop
16
16
  match = generation_command.match(COMMAND_REGEX)
17
17
  return DEFAULT_OPTIONS unless match
18
18
 
19
- options = match[1].split(' ')
19
+ options = match[1].split
20
20
  Options.new.parse(options).first
21
21
  end
22
22
 
@@ -48,7 +48,7 @@ module RuboCop
48
48
  def autocorrect_multiline_words(node, escape, delimiters)
49
49
  contents = process_multiline_words(node, escape, delimiters)
50
50
  contents << end_content(node.source)
51
- contents.join('')
51
+ contents.join
52
52
  end
53
53
 
54
54
  def autocorrect_words(node, escape, delimiters)
@@ -38,7 +38,7 @@ module RuboCop
38
38
 
39
39
  def assertions_using_described_class_msg
40
40
  described_class_msg(processed_source.ast).reject do |node|
41
- node.ancestors.any?(&method(:rspec_expectation_on_msg?))
41
+ node.ancestors.any? { |ancestor| rspec_expectation_on_msg?(ancestor) }
42
42
  end
43
43
  end
44
44
 
@@ -13,7 +13,8 @@ module RuboCop
13
13
  # `AllowAdjacentOneLineDefs` configures whether adjacent
14
14
  # one-line method definitions are considered an offense.
15
15
  #
16
- # @example
16
+ # @example EmptyLineBetweenMethodDefs: true (default)
17
+ # # checks for empty lines between method definitions.
17
18
  #
18
19
  # # bad
19
20
  # def a
@@ -29,11 +30,57 @@ module RuboCop
29
30
  #
30
31
  # def b
31
32
  # end
33
+ #
34
+ # @example EmptyLineBetweenClassDefs: true (default)
35
+ # # checks for empty lines between class definitions.
36
+ #
37
+ # # bad
38
+ # class A
39
+ # end
40
+ # class B
41
+ # end
42
+ # def b
43
+ # end
44
+ #
45
+ # @example
46
+ #
47
+ # # good
48
+ # class A
49
+ # end
50
+ #
51
+ # class B
52
+ # end
53
+ #
54
+ # def b
55
+ # end
56
+ #
57
+ # @example EmptyLineBetweenModuleDefs: true (default)
58
+ # # checks for empty lines between module definitions.
59
+ #
60
+ # # bad
61
+ # module A
62
+ # end
63
+ # module B
64
+ # end
65
+ # def b
66
+ # end
67
+ #
68
+ # @example
69
+ #
70
+ # # good
71
+ # module A
72
+ # end
73
+ #
74
+ # module B
75
+ # end
76
+ #
77
+ # def b
78
+ # end
32
79
  class EmptyLineBetweenDefs < Base
33
80
  include RangeHelp
34
81
  extend AutoCorrector
35
82
 
36
- MSG = 'Use empty lines between method definitions.'
83
+ MSG = 'Use empty lines between %<type>s definitions.'
37
84
 
38
85
  def self.autocorrect_incompatible_with
39
86
  [Layout::EmptyLines]
@@ -47,7 +94,7 @@ module RuboCop
47
94
  def on_begin(node)
48
95
  node.children.each_cons(2) do |prev, n|
49
96
  nodes = [prev, n]
50
- check_defs(nodes) if nodes.all?(&method(:def_node?))
97
+ check_defs(nodes) if nodes.all? { |def_candidate| candidate?(def_candidate) }
51
98
  end
52
99
  end
53
100
 
@@ -57,8 +104,9 @@ module RuboCop
57
104
  return if nodes.all?(&:single_line?) &&
58
105
  cop_config['AllowAdjacentOneLineDefs']
59
106
 
60
- location = nodes.last.loc.keyword.join(nodes.last.loc.name)
61
- add_offense(location) do |corrector|
107
+ correction_node = nodes.last
108
+ location = correction_node.loc.keyword.join(correction_node.loc.name)
109
+ add_offense(location, message: message(correction_node)) do |corrector|
62
110
  autocorrect(corrector, *nodes)
63
111
  end
64
112
  end
@@ -83,10 +131,32 @@ module RuboCop
83
131
 
84
132
  private
85
133
 
86
- def def_node?(node)
134
+ def candidate?(node)
87
135
  return unless node
88
136
 
89
- node.def_type? || node.defs_type?
137
+ method_candidate?(node) || class_candidate?(node) || module_candidate?(node)
138
+ end
139
+
140
+ def method_candidate?(node)
141
+ cop_config['EmptyLineBetweenMethodDefs'] && (node.def_type? || node.defs_type?)
142
+ end
143
+
144
+ def class_candidate?(node)
145
+ cop_config['EmptyLineBetweenClassDefs'] && node.class_type?
146
+ end
147
+
148
+ def module_candidate?(node)
149
+ cop_config['EmptyLineBetweenModuleDefs'] && node.module_type?
150
+ end
151
+
152
+ def message(node)
153
+ type = case node.type
154
+ when :def, :defs
155
+ :method
156
+ else
157
+ node.type
158
+ end
159
+ format(MSG, type: type)
90
160
  end
91
161
 
92
162
  def multiple_blank_lines_groups?(first_def_node, second_def_node)
@@ -51,7 +51,7 @@ module RuboCop
51
51
  alias on_csend on_send
52
52
 
53
53
  def on_const(node)
54
- return unless node.loc.double_colon
54
+ return unless node.loc.respond_to?(:double_colon) && node.loc.double_colon
55
55
 
56
56
  check_space_after_double_colon(node)
57
57
  end
@@ -53,7 +53,8 @@ module RuboCop
53
53
  def find_offense_node(node, regexp_receiver)
54
54
  return node unless node.parent
55
55
 
56
- if node.parent.send_type? || method_chain_to_regexp_receiver?(node, regexp_receiver)
56
+ if (node.parent.send_type? && node.receiver) ||
57
+ method_chain_to_regexp_receiver?(node, regexp_receiver)
57
58
  node = find_offense_node(node.parent, regexp_receiver)
58
59
  end
59
60
 
@@ -95,7 +95,7 @@ module RuboCop
95
95
  def autocorrected_value_for_array(node)
96
96
  return node.source.gsub('"', '\"') unless node.percent_literal?
97
97
 
98
- contents_range(node).source.split(' ').to_s.gsub('"', '\"')
98
+ contents_range(node).source.split.to_s.gsub('"', '\"')
99
99
  end
100
100
 
101
101
  # Does node print its own source when converted to a string?
@@ -6,6 +6,11 @@ module RuboCop
6
6
  # This cop checks for the presence of constructors and lifecycle callbacks
7
7
  # without calls to `super`.
8
8
  #
9
+ # This cop does not consider `method_missing` (and `respond_to_missing?`)
10
+ # because in some cases it makes sense to overtake what is considered a
11
+ # missing method. In other cases, the theoretical ideal handling could be
12
+ # challenging or verbose for no actual gain.
13
+ #
9
14
  # @example
10
15
  # # bad
11
16
  # class Employee < Person
@@ -43,15 +48,13 @@ module RuboCop
43
48
 
44
49
  STATELESS_CLASSES = %w[BasicObject Object].freeze
45
50
 
46
- OBJECT_LIFECYCLE_CALLBACKS = %i[method_missing respond_to_missing?].freeze
47
51
  CLASS_LIFECYCLE_CALLBACKS = %i[inherited].freeze
48
52
  METHOD_LIFECYCLE_CALLBACKS = %i[method_added method_removed method_undefined
49
53
  singleton_method_added singleton_method_removed
50
54
  singleton_method_undefined].freeze
51
55
 
52
- CALLBACKS = (OBJECT_LIFECYCLE_CALLBACKS +
53
- CLASS_LIFECYCLE_CALLBACKS +
54
- METHOD_LIFECYCLE_CALLBACKS).to_set.freeze
56
+ CALLBACKS = (CLASS_LIFECYCLE_CALLBACKS +
57
+ METHOD_LIFECYCLE_CALLBACKS).to_set.freeze
55
58
 
56
59
  def on_def(node)
57
60
  return unless offender?(node)
@@ -54,6 +54,9 @@ module RuboCop
54
54
  # value
55
55
  # end
56
56
  #
57
+ # # good, recursive
58
+ # keys.reduce(self) { |result, key| result[key] }
59
+ #
57
60
  # # ignored as the return value cannot be determined
58
61
  # enum.reduce do |acc, el|
59
62
  # x = foo(acc, el)
@@ -131,7 +134,7 @@ module RuboCop
131
134
  element_name = block_arg_name(block_node, 1)
132
135
  message_opts = { method: block_node.method_name, accum: accumulator_name }
133
136
 
134
- if (node = returned_accumulator_index(return_values, accumulator_name))
137
+ if (node = returned_accumulator_index(return_values, accumulator_name, element_name))
135
138
  add_offense(node, message: format(MSG_INDEX, message_opts))
136
139
  elsif potential_offense?(return_values, block_node.body, element_name, accumulator_name)
137
140
  return_values.each do |return_val|
@@ -146,11 +149,17 @@ module RuboCop
146
149
  node.arguments[index].node_parts[0]
147
150
  end
148
151
 
149
- # Look for an index of the accumulator being returned
152
+ # Look for an index of the accumulator being returned, except where the index
153
+ # is the element.
150
154
  # This is always an offense, in order to try to catch potential exceptions
151
155
  # due to type mismatches
152
- def returned_accumulator_index(return_values, accumulator_name)
153
- return_values.detect { |val| accumulator_index?(val, accumulator_name) }
156
+ def returned_accumulator_index(return_values, accumulator_name, element_name)
157
+ return_values.detect do |val|
158
+ next unless accumulator_index?(val, accumulator_name)
159
+ next true if val.method?(:[]=)
160
+
161
+ val.arguments.none? { |arg| lvar_used?(arg, element_name) }
162
+ end
154
163
  end
155
164
 
156
165
  def potential_offense?(return_values, block_body, element_name, accumulator_name)
@@ -36,7 +36,7 @@ module RuboCop
36
36
 
37
37
  def on_def(node)
38
38
  excluded_methods = cop_config['ExcludedMethods']
39
- return if excluded_methods.include?(String(node.method_name))
39
+ return if excluded_methods.any? { |m| m.match? String(node.method_name) }
40
40
 
41
41
  check_code_length(node)
42
42
  end
@@ -31,7 +31,7 @@ module RuboCop
31
31
  # b c { block }. <-- b is indented relative to a
32
32
  # d <-- d is indented relative to a
33
33
  def left_hand_side(lhs)
34
- lhs = lhs.parent while lhs.parent&.send_type?
34
+ lhs = lhs.parent while lhs.parent&.send_type? && lhs.parent.loc.dot
35
35
  lhs
36
36
  end
37
37
 
@@ -16,9 +16,7 @@ module RuboCop
16
16
  end
17
17
 
18
18
  def find_visibility_start(node)
19
- node.left_siblings
20
- .reverse
21
- .find(&method(:visibility_block?))
19
+ node.left_siblings.reverse.find { |sibling| visibility_block?(sibling) }
22
20
  end
23
21
 
24
22
  # Navigate to find the last protected method
@@ -55,6 +55,11 @@ module RuboCop
55
55
  # Public = Class.new
56
56
  # end
57
57
  #
58
+ # # Macro calls
59
+ # module Namespace
60
+ # extend Foo
61
+ # end
62
+ #
58
63
  class Documentation < Base
59
64
  include DocumentationComment
60
65
 
@@ -83,15 +88,21 @@ module RuboCop
83
88
  return if documentation_comment?(node) || nodoc_comment?(node)
84
89
  return if compact_namespace?(node) &&
85
90
  nodoc_comment?(outer_module(node).first)
91
+ return if macro_only?(body)
86
92
 
87
93
  add_offense(node.loc.keyword, message: format(MSG, type: type))
88
94
  end
89
95
 
96
+ def macro_only?(body)
97
+ body.respond_to?(:macro?) && body.macro? ||
98
+ body.respond_to?(:children) && body.children&.all? { |child| macro_only?(child) }
99
+ end
100
+
90
101
  def namespace?(node)
91
102
  return false unless node
92
103
 
93
104
  if node.begin_type?
94
- node.children.all?(&method(:constant_declaration?))
105
+ node.children.all? { |child| constant_declaration?(child) }
95
106
  else
96
107
  constant_definition?(node)
97
108
  end
@@ -74,7 +74,7 @@ module RuboCop
74
74
  parent &&
75
75
  (logical_operator?(parent) ||
76
76
  parent.send_type? &&
77
- parent.arguments.any?(&method(:logical_operator?)))
77
+ parent.arguments.any? { |argument| logical_operator?(argument) })
78
78
  end
79
79
 
80
80
  def call_in_optional_arguments?(node)
@@ -110,7 +110,7 @@ module RuboCop
110
110
  def hash_literal_in_arguments?(node)
111
111
  node.arguments.any? do |n|
112
112
  hash_literal?(n) ||
113
- n.send_type? && node.descendants.any?(&method(:hash_literal?))
113
+ n.send_type? && node.descendants.any? { |descendant| hash_literal?(descendant) }
114
114
  end
115
115
  end
116
116
 
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'parser/current'
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Style
8
+ # This cop checks for a redundant argument passed to certain methods.
9
+ #
10
+ # Limitations:
11
+ #
12
+ # 1. This cop matches for method names only and hence cannot tell apart
13
+ # methods with same name in different classes.
14
+ # 2. This cop is limited to methods with single parameter.
15
+ # 3. This cop is unsafe if certain special global variables (e.g. `$;`) are set.
16
+ # That depends on the nature of the target methods, of course.
17
+ #
18
+ # Method names and their redundant arguments can be configured like this:
19
+ #
20
+ # Methods:
21
+ # join: ''
22
+ # split: ' '
23
+ # foo: 2
24
+ #
25
+ # @example
26
+ # # bad
27
+ # array.join('')
28
+ # [1, 2, 3].join("")
29
+ # string.split(" ")
30
+ # "first\nsecond".split(" ")
31
+ # A.foo(2)
32
+ #
33
+ # # good
34
+ # array.join
35
+ # [1, 2, 3].join
36
+ # string.split
37
+ # "first second".split
38
+ # A.foo
39
+ class RedundantArgument < Cop
40
+ MSG = 'Argument %<arg>s is redundant because it is implied by default.'
41
+
42
+ def on_send(node)
43
+ return unless redundant_argument?(node)
44
+
45
+ add_offense(node, message: format(MSG, arg: node.arguments.first.source))
46
+ end
47
+
48
+ private
49
+
50
+ def redundant_argument?(node)
51
+ redundant_argument = redundant_arg_for_method(node.method_name.to_s)
52
+ return false if redundant_argument.nil?
53
+
54
+ node.arguments.first == redundant_argument
55
+ end
56
+
57
+ def redundant_arg_for_method(method_name)
58
+ return nil unless cop_config['Methods'].key?(method_name)
59
+
60
+ @mem ||= {}
61
+ @mem[method_name] ||=
62
+ begin
63
+ arg = cop_config['Methods'].fetch(method_name)
64
+ buffer = Parser::Source::Buffer.new('(string)', 1)
65
+ buffer.source = arg.inspect
66
+ builder = RuboCop::AST::Builder.new
67
+ Parser::CurrentRuby.new(builder).parse(buffer)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -53,7 +53,7 @@ module RuboCop
53
53
  end
54
54
 
55
55
  def on_node(syms, sexp, excludes = [], &block)
56
- return to_enum(:on_node, syms, sexp, excludes) unless block_given?
56
+ return to_enum(:on_node, syms, sexp, excludes) unless block
57
57
 
58
58
  yield sexp if Array(syms).include?(sexp.type)
59
59
  return if Array(excludes).include?(sexp.type)
@@ -78,7 +78,7 @@ module RuboCop
78
78
  end
79
79
 
80
80
  def each_ancestor(include_self: false, &block)
81
- return to_enum(__method__, include_self: include_self) unless block_given?
81
+ return to_enum(__method__, include_self: include_self) unless block
82
82
 
83
83
  yield self if include_self
84
84
  scan_ancestors(&block)
@@ -61,7 +61,7 @@ module RuboCop
61
61
  end
62
62
 
63
63
  def each_node(&block)
64
- return to_enum(__method__) unless block_given?
64
+ return to_enum(__method__) unless block
65
65
 
66
66
  yield node if naked_top_level?
67
67
  scan_node(node, &block)
@@ -5,6 +5,8 @@ module RuboCop
5
5
  # This formatter displays a YAML configuration file where all cops that
6
6
  # detected any offenses are configured to not detect the offense.
7
7
  class DisabledConfigFormatter < BaseFormatter
8
+ include PathUtil
9
+
8
10
  HEADING = <<~COMMENTS
9
11
  # This configuration was generated by
10
12
  # `%<command>s`
@@ -195,15 +197,28 @@ module RuboCop
195
197
  end
196
198
 
197
199
  def excludes(offending_files, cop_name, parent)
198
- # Exclude properties in .rubocop_todo.yml override default ones, as well
199
- # as any custom excludes in .rubocop.yml, so in order to retain those
200
- # excludes we must copy them.
201
- # There can be multiple .rubocop.yml files in subdirectories, but we
202
- # just look at the current working directory
200
+ # Exclude properties in .rubocop_todo.yml override default ones, as well as any custom
201
+ # excludes in .rubocop.yml, so in order to retain those excludes we must copy them.
202
+ # There can be multiple .rubocop.yml files in subdirectories, but we just look at the
203
+ # current working directory.
203
204
  config = ConfigStore.new.for(parent)
204
205
  cfg = config[cop_name] || {}
205
206
 
206
- ((cfg['Exclude'] || []) + offending_files).uniq
207
+ if merge_mode_for_exclude?(config) || merge_mode_for_exclude?(cfg)
208
+ offending_files
209
+ else
210
+ cop_exclude = cfg['Exclude']
211
+ if cop_exclude && cop_exclude != default_config(cop_name)['Exclude']
212
+ warn "`#{cop_name}: Exclude` in `#{smart_path(config.loaded_path)}` overrides a " \
213
+ 'generated `Exclude` in `.rubocop_todo.yml`. Either remove ' \
214
+ "`#{cop_name}: Exclude` or add `inherit_mode: merge: - Exclude`."
215
+ end
216
+ ((cop_exclude || []) + offending_files).uniq
217
+ end
218
+ end
219
+
220
+ def merge_mode_for_exclude?(cfg)
221
+ Array(cfg.to_h.dig('inherit_mode', 'merge')).include?('Exclude')
207
222
  end
208
223
 
209
224
  def output_exclude_path(output_buffer, exclude_path, parent)
@@ -5,6 +5,7 @@ require 'shellwords'
5
5
 
6
6
  module RuboCop
7
7
  class IncorrectCopNameError < StandardError; end
8
+
8
9
  class OptionArgumentError < StandardError; end
9
10
 
10
11
  # This class handles command line options.
@@ -195,6 +196,7 @@ module RuboCop
195
196
 
196
197
  option(opts, '--safe')
197
198
 
199
+ option(opts, '--stderr')
198
200
  option(opts, '--[no-]color')
199
201
 
200
202
  option(opts, '-v', '--version')
@@ -498,6 +500,9 @@ module RuboCop
498
500
  extra_details: 'Display extra details in offense messages.',
499
501
  lint: 'Run only lint cops.',
500
502
  safe: 'Run only safe cops.',
503
+ stderr: ['Write all output to stderr except for the',
504
+ 'autocorrected source. This is especially useful',
505
+ 'when combined with --auto-correct and --stdin.'],
501
506
  list_target_files: 'List all files RuboCop will inspect.',
502
507
  auto_correct: 'Auto-correct offenses (only when it\'s safe).',
503
508
  safe_auto_correct: '(same, deprecated)',
@@ -22,7 +22,7 @@ module RuboCop
22
22
 
23
23
  task(name, *args) do |_, task_args|
24
24
  RakeFileUtils.verbose(verbose) do
25
- yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
25
+ yield(*[self, task_args].slice(0, task_block.arity)) if task_block
26
26
  run_cli(verbose, full_options)
27
27
  end
28
28
  end
@@ -66,7 +66,7 @@ module RuboCop
66
66
 
67
67
  task(:auto_correct, *args) do |_, task_args|
68
68
  RakeFileUtils.verbose(verbose) do
69
- yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
69
+ yield(*[self, task_args].slice(0, task_block.arity)) if task_block
70
70
  options = full_options.unshift('--auto-correct-all')
71
71
  options.delete('--parallel')
72
72
  run_cli(verbose, options)
@@ -64,7 +64,7 @@ module RuboCop
64
64
  # instances that each inspects its allotted group of files.
65
65
  def warm_cache(target_files)
66
66
  puts 'Running parallel inspection' if @options[:debug]
67
- Parallel.each(target_files, &method(:file_offenses))
67
+ Parallel.each(target_files) { |target_file| file_offenses(target_file) }
68
68
  end
69
69
 
70
70
  def find_target_files(paths)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.3.1'
6
+ STRING = '1.4.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, '\
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
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: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2020-11-16 00:00:00.000000000 Z
13
+ date: 2020-11-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parallel
@@ -169,11 +169,6 @@ extra_rdoc_files:
169
169
  files:
170
170
  - LICENSE.txt
171
171
  - README.md
172
- - assets/logo.png
173
- - assets/output.html.erb
174
- - bin/console
175
- - bin/rubocop-profile
176
- - bin/setup
177
172
  - config/default.yml
178
173
  - exe/rubocop
179
174
  - lib/rubocop.rb
@@ -685,6 +680,7 @@ files:
685
680
  - lib/rubocop/cop/style/proc.rb
686
681
  - lib/rubocop/cop/style/raise_args.rb
687
682
  - lib/rubocop/cop/style/random_with_offset.rb
683
+ - lib/rubocop/cop/style/redundant_argument.rb
688
684
  - lib/rubocop/cop/style/redundant_assignment.rb
689
685
  - lib/rubocop/cop/style/redundant_begin.rb
690
686
  - lib/rubocop/cop/style/redundant_capital_w.rb
@@ -821,7 +817,7 @@ metadata:
821
817
  homepage_uri: https://rubocop.org/
822
818
  changelog_uri: https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md
823
819
  source_code_uri: https://github.com/rubocop-hq/rubocop/
824
- documentation_uri: https://docs.rubocop.org/rubocop/1.3/
820
+ documentation_uri: https://docs.rubocop.org/rubocop/1.4/
825
821
  bug_tracker_uri: https://github.com/rubocop-hq/rubocop/issues
826
822
  post_install_message:
827
823
  rdoc_options: []
Binary file
@@ -1,261 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset='UTF-8' />
5
- <title>RuboCop Inspection Report</title>
6
- <%# TODO: Clean up the messy markup and style definitions. %>
7
- <style>
8
- * {
9
- -webkit-box-sizing: border-box;
10
- -moz-box-sizing: border-box;
11
- box-sizing: border-box;
12
- }
13
-
14
- body, html {
15
- font-size: 62.5%;
16
- }
17
- body {
18
- background-color: #ecedf0;
19
- font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
20
- margin: 0;
21
- }
22
- code {
23
- font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
24
- font-size: 85%;
25
- }
26
- #header {
27
- background: #f9f9f9;
28
- color: #333;
29
- border-bottom: 3px solid #ccc;
30
- height: 50px;
31
- padding: 0;
32
- }
33
- #header .logo {
34
- float: left;
35
- margin: 5px 12px 7px 20px;
36
- width: 38px;
37
- height: 38px;
38
- }
39
- #header .title {
40
- display: inline-block;
41
- float: left;
42
- height: 50px;
43
- font-size: 2.4rem;
44
- letter-spacing: normal;
45
- line-height: 50px;
46
- margin: 0;
47
- }
48
-
49
- .information, #offenses {
50
- width: 100%;
51
- padding: 20px;
52
- color: #333;
53
- }
54
- #offenses {
55
- padding: 0 20px;
56
- }
57
-
58
- .information .infobox {
59
- border-left: 3px solid;
60
- border-radius: 4px;
61
- background-color: #fff;
62
- -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
63
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
64
- padding: 15px;
65
- border-color: #0088cc;
66
- font-size: 1.4rem;
67
- }
68
- .information .infobox .info-title {
69
- font-size: 1.8rem;
70
- line-height: 2.2rem;
71
- margin: 0 0 0.5em;
72
- }
73
- .information .offenses-list li {
74
- line-height: 1.8rem
75
- }
76
- .information .offenses-list {
77
- padding-left: 20px;
78
- margin-bottom: 0;
79
- }
80
-
81
- #offenses .offense-box {
82
- border-radius: 4px;
83
- margin-bottom: 20px;
84
- background-color: #fff;
85
- -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
86
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
87
- }
88
- .fixed .box-title {
89
- position: fixed;
90
- top: 0;
91
- z-index: 10;
92
- width: 100%;
93
- }
94
- .box-title-placeholder {
95
- display: none;
96
- }
97
- .fixed .box-title-placeholder {
98
- display: block;
99
- }
100
- #offenses .offense-box .box-title h3, #offenses .offense-box .box-title-placeholder h3 {
101
- color: #33353f;
102
- background-color: #f6f6f6;
103
- font-size: 2rem;
104
- line-height: 2rem;
105
- display: block;
106
- padding: 15px;
107
- border-radius: 5px;
108
- margin: 0;
109
- }
110
- #offenses .offense-box .offense-reports {
111
- padding: 0 15px;
112
- }
113
- #offenses .offense-box .offense-reports .report {
114
- border-bottom: 1px dotted #ddd;
115
- padding: 15px 0px;
116
- position: relative;
117
- font-size: 1.3rem;
118
- }
119
- #offenses .offense-box .offense-reports .report:last-child {
120
- border-bottom: none;
121
- }
122
- #offenses .offense-box .offense-reports .report pre code {
123
- display: block;
124
- background: #000;
125
- color: #fff;
126
- padding: 10px 15px;
127
- border-radius: 5px;
128
- line-height: 1.6rem;
129
- }
130
- #offenses .offense-box .offense-reports .report .location {
131
- font-weight: bold;
132
- }
133
- #offenses .offense-box .offense-reports .report .message code {
134
- padding: 0.3em;
135
- background-color: rgba(0,0,0,0.07);
136
- border-radius: 3px;
137
- }
138
- .severity {
139
- text-transform: capitalize;
140
- font-weight: bold;
141
- }
142
- .highlight {
143
- padding: 2px;
144
- border-radius: 2px;
145
- font-weight: bold;
146
- }
147
- <%- SEVERITY_COLORS.each do |severity, color| %>
148
- .severity.<%= severity %> {
149
- color: <%= color %>;
150
- }
151
- .highlight.<%= severity %> {
152
- background-color: <%= color.fade_out(0.4) %>;
153
- border: 1px solid <%= color.fade_out(0.6) %>;
154
- }
155
- <%- end %>
156
- footer {
157
- margin-bottom: 20px;
158
- margin-right: 20px;
159
- font-size: 1.3rem;
160
- color: #777;
161
- text-align: right;
162
- }
163
- .extra-code {
164
- color: #ED9C28
165
- }
166
- </style>
167
-
168
- <script>
169
- (function() {
170
- // floating headers. requires classList support.
171
- if (!('classList' in document.createElement("_"))) return;
172
-
173
- var loaded = false,
174
- boxes,
175
- boxPositions;
176
-
177
- window.onload = function() {
178
- var scrollY = window.scrollY;
179
- boxes = document.querySelectorAll('.offense-box');
180
- boxPositions = [];
181
- for (var i = 0; i < boxes.length; i++)
182
- // need to add scrollY because the page might be somewhere other than the top when loaded.
183
- boxPositions[i] = boxes[i].getBoundingClientRect().top + scrollY;
184
- loaded = true;
185
- };
186
-
187
- window.onscroll = function() {
188
- if (!loaded) return;
189
- var i,
190
- idx,
191
- scrollY = window.scrollY;
192
- for (i = 0; i < boxPositions.length; i++) {
193
- if (scrollY <= boxPositions[i] - 1) {
194
- idx = i;
195
- break;
196
- }
197
- }
198
- if (typeof idx == 'undefined') idx = boxes.length;
199
- if (idx > 0)
200
- boxes[idx - 1].classList.add('fixed');
201
- for (i = 0; i < boxes.length; i++) {
202
- if (i < idx) continue;
203
- boxes[i].classList.remove('fixed');
204
- }
205
- };
206
- })();
207
- </script>
208
- </head>
209
- <body>
210
- <div id="header">
211
- <img class="logo" src="data:image/png;base64,<%= base64_encoded_logo_image %>" alt="">
212
- <h1 class="title">RuboCop Inspection Report</h1>
213
- </div>
214
- <div class="information">
215
- <div class="infobox">
216
- <div class="total">
217
- <%= pluralize(files.count, 'file') %> inspected,
218
- <%= pluralize(summary.offense_count, 'offense', no_for_zero: true) %> detected:
219
- </div>
220
- <ul class="offenses-list">
221
- <% files.each do |file| %>
222
- <% next if file.offenses.none? %>
223
- <li>
224
- <a href="#offense_<%= relative_path(file.path) %>">
225
- <%= relative_path(file.path) %> - <%= pluralize(file.offenses.count, 'offense') %>
226
- </a>
227
- </li>
228
- <% end %>
229
- </ul>
230
- </div>
231
- </div>
232
- <div id="offenses">
233
- <% files.each do |file| %>
234
- <% if file.offenses.any? %>
235
- <div class="offense-box" id="offense_<%= relative_path(file.path) %>">
236
- <div class="box-title-placeholder"><h3>&nbsp;</h3></div>
237
- <div class="box-title"><h3><%= relative_path(file.path) %> - <%= pluralize(file.offenses.count, 'offense') %></h3></div>
238
- <div class="offense-reports">
239
- <% file.offenses.each do |offense| %>
240
- <div class="report">
241
- <div class="meta">
242
- <span class="location">Line #<%= offense.location.line %></span> –
243
- <span class="severity <%= offense.severity %>"><%= offense.severity %>:</span>
244
- <span class="message"><%= decorated_message(offense) %></span>
245
- </div>
246
- <% unless offense.location.source_line.strip.empty? %>
247
- <pre><code><%= highlighted_source_line(offense) %></code></pre>
248
- <% end %>
249
- </div>
250
- <% end %>
251
- </div>
252
- </div>
253
- <% end %>
254
- <% end %>
255
- </div>
256
- <footer>
257
- Generated by <a href="https://github.com/rubocop-hq/rubocop">RuboCop</a>
258
- <span class="version"><%= RuboCop::Version::STRING %></span>
259
- </footer>
260
- </body>
261
- </html>
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'pry'
6
- require 'rubocop'
7
-
8
- ARGV.clear
9
-
10
- RuboCop.pry
@@ -1,32 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- if ARGV.include?('-h') || ARGV.include?('--help')
5
- puts "Usage: same as main `rubocop` command but gathers profiling info"
6
- puts "Additional option: `--memory` to print memory usage"
7
- exit(0)
8
- end
9
- with_mem = ARGV.delete('--memory')
10
- ARGV.unshift '--cache', 'false' unless ARGV.include?('--cache')
11
-
12
- require 'stackprof'
13
- if with_mem
14
- require 'memory_profiler'
15
- MemoryProfiler.start
16
- end
17
- StackProf.start
18
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
19
- begin
20
- load "#{__dir__}/../exe/rubocop"
21
- ensure
22
- delta = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
23
- puts "Finished in #{delta.round(1)} seconds"
24
- StackProf.stop
25
- if with_mem
26
- puts "Building memory report..."
27
- report = MemoryProfiler.stop
28
- end
29
- Dir.mkdir('tmp') unless File.exist?('tmp')
30
- StackProf.results('tmp/stackprof.dump')
31
- report&.pretty_print(scale_bytes: true)
32
- end
data/bin/setup DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- set -euo pipefail
4
- IFS=$'\n\t'
5
- set -vx
6
-
7
- bundle install