rubocop 0.78.0 → 0.82.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +4 -4
- data/config/default.yml +158 -48
- data/lib/rubocop.rb +19 -4
- data/lib/rubocop/ast/builder.rb +45 -42
- data/lib/rubocop/ast/node.rb +12 -19
- data/lib/rubocop/ast/node/array_node.rb +13 -0
- data/lib/rubocop/ast/node/block_node.rb +5 -1
- data/lib/rubocop/ast/node/case_match_node.rb +56 -0
- data/lib/rubocop/ast/node/def_node.rb +11 -0
- data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +8 -0
- data/lib/rubocop/ast/node/regexp_node.rb +2 -4
- data/lib/rubocop/ast/traversal.rb +29 -10
- data/lib/rubocop/cli.rb +10 -4
- data/lib/rubocop/cli/command/show_cops.rb +11 -4
- data/lib/rubocop/comment_config.rb +6 -1
- data/lib/rubocop/config.rb +36 -10
- data/lib/rubocop/config_loader.rb +42 -33
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/config_obsoletion.rb +4 -1
- data/lib/rubocop/config_validator.rb +66 -92
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -3
- data/lib/rubocop/cop/badge.rb +5 -5
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -1
- data/lib/rubocop/cop/corrector.rb +48 -24
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -2
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/string_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/generator.rb +3 -4
- data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/array_alignment.rb +53 -10
- data/lib/rubocop/cop/layout/block_end_newline.rb +5 -3
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +8 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/layout/end_of_line.rb +2 -2
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +16 -10
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +8 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/{tab.rb → indentation_style.rb} +48 -6
- data/lib/rubocop/cop/layout/leading_comment_space.rb +34 -3
- data/lib/rubocop/cop/layout/line_length.rb +32 -3
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +15 -6
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +0 -4
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +3 -3
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +133 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +19 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -2
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +8 -0
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -9
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +2 -2
- data/lib/rubocop/cop/lint/boolean_symbol.rb +12 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -2
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/inherit_exception.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/loop.rb +6 -4
- data/lib/rubocop/cop/lint/multiple_comparison.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +2 -2
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +2 -2
- data/lib/rubocop/cop/lint/raise_exception.rb +75 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +12 -7
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +58 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +12 -22
- data/lib/rubocop/cop/lint/unified_integer.rb +0 -2
- data/lib/rubocop/cop/lint/unused_method_argument.rb +32 -6
- data/lib/rubocop/cop/lint/uri_regexp.rb +4 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -0
- data/lib/rubocop/cop/migration/department_name.rb +47 -6
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +4 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +6 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +7 -7
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +171 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -0
- data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -3
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -10
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +30 -0
- data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/registry.rb +15 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -6
- data/lib/rubocop/cop/style/alias.rb +4 -4
- data/lib/rubocop/cop/style/and_or.rb +5 -6
- data/lib/rubocop/cop/style/array_join.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +60 -1
- data/lib/rubocop/cop/style/case_equality.rb +24 -1
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -8
- data/lib/rubocop/cop/style/copyright.rb +1 -1
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -0
- data/lib/rubocop/cop/style/documentation.rb +43 -5
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +3 -3
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/end_block.rb +6 -0
- data/lib/rubocop/cop/style/even_odd.rb +1 -1
- data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -3
- data/lib/rubocop/cop/style/exponential_notation.rb +119 -0
- data/lib/rubocop/cop/style/format_string.rb +2 -2
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +89 -11
- data/lib/rubocop/cop/style/hash_each_methods.rb +89 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -5
- data/lib/rubocop/cop/style/hash_transform_keys.rb +83 -0
- data/lib/rubocop/cop/style/hash_transform_values.rb +80 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +9 -5
- data/lib/rubocop/cop/style/lambda.rb +3 -2
- data/lib/rubocop/cop/style/lambda_call.rb +2 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -205
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +169 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/module_function.rb +58 -12
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +1 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +5 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +2 -4
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -4
- data/lib/rubocop/cop/style/next.rb +2 -2
- data/lib/rubocop/cop/style/nil_comparison.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +4 -4
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +5 -4
- data/lib/rubocop/cop/style/one_line_conditional.rb +4 -3
- data/lib/rubocop/cop/style/or_assignment.rb +4 -3
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +2 -2
- data/lib/rubocop/cop/style/proc.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +18 -6
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +3 -3
- data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -2
- data/lib/rubocop/cop/style/redundant_return.rb +5 -7
- data/lib/rubocop/cop/style/redundant_self.rb +1 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -4
- data/lib/rubocop/cop/style/string_hash_keys.rb +1 -1
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/style/symbol_literal.rb +2 -2
- data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +35 -22
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +41 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +88 -0
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +44 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unpack_first.rb +0 -4
- data/lib/rubocop/cop/style/variable_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +4 -1
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +74 -0
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/node_pattern.rb +96 -10
- data/lib/rubocop/options.rb +7 -1
- data/lib/rubocop/processed_source.rb +1 -4
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +5 -4
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/target_ruby.rb +151 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +39 -12
- data/lib/rubocop/cop/lint/end_in_method.rb +0 -40
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +0 -209
- data/lib/rubocop/formatter/disabled_lines_formatter.rb +0 -57
@@ -190,7 +190,10 @@ module RuboCop
|
|
190
190
|
end
|
191
191
|
|
192
192
|
def regexp_captured_names(node)
|
193
|
-
regexp_string = node.children
|
193
|
+
regexp_string = node.children.select(&:str_type?).map do |child|
|
194
|
+
child.children.first
|
195
|
+
end.join || ''
|
196
|
+
|
194
197
|
regexp = Regexp.new(regexp_string)
|
195
198
|
|
196
199
|
regexp.named_captures.keys
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
|
30
30
|
report_line(offense.location)
|
31
31
|
report_highlighted_area(offense.highlighted_area)
|
32
|
-
rescue IndexError
|
32
|
+
rescue IndexError
|
33
33
|
# range is not on a valid line; perhaps the source file is empty
|
34
34
|
end
|
35
35
|
end
|
@@ -11,12 +11,12 @@ module RuboCop
|
|
11
11
|
BUILTIN_FORMATTERS_FOR_KEYS = {
|
12
12
|
'[a]utogenconf' => AutoGenConfigFormatter,
|
13
13
|
'[c]lang' => ClangStyleFormatter,
|
14
|
-
'[d]isabled' => DisabledLinesFormatter,
|
15
14
|
'[e]macs' => EmacsStyleFormatter,
|
16
15
|
'[fi]les' => FileListFormatter,
|
17
16
|
'[fu]ubar' => FuubarStyleFormatter,
|
18
17
|
'[h]tml' => HTMLFormatter,
|
19
18
|
'[j]son' => JSONFormatter,
|
19
|
+
'[ju]nit' => JUnitFormatter,
|
20
20
|
'[o]ffenses' => OffenseCountFormatter,
|
21
21
|
'[pa]cman' => PacmanFormatter,
|
22
22
|
'[p]rogress' => ProgressFormatter,
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
#
|
6
|
+
# This code is based on https://github.com/mikian/rubocop-junit-formatter.
|
7
|
+
#
|
8
|
+
# Copyright (c) 2015 Mikko Kokkonen
|
9
|
+
#
|
10
|
+
# MIT License
|
11
|
+
#
|
12
|
+
# https://github.com/mikian/rubocop-junit-formatter/blob/master/LICENSE.txt
|
13
|
+
#
|
14
|
+
module RuboCop
|
15
|
+
module Formatter
|
16
|
+
# This formatter formats the report data in JUnit format.
|
17
|
+
class JUnitFormatter < BaseFormatter
|
18
|
+
def initialize(output, options = {})
|
19
|
+
super
|
20
|
+
|
21
|
+
@document = REXML::Document.new.tap do |document|
|
22
|
+
document << REXML::XMLDecl.new
|
23
|
+
end
|
24
|
+
testsuites = REXML::Element.new('testsuites', @document)
|
25
|
+
testsuite = REXML::Element.new('testsuite', testsuites)
|
26
|
+
@testsuite = testsuite.tap do |element|
|
27
|
+
element.add_attributes('name' => 'rubocop')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def file_finished(file, offenses)
|
32
|
+
# TODO: Returns all cops with the same behavior as
|
33
|
+
# the original rubocop-junit-formatter.
|
34
|
+
# https://github.com/mikian/rubocop-junit-formatter/blob/v0.1.4/lib/rubocop/formatter/junit_formatter.rb#L9
|
35
|
+
#
|
36
|
+
# In the future, it would be preferable to return only enabled cops.
|
37
|
+
Cop::Cop.all.each do |cop|
|
38
|
+
REXML::Element.new('testcase', @testsuite).tap do |testcase|
|
39
|
+
testcase.attributes['classname'] = classname_attribute_value(file)
|
40
|
+
testcase.attributes['name'] = cop.cop_name
|
41
|
+
|
42
|
+
target_offenses = offenses.select do |offense|
|
43
|
+
offense.cop_name == cop.cop_name
|
44
|
+
end
|
45
|
+
|
46
|
+
add_failure_to(testcase, target_offenses, cop.cop_name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def classname_attribute_value(file)
|
52
|
+
file.gsub(/\.rb\Z/, '').gsub("#{Dir.pwd}/", '').tr('/', '.')
|
53
|
+
end
|
54
|
+
|
55
|
+
def finished(_inspected_files)
|
56
|
+
@document.write(output, 2)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def add_failure_to(testcase, offenses, cop_name)
|
62
|
+
# One failure per offense. Zero failures is a passing test case,
|
63
|
+
# for most surefire/nUnit parsers.
|
64
|
+
offenses.each do |offense|
|
65
|
+
REXML::Element.new('failure', testcase).tap do |failure|
|
66
|
+
failure.attributes['type'] = cop_name
|
67
|
+
failure.attributes['message'] = offense.message
|
68
|
+
failure.add_text(offense.location.to_s)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
69
69
|
regex = /#{Regexp.quote(PACMAN)}|#{Regexp.quote(PACDOT)}/
|
70
70
|
@progress_line = @progress_line.sub(regex, character)
|
71
71
|
output.printf("%<line>s\r", line: @progress_line)
|
72
|
-
return unless @progress_line[-1]
|
72
|
+
return unless /ᗣ|\./.match?(@progress_line[-1])
|
73
73
|
|
74
74
|
@repetitions += 1
|
75
75
|
output.puts
|
@@ -56,7 +56,7 @@ module RuboCop
|
|
56
56
|
|
57
57
|
report_line(offense.location)
|
58
58
|
report_highlighted_area(offense.highlighted_area)
|
59
|
-
rescue IndexError
|
59
|
+
rescue IndexError
|
60
60
|
# range is not on a valid line; perhaps the source file is empty
|
61
61
|
end
|
62
62
|
end
|
data/lib/rubocop/node_pattern.rb
CHANGED
@@ -78,6 +78,8 @@ module RuboCop
|
|
78
78
|
# # matching process starts
|
79
79
|
# '^^send' # each ^ ascends one level in the AST
|
80
80
|
# # so this matches against the grandparent node
|
81
|
+
# '`send' # descends any number of level in the AST
|
82
|
+
# # so this matches against any descendant node
|
81
83
|
# '#method' # we call this a 'funcall'; it calls a method in the
|
82
84
|
# # context where a pattern-matching method is defined
|
83
85
|
# # if that returns a truthy value, the match succeeds
|
@@ -112,7 +114,7 @@ module RuboCop
|
|
112
114
|
SYMBOL = %r{:(?:[\w+@*/?!<>=~|%^-]+|\[\]=?)}.freeze
|
113
115
|
IDENTIFIER = /[a-zA-Z_][a-zA-Z0-9_-]*/.freeze
|
114
116
|
META = Regexp.union(
|
115
|
-
%w"( ) { } [ ] $< < > $... $ ! ^ ... + * ?"
|
117
|
+
%w"( ) { } [ ] $< < > $... $ ! ^ ` ... + * ?"
|
116
118
|
).freeze
|
117
119
|
NUMBER = /-?\d+(?:\.\d+)?/.freeze
|
118
120
|
STRING = /".+?"/.freeze
|
@@ -188,7 +190,7 @@ module RuboCop
|
|
188
190
|
|
189
191
|
@temps = 0 # avoid name clashes between temp variables
|
190
192
|
@captures = 0 # number of captures seen
|
191
|
-
@unify = {} # named wildcard -> temp variable
|
193
|
+
@unify = {} # named wildcard -> temp variable
|
192
194
|
@params = 0 # highest % (param) number seen
|
193
195
|
run(node_var)
|
194
196
|
end
|
@@ -223,6 +225,7 @@ module RuboCop
|
|
223
225
|
when '!' then compile_negation
|
224
226
|
when '$' then compile_capture
|
225
227
|
when '^' then compile_ascend
|
228
|
+
when '`' then compile_descend
|
226
229
|
when WILDCARD then compile_wildcard(token[1..-1])
|
227
230
|
when FUNCALL then compile_funcall(token)
|
228
231
|
when LITERAL then compile_literal(token)
|
@@ -466,12 +469,67 @@ module RuboCop
|
|
466
469
|
end
|
467
470
|
end
|
468
471
|
|
472
|
+
def access_unify(name)
|
473
|
+
var = @unify[name]
|
474
|
+
|
475
|
+
if var == :forbidden_unification
|
476
|
+
fail_due_to "Wildcard #{name} was first seen in a subset of a" \
|
477
|
+
" union and can't be used outside that union"
|
478
|
+
end
|
479
|
+
var
|
480
|
+
end
|
481
|
+
|
482
|
+
def forbid_unification(*names)
|
483
|
+
names.each do |name|
|
484
|
+
@unify[name] = :forbidden_unification
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
489
|
+
def unify_in_union(enum)
|
490
|
+
# We need to reset @unify before each branch is processed.
|
491
|
+
# Moreover we need to keep track of newly encountered wildcards.
|
492
|
+
# Var `new_unify_intersection` will hold those that are encountered
|
493
|
+
# in all branches; these are not a problem.
|
494
|
+
# Var `partial_unify` will hold those encountered in only a subset
|
495
|
+
# of the branches; these can't be used outside of the union.
|
496
|
+
|
497
|
+
return to_enum __method__, enum unless block_given?
|
498
|
+
|
499
|
+
new_unify_intersection = nil
|
500
|
+
partial_unify = []
|
501
|
+
unify_before = @unify.dup
|
502
|
+
|
503
|
+
result = enum.each do |e|
|
504
|
+
@unify = unify_before.dup if new_unify_intersection
|
505
|
+
yield e
|
506
|
+
new_unify = @unify.keys - unify_before.keys
|
507
|
+
if new_unify_intersection.nil?
|
508
|
+
# First iteration
|
509
|
+
new_unify_intersection = new_unify
|
510
|
+
else
|
511
|
+
union = new_unify_intersection | new_unify
|
512
|
+
new_unify_intersection &= new_unify
|
513
|
+
partial_unify |= union - new_unify_intersection
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
# At this point, all members of `new_unify_intersection` can be used
|
518
|
+
# for unification outside of the union, but partial_unify may not
|
519
|
+
|
520
|
+
forbid_unification(*partial_unify)
|
521
|
+
|
522
|
+
result
|
523
|
+
end
|
524
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
525
|
+
|
469
526
|
def compile_union
|
470
527
|
# we need to ensure that each branch of the {} contains the same
|
471
528
|
# number of captures (since only one branch of the {} can actually
|
472
529
|
# match, the same variables are used to hold the captures for each
|
473
530
|
# branch)
|
474
531
|
enum = tokens_until('}', 'union')
|
532
|
+
enum = unify_in_union(enum)
|
475
533
|
terms = insure_same_captures(enum, 'branch of {}')
|
476
534
|
.map { compile_expr }
|
477
535
|
|
@@ -496,6 +554,19 @@ module RuboCop
|
|
496
554
|
with_context("#{CUR_NODE} && #{compile_expr}", "#{CUR_NODE}.parent")
|
497
555
|
end
|
498
556
|
|
557
|
+
def compile_descend
|
558
|
+
with_temp_variables do |descendant|
|
559
|
+
pattern = with_context(compile_expr, descendant,
|
560
|
+
use_temp_node: false)
|
561
|
+
[
|
562
|
+
"RuboCop::NodePattern.descend(#{CUR_ELEMENT}).",
|
563
|
+
"any? do |#{descendant}|",
|
564
|
+
" #{pattern}",
|
565
|
+
'end'
|
566
|
+
].join("\n")
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
499
570
|
def compile_wildcard(name)
|
500
571
|
if name.empty?
|
501
572
|
'true'
|
@@ -503,12 +574,12 @@ module RuboCop
|
|
503
574
|
# we have already seen a wildcard with this name before
|
504
575
|
# so the value it matched the first time will already be stored
|
505
576
|
# in a temp. check if this value matches the one stored in the temp
|
506
|
-
"#{CUR_ELEMENT} ==
|
577
|
+
"#{CUR_ELEMENT} == #{access_unify(name)}"
|
507
578
|
else
|
508
|
-
n = @unify[name] =
|
509
|
-
# double assign to
|
510
|
-
"(
|
511
|
-
"
|
579
|
+
n = @unify[name] = "unify_#{name.gsub('-', '__')}"
|
580
|
+
# double assign to avoid "assigned but unused variable"
|
581
|
+
"(#{n} = #{CUR_ELEMENT}; " \
|
582
|
+
"#{n} = #{n}; true)"
|
512
583
|
end
|
513
584
|
end
|
514
585
|
|
@@ -560,9 +631,8 @@ module RuboCop
|
|
560
631
|
def compile_arg(token)
|
561
632
|
case token
|
562
633
|
when WILDCARD then
|
563
|
-
name
|
564
|
-
|
565
|
-
"temp#{number}"
|
634
|
+
name = token[1..-1]
|
635
|
+
access_unify(name) || fail_due_to('invalid in arglist: ' + token)
|
566
636
|
when LITERAL then token
|
567
637
|
when PARAM then get_param(token[1..-1])
|
568
638
|
when CLOSING then fail_due_to("#{token} in invalid position")
|
@@ -796,6 +866,22 @@ module RuboCop
|
|
796
866
|
def to_s
|
797
867
|
"#<#{self.class} #{pattern}>"
|
798
868
|
end
|
869
|
+
|
870
|
+
# Yields its argument and any descendants, depth-first.
|
871
|
+
#
|
872
|
+
def self.descend(element, &block)
|
873
|
+
return to_enum(__method__, element) unless block_given?
|
874
|
+
|
875
|
+
yield element
|
876
|
+
|
877
|
+
if element.is_a?(::RuboCop::AST::Node)
|
878
|
+
element.children.each do |child|
|
879
|
+
descend(child, &block)
|
880
|
+
end
|
881
|
+
end
|
882
|
+
|
883
|
+
nil
|
884
|
+
end
|
799
885
|
end
|
800
886
|
end
|
801
887
|
# rubocop:enable Metrics/ClassLength, Metrics/CyclomaticComplexity
|
data/lib/rubocop/options.rb
CHANGED
@@ -154,6 +154,7 @@ module RuboCop
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
|
+
# rubocop:disable Metrics/MethodLength
|
157
158
|
def add_boolean_flags(opts)
|
158
159
|
option(opts, '-F', '--fail-fast')
|
159
160
|
option(opts, '-C', '--cache FLAG')
|
@@ -162,6 +163,8 @@ module RuboCop
|
|
162
163
|
option(opts, '-E', '--extra-details')
|
163
164
|
option(opts, '-S', '--display-style-guide')
|
164
165
|
option(opts, '-a', '--auto-correct')
|
166
|
+
option(opts, '--disable-pending-cops')
|
167
|
+
option(opts, '--enable-pending-cops')
|
165
168
|
option(opts, '--ignore-disable-comments')
|
166
169
|
|
167
170
|
option(opts, '--safe')
|
@@ -172,6 +175,7 @@ module RuboCop
|
|
172
175
|
option(opts, '-V', '--verbose-version')
|
173
176
|
option(opts, '-P', '--parallel')
|
174
177
|
end
|
178
|
+
# rubocop:enable Metrics/MethodLength
|
175
179
|
|
176
180
|
def add_aliases(opts)
|
177
181
|
option(opts, '-l', '--lint') do
|
@@ -362,7 +366,7 @@ module RuboCop
|
|
362
366
|
end
|
363
367
|
|
364
368
|
def validate_exclude_limit_option
|
365
|
-
return if @options[:exclude_limit]
|
369
|
+
return if /^\d+$/.match?(@options[:exclude_limit])
|
366
370
|
|
367
371
|
# Emulate OptionParser's behavior to make failures consistent regardless
|
368
372
|
# of option order.
|
@@ -438,7 +442,9 @@ module RuboCop
|
|
438
442
|
debug: 'Display debug info.',
|
439
443
|
display_cop_names: ['Display cop names in offense messages.',
|
440
444
|
'Default is true.'],
|
445
|
+
disable_pending_cops: 'Run without pending cops.',
|
441
446
|
display_style_guide: 'Display style guide URLs in offense messages.',
|
447
|
+
enable_pending_cops: 'Run with pending cops.',
|
442
448
|
extra_details: 'Display extra details in offense messages.',
|
443
449
|
lint: 'Run only lint cops.',
|
444
450
|
safe: 'Run only safe cops.',
|
@@ -163,7 +163,7 @@ module RuboCop
|
|
163
163
|
ast, comments, tokens = parser.tokenize(@buffer)
|
164
164
|
|
165
165
|
ast.respond_to?(:complete!) && ast.complete!
|
166
|
-
rescue Parser::SyntaxError
|
166
|
+
rescue Parser::SyntaxError
|
167
167
|
# All errors are in diagnostics. No need to handle exception.
|
168
168
|
end
|
169
169
|
|
@@ -175,9 +175,6 @@ module RuboCop
|
|
175
175
|
# rubocop:disable Metrics/MethodLength
|
176
176
|
def parser_class(ruby_version)
|
177
177
|
case ruby_version
|
178
|
-
when 2.3
|
179
|
-
require 'parser/ruby23'
|
180
|
-
Parser::Ruby23
|
181
178
|
when 2.4
|
182
179
|
require 'parser/ruby24'
|
183
180
|
Parser::Ruby24
|
@@ -153,7 +153,7 @@ module RuboCop
|
|
153
153
|
annotations = []
|
154
154
|
|
155
155
|
annotated_source.each_line do |source_line|
|
156
|
-
if source_line
|
156
|
+
if ANNOTATION_PATTERN.match?(source_line)
|
157
157
|
annotations << [source.size, source_line]
|
158
158
|
else
|
159
159
|
source << source_line
|
@@ -52,6 +52,7 @@ RSpec.shared_context 'config', :config do
|
|
52
52
|
cop_name = described_class.cop_name
|
53
53
|
hash[cop_name] = RuboCop::ConfigLoader
|
54
54
|
.default_configuration[cop_name]
|
55
|
+
.merge('Enabled' => true) # in case it is 'pending'
|
55
56
|
.merge(cop_config)
|
56
57
|
end
|
57
58
|
|
@@ -73,10 +74,6 @@ RSpec.shared_context 'mock console output' do
|
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
76
|
-
RSpec.shared_context 'ruby 2.3', :ruby23 do
|
77
|
-
let(:ruby_version) { 2.3 }
|
78
|
-
end
|
79
|
-
|
80
77
|
RSpec.shared_context 'ruby 2.4', :ruby24 do
|
81
78
|
let(:ruby_version) { 2.4 }
|
82
79
|
end
|
@@ -88,3 +85,7 @@ end
|
|
88
85
|
RSpec.shared_context 'ruby 2.6', :ruby26 do
|
89
86
|
let(:ruby_version) { 2.6 }
|
90
87
|
end
|
88
|
+
|
89
|
+
RSpec.shared_context 'ruby 2.7', :ruby27 do
|
90
|
+
let(:ruby_version) { 2.7 }
|
91
|
+
end
|
data/lib/rubocop/runner.rb
CHANGED
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# The kind of Ruby that code inspected by RuboCop is written in.
|
5
|
+
class TargetRuby
|
6
|
+
KNOWN_RUBIES = [2.4, 2.5, 2.6, 2.7].freeze
|
7
|
+
DEFAULT_VERSION = KNOWN_RUBIES.first
|
8
|
+
|
9
|
+
OBSOLETE_RUBIES = {
|
10
|
+
1.9 => '0.50', 2.0 => '0.50', 2.1 => '0.58', 2.2 => '0.69', 2.3 => '0.82'
|
11
|
+
}.freeze
|
12
|
+
private_constant :KNOWN_RUBIES, :OBSOLETE_RUBIES
|
13
|
+
|
14
|
+
# A place where information about a target ruby version is found.
|
15
|
+
class Source
|
16
|
+
attr_reader :version, :name
|
17
|
+
|
18
|
+
def initialize(config)
|
19
|
+
@config = config
|
20
|
+
@version = find_version
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# The target ruby version may be configured in RuboCop's config.
|
29
|
+
class RuboCopConfig < Source
|
30
|
+
def name
|
31
|
+
"`TargetRubyVersion` parameter (in #{@config.smart_loaded_path})"
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def find_version
|
37
|
+
@config.for_all_cops['TargetRubyVersion']&.to_f
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# The target ruby version may be found in a .ruby-version file.
|
42
|
+
class RubyVersionFile < Source
|
43
|
+
FILENAME = '.ruby-version'
|
44
|
+
|
45
|
+
def name
|
46
|
+
"`#{FILENAME}`"
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def find_version
|
52
|
+
file = ruby_version_file
|
53
|
+
return unless file && File.file?(file)
|
54
|
+
|
55
|
+
File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
|
56
|
+
md[:version].to_f
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def ruby_version_file
|
61
|
+
@ruby_version_file ||=
|
62
|
+
@config.find_file_upwards(FILENAME,
|
63
|
+
@config.base_dir_for_path_parameters)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# The lock file of Bundler may identify the target ruby version.
|
68
|
+
class BundlerLockFile < Source
|
69
|
+
def name
|
70
|
+
"`#{bundler_lock_file_path}`"
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def find_version
|
76
|
+
lock_file_path = bundler_lock_file_path
|
77
|
+
return nil unless lock_file_path
|
78
|
+
|
79
|
+
in_ruby_section = false
|
80
|
+
File.foreach(lock_file_path) do |line|
|
81
|
+
# If ruby is in Gemfile.lock or gems.lock, there should be two lines
|
82
|
+
# towards the bottom of the file that look like:
|
83
|
+
# RUBY VERSION
|
84
|
+
# ruby W.X.YpZ
|
85
|
+
# We ultimately want to match the "ruby W.X.Y.pZ" line, but there's
|
86
|
+
# extra logic to make sure we only start looking once we've seen the
|
87
|
+
# "RUBY VERSION" line.
|
88
|
+
in_ruby_section ||= line.match(/^\s*RUBY\s*VERSION\s*$/)
|
89
|
+
next unless in_ruby_section
|
90
|
+
|
91
|
+
# We currently only allow this feature to work with MRI ruby. If
|
92
|
+
# jruby (or something else) is used by the project, it's lock file
|
93
|
+
# will have a line that looks like:
|
94
|
+
# RUBY VERSION
|
95
|
+
# ruby W.X.YpZ (jruby x.x.x.x)
|
96
|
+
# The regex won't match in this situation.
|
97
|
+
result = line.match(/^\s*ruby\s+(\d+\.\d+)[p.\d]*\s*$/)
|
98
|
+
return result.captures.first.to_f if result
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def bundler_lock_file_path
|
103
|
+
@config.bundler_lock_file_path
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# If all else fails, a default version will be picked.
|
108
|
+
class Default < Source
|
109
|
+
def name
|
110
|
+
'default'
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def find_version
|
116
|
+
DEFAULT_VERSION
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.supported_versions
|
121
|
+
KNOWN_RUBIES
|
122
|
+
end
|
123
|
+
|
124
|
+
SOURCES = [RuboCopConfig, RubyVersionFile, BundlerLockFile, Default].freeze
|
125
|
+
private_constant :SOURCES
|
126
|
+
|
127
|
+
def initialize(config)
|
128
|
+
@config = config
|
129
|
+
end
|
130
|
+
|
131
|
+
def source
|
132
|
+
@source ||= SOURCES.each.lazy.map { |c| c.new(@config) }.detect(&:version)
|
133
|
+
end
|
134
|
+
|
135
|
+
def version
|
136
|
+
source.version
|
137
|
+
end
|
138
|
+
|
139
|
+
def supported?
|
140
|
+
KNOWN_RUBIES.include?(version)
|
141
|
+
end
|
142
|
+
|
143
|
+
def rubocop_version_with_support
|
144
|
+
if supported?
|
145
|
+
RuboCop::Version.version
|
146
|
+
else
|
147
|
+
OBSOLETE_RUBIES[version]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|