rubocop 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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