rubocop 1.0.0 → 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.
- checksums.yaml +4 -4
- data/README.md +36 -16
- data/config/default.yml +165 -19
- data/exe/rubocop +1 -1
- data/lib/rubocop.rb +17 -0
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/execute_runner.rb +26 -11
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config_loader.rb +14 -5
- data/lib/rubocop/config_regeneration.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +26 -6
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/commissioner.rb +10 -10
- data/lib/rubocop/cop/corrector.rb +3 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/force.rb +1 -1
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -3
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +4 -5
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
- data/lib/rubocop/cop/generator.rb +2 -9
- data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/class_structure.rb +15 -3
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +77 -7
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/line_length.rb +8 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_parens.rb +35 -13
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +26 -2
- data/lib/rubocop/cop/lint/debugger.rb +17 -28
- data/lib/rubocop/cop/lint/duplicate_branch.rb +93 -0
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +2 -12
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
- data/lib/rubocop/cop/lint/else_layout.rb +29 -3
- data/lib/rubocop/cop/lint/empty_block.rb +82 -0
- data/lib/rubocop/cop/lint/empty_class.rb +93 -0
- data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +39 -7
- data/lib/rubocop/cop/lint/loop.rb +4 -4
- data/lib/rubocop/cop/lint/missing_super.rb +7 -4
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +14 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +58 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +19 -16
- data/lib/rubocop/cop/lint/shadowed_exception.rb +4 -5
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +86 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +194 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_method_definition.rb +2 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +6 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -4
- data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +11 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +11 -5
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +67 -18
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
- data/lib/rubocop/cop/naming/variable_number.rb +98 -8
- data/lib/rubocop/cop/offense.rb +3 -3
- data/lib/rubocop/cop/style/and_or.rb +1 -3
- data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +0 -4
- data/lib/rubocop/cop/style/case_like_if.rb +0 -4
- data/lib/rubocop/cop/style/collection_compact.rb +91 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +169 -0
- data/lib/rubocop/cop/style/documentation.rb +12 -1
- data/lib/rubocop/cop/style/double_negation.rb +6 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +7 -2
- data/lib/rubocop/cop/style/if_inside_else.rb +37 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +7 -3
- data/lib/rubocop/cop/style/infinite_loop.rb +4 -0
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/mixin_grouping.rb +0 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +55 -7
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +106 -0
- data/lib/rubocop/cop/style/nil_lambda.rb +52 -0
- data/lib/rubocop/cop/style/raise_args.rb +21 -6
- data/lib/rubocop/cop/style/redundant_argument.rb +73 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +3 -0
- data/lib/rubocop/cop/style/static_class.rb +97 -0
- data/lib/rubocop/cop/style/swap_values.rb +108 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +9 -0
- data/lib/rubocop/cop/team.rb +6 -1
- data/lib/rubocop/cop/util.rb +6 -2
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/ext/regexp_node.rb +17 -9
- data/lib/rubocop/ext/regexp_parser.rb +84 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
- data/lib/rubocop/formatter/formatter_set.rb +2 -1
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +47 -0
- data/lib/rubocop/magic_comment.rb +2 -2
- data/lib/rubocop/options.rb +7 -0
- data/lib/rubocop/rake_task.rb +2 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +65 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +22 -10
- data/assets/logo.png +0 -0
- data/assets/output.html.erb +0 -261
- data/bin/console +0 -10
- data/bin/rubocop-profile +0 -32
- data/bin/setup +0 -7
data/lib/rubocop/cop/team.rb
CHANGED
@@ -99,7 +99,12 @@ module RuboCop
|
|
99
99
|
def self.forces_for(cops)
|
100
100
|
needed = Hash.new { |h, k| h[k] = [] }
|
101
101
|
cops.each do |cop|
|
102
|
-
|
102
|
+
forces = cop.class.joining_forces
|
103
|
+
if forces.is_a?(Array)
|
104
|
+
forces.each { |force| needed[force] << cop }
|
105
|
+
elsif forces
|
106
|
+
needed[forces] << cop
|
107
|
+
end
|
103
108
|
end
|
104
109
|
|
105
110
|
needed.map do |force_class, joining_cops|
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -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
|
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)
|
@@ -62,7 +62,7 @@ module RuboCop
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def begins_its_line?(range)
|
65
|
-
|
65
|
+
range.source_line.index(/\S/) == range.column
|
66
66
|
end
|
67
67
|
|
68
68
|
# Returns, for example, a bare `if` node if the given node is an `if`
|
@@ -123,6 +123,10 @@ module RuboCop
|
|
123
123
|
node1.loc.line == node2.loc.line
|
124
124
|
end
|
125
125
|
|
126
|
+
def indent(node)
|
127
|
+
' ' * node.loc.column
|
128
|
+
end
|
129
|
+
|
126
130
|
def to_supported_styles(enforced_style)
|
127
131
|
enforced_style
|
128
132
|
.sub(/^Enforced/, 'Supported')
|
@@ -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
|
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)
|
@@ -10,18 +10,26 @@ module RuboCop
|
|
10
10
|
end
|
11
11
|
private_constant :ANY
|
12
12
|
|
13
|
-
class << self
|
14
|
-
attr_reader :parsed_cache
|
15
|
-
end
|
16
|
-
@parsed_cache = {}
|
17
|
-
|
18
13
|
# @return [Regexp::Expression::Root, nil]
|
19
|
-
|
14
|
+
# Note: we extend Regexp nodes to provide `loc` and `expression`
|
15
|
+
# see `ext/regexp_parser`.
|
16
|
+
attr_reader :parsed_tree
|
17
|
+
|
18
|
+
def assign_properties(*)
|
19
|
+
super
|
20
|
+
|
20
21
|
str = with_interpolations_blanked
|
21
|
-
|
22
|
-
Regexp::Parser.parse(str, options: options)
|
22
|
+
begin
|
23
|
+
@parsed_tree = Regexp::Parser.parse(str, options: options)
|
23
24
|
rescue StandardError
|
24
|
-
nil
|
25
|
+
@parsed_tree = nil
|
26
|
+
else
|
27
|
+
origin = loc.begin.end
|
28
|
+
source = @parsed_tree.to_s
|
29
|
+
@parsed_tree.each_expression(true) do |e|
|
30
|
+
e.origin = origin
|
31
|
+
e.source = source
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
27
35
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Ext
|
5
|
+
# Extensions for `regexp_parser` gem
|
6
|
+
module RegexpParser
|
7
|
+
# Source map for RegexpParser nodes
|
8
|
+
class Map < ::Parser::Source::Map
|
9
|
+
attr_reader :body, :quantifier, :begin, :end
|
10
|
+
|
11
|
+
def initialize(expression, body:, quantifier: nil, begin_l: nil, end_l: nil)
|
12
|
+
@begin = begin_l
|
13
|
+
@end = end_l
|
14
|
+
@body = body
|
15
|
+
@quantifier = quantifier
|
16
|
+
super(expression)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Expression
|
21
|
+
# Add `expression` and `loc` to all `regexp_parser` nodes
|
22
|
+
module Base
|
23
|
+
attr_accessor :origin, :source
|
24
|
+
|
25
|
+
def start_index
|
26
|
+
# ts is a byte index; convert it to a character index
|
27
|
+
@start_index ||= source.byteslice(0, ts).length
|
28
|
+
end
|
29
|
+
|
30
|
+
# Shortcut to `loc.expression`
|
31
|
+
def expression
|
32
|
+
@expression ||= begin
|
33
|
+
origin.adjust(begin_pos: start_index, end_pos: start_index + full_length)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @returns a location map like `parser` does, with:
|
38
|
+
# - expression: complete expression
|
39
|
+
# - quantifier: for `+`, `{1,2}`, etc.
|
40
|
+
# - begin/end: for `[` and `]` (only CharacterSet for now)
|
41
|
+
#
|
42
|
+
# E.g.
|
43
|
+
# [a-z]{2,}
|
44
|
+
# ^^^^^^^^^ expression
|
45
|
+
# ^^^^ quantifier
|
46
|
+
# ^^^^^ body
|
47
|
+
# ^ begin
|
48
|
+
# ^ end
|
49
|
+
#
|
50
|
+
# Please open issue if you need other locations
|
51
|
+
def loc
|
52
|
+
@loc ||= begin
|
53
|
+
Map.new(expression, **build_location)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def build_location
|
60
|
+
return { body: expression } unless (q = quantifier)
|
61
|
+
|
62
|
+
body = expression.adjust(end_pos: -q.text.length)
|
63
|
+
q_loc = expression.with(begin_pos: body.end_pos)
|
64
|
+
{ body: body, quantifier: q_loc }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Provide `CharacterSet` with `begin` and `end` locations.
|
69
|
+
module CharacterSet
|
70
|
+
def build_location
|
71
|
+
h = super
|
72
|
+
body = h[:body]
|
73
|
+
h.merge!(
|
74
|
+
begin_l: body.with(end_pos: body.begin_pos + 1),
|
75
|
+
end_l: body.with(begin_pos: body.end_pos - 1)
|
76
|
+
)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
::Regexp::Expression::Base.include Expression::Base
|
81
|
+
::Regexp::Expression::CharacterSet.include Expression::CharacterSet
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -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
|
-
#
|
200
|
-
#
|
201
|
-
#
|
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
|
-
(
|
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)
|
@@ -14,6 +14,7 @@ module RuboCop
|
|
14
14
|
'[e]macs' => EmacsStyleFormatter,
|
15
15
|
'[fi]les' => FileListFormatter,
|
16
16
|
'[fu]ubar' => FuubarStyleFormatter,
|
17
|
+
'[g]ithub' => GitHubActionsFormatter,
|
17
18
|
'[h]tml' => HTMLFormatter,
|
18
19
|
'[j]son' => JSONFormatter,
|
19
20
|
'[ju]nit' => JUnitFormatter,
|
@@ -30,7 +31,7 @@ module RuboCop
|
|
30
31
|
|
31
32
|
FORMATTER_APIS.each do |method_name|
|
32
33
|
define_method(method_name) do |*args|
|
33
|
-
each { |f| f.
|
34
|
+
each { |f| f.public_send(method_name, *args) }
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Formatter
|
5
|
+
# This formatter formats report data as GitHub Workflow commands resulting
|
6
|
+
# in GitHub check annotations when run within GitHub Actions.
|
7
|
+
class GitHubActionsFormatter < BaseFormatter
|
8
|
+
ESCAPE_MAP = {
|
9
|
+
'%' => '%25',
|
10
|
+
"\n" => '%0A',
|
11
|
+
"\r" => '%0D'
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def file_finished(file, offenses)
|
15
|
+
offenses.each { |offense| report_offense(file, offense) }
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def github_escape(string)
|
21
|
+
string.gsub(Regexp.union(ESCAPE_MAP.keys), ESCAPE_MAP)
|
22
|
+
end
|
23
|
+
|
24
|
+
def minimum_severity_to_fail
|
25
|
+
@minimum_severity_to_fail ||= begin
|
26
|
+
name = options.fetch(:fail_level, :refactor)
|
27
|
+
RuboCop::Cop::Severity.new(name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def github_severity(offense)
|
32
|
+
offense.severity < minimum_severity_to_fail ? 'warning' : 'error'
|
33
|
+
end
|
34
|
+
|
35
|
+
def report_offense(file, offense)
|
36
|
+
output.printf(
|
37
|
+
"\n::%<severity>s file=%<file>s,line=%<line>d,col=%<column>d::%<message>s\n",
|
38
|
+
severity: github_severity(offense),
|
39
|
+
file: file,
|
40
|
+
line: offense.line,
|
41
|
+
column: offense.real_column,
|
42
|
+
message: github_escape(offense.message)
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -194,7 +194,7 @@ module RuboCop
|
|
194
194
|
class SimpleComment < MagicComment
|
195
195
|
# Match `encoding` or `coding`
|
196
196
|
def encoding
|
197
|
-
extract(/\A\s*\#.*\b(?:en)?coding: (#{TOKEN})/
|
197
|
+
extract(/\A\s*\#.*\b(?:en)?coding: (#{TOKEN})/io)
|
198
198
|
end
|
199
199
|
|
200
200
|
private
|
@@ -207,7 +207,7 @@ module RuboCop
|
|
207
207
|
# Case-insensitive and dashes/underscores are acceptable.
|
208
208
|
# @see https://git.io/vM7Mg
|
209
209
|
def extract_frozen_string_literal
|
210
|
-
extract(/\A\s*#\s*frozen[_-]string[_-]literal:\s*(#{TOKEN})\s*\z/
|
210
|
+
extract(/\A\s*#\s*frozen[_-]string[_-]literal:\s*(#{TOKEN})\s*\z/io)
|
211
211
|
end
|
212
212
|
end
|
213
213
|
end
|
data/lib/rubocop/options.rb
CHANGED
@@ -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.
|
@@ -145,6 +146,7 @@ module RuboCop
|
|
145
146
|
end
|
146
147
|
end
|
147
148
|
|
149
|
+
option(opts, '--display-time')
|
148
150
|
option(opts, '--display-only-failed')
|
149
151
|
end
|
150
152
|
|
@@ -194,6 +196,7 @@ module RuboCop
|
|
194
196
|
|
195
197
|
option(opts, '--safe')
|
196
198
|
|
199
|
+
option(opts, '--stderr')
|
197
200
|
option(opts, '--[no-]color')
|
198
201
|
|
199
202
|
option(opts, '-v', '--version')
|
@@ -469,6 +472,7 @@ module RuboCop
|
|
469
472
|
'if no format is specified.'],
|
470
473
|
fail_level: ['Minimum severity (A/R/C/W/E/F) for exit',
|
471
474
|
'with error code.'],
|
475
|
+
display_time: 'Display elapsed time in seconds.',
|
472
476
|
display_only_failed: ['Only output offense messages. Omit passing',
|
473
477
|
'cops. Only valid for --format junit.'],
|
474
478
|
display_only_fail_level_offenses:
|
@@ -496,6 +500,9 @@ module RuboCop
|
|
496
500
|
extra_details: 'Display extra details in offense messages.',
|
497
501
|
lint: 'Run only lint cops.',
|
498
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.'],
|
499
506
|
list_target_files: 'List all files RuboCop will inspect.',
|
500
507
|
auto_correct: 'Auto-correct offenses (only when it\'s safe).',
|
501
508
|
safe_auto_correct: '(same, deprecated)',
|
data/lib/rubocop/rake_task.rb
CHANGED
@@ -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
|
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
|
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)
|
data/lib/rubocop/runner.rb
CHANGED
@@ -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
|
67
|
+
Parallel.each(target_files) { |target_file| file_offenses(target_file) }
|
68
68
|
end
|
69
69
|
|
70
70
|
def find_target_files(paths)
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def wanted_dir_patterns(base_dir, exclude_pattern, flags)
|
97
|
-
dirs = Dir.glob(File.join(base_dir, '*/'), flags)
|
97
|
+
dirs = Dir.glob(File.join(base_dir.gsub('/**/', '/\**/'), '*/'), flags)
|
98
98
|
.reject do |dir|
|
99
99
|
dir.end_with?('/./', '/../') || File.fnmatch?(exclude_pattern, dir, flags)
|
100
100
|
end
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -112,6 +112,70 @@ module RuboCop
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
+
# The target ruby version may be found in a .gemspec file.
|
116
|
+
# @api private
|
117
|
+
class GemspecFile < Source
|
118
|
+
extend NodePattern::Macros
|
119
|
+
|
120
|
+
GEMSPEC_EXTENSION = '.gemspec'
|
121
|
+
|
122
|
+
def_node_search :required_ruby_version, <<~PATTERN
|
123
|
+
(send _ :required_ruby_version= $_)
|
124
|
+
PATTERN
|
125
|
+
|
126
|
+
def_node_matcher :gem_requirement?, <<~PATTERN
|
127
|
+
(send (const(const _ :Gem):Requirement) :new $str)
|
128
|
+
PATTERN
|
129
|
+
|
130
|
+
def name
|
131
|
+
"`required_ruby_version` parameter (in #{gemspec_filename})"
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def find_version
|
137
|
+
file = gemspec_filepath
|
138
|
+
return unless file && File.file?(file)
|
139
|
+
|
140
|
+
version = version_from_gemspec_file(file)
|
141
|
+
return if version.nil?
|
142
|
+
|
143
|
+
requirement = version.children.last
|
144
|
+
return version_from_array(version) if version.array_type?
|
145
|
+
return version_from_array(requirement) if gem_requirement? version
|
146
|
+
|
147
|
+
version_from_str(version.str_content)
|
148
|
+
end
|
149
|
+
|
150
|
+
def gemspec_filename
|
151
|
+
@gemspec_filename ||= begin
|
152
|
+
basename = Pathname.new(@config.base_dir_for_path_parameters).basename.to_s
|
153
|
+
"#{basename}#{GEMSPEC_EXTENSION}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def gemspec_filepath
|
158
|
+
@gemspec_filepath ||=
|
159
|
+
@config.find_file_upwards(gemspec_filename, @config.base_dir_for_path_parameters)
|
160
|
+
end
|
161
|
+
|
162
|
+
def version_from_gemspec_file(file)
|
163
|
+
processed_source = ProcessedSource.from_file(file, DEFAULT_VERSION)
|
164
|
+
required_ruby_version(processed_source.ast).first
|
165
|
+
end
|
166
|
+
|
167
|
+
def version_from_array(array)
|
168
|
+
versions = array.children.map { |v| version_from_str(v.is_a?(String) ? v : v.str_content) }
|
169
|
+
versions.compact.min
|
170
|
+
end
|
171
|
+
|
172
|
+
def version_from_str(str)
|
173
|
+
str.match(/^(?:>=|<=)?\s*(?<version>\d+(?:\.\d+)*)/) do |md|
|
174
|
+
md[:version].to_f
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
115
179
|
# If all else fails, a default version will be picked.
|
116
180
|
# @api private
|
117
181
|
class Default < Source
|
@@ -130,7 +194,7 @@ module RuboCop
|
|
130
194
|
KNOWN_RUBIES
|
131
195
|
end
|
132
196
|
|
133
|
-
SOURCES = [RuboCopConfig, RubyVersionFile, BundlerLockFile, Default].freeze
|
197
|
+
SOURCES = [RuboCopConfig, RubyVersionFile, BundlerLockFile, GemspecFile, Default].freeze
|
134
198
|
private_constant :SOURCES
|
135
199
|
|
136
200
|
def initialize(config)
|