rubocop 1.36.0 → 1.40.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 +1 -1
- data/config/default.yml +78 -12
- data/exe/rubocop +1 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cli/command/suggest_extensions.rb +8 -1
- data/lib/rubocop/comment_config.rb +41 -1
- data/lib/rubocop/config.rb +5 -4
- data/lib/rubocop/config_loader.rb +5 -5
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/cop/base.rb +2 -9
- data/lib/rubocop/cop/commissioner.rb +3 -1
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
- data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
- data/lib/rubocop/cop/internal_affairs.rb +3 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +29 -8
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
- data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -2
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +28 -9
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/empty_block.rb +1 -5
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +21 -9
- data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +36 -4
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +38 -10
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +18 -8
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
- data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -3
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/lint/void.rb +6 -6
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +9 -4
- data/lib/rubocop/cop/metrics/class_length.rb +9 -4
- data/lib/rubocop/cop/metrics/method_length.rb +9 -4
- data/lib/rubocop/cop/metrics/module_length.rb +9 -4
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +30 -8
- data/lib/rubocop/cop/mixin/range_help.rb +23 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +10 -8
- data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/registry.rb +32 -14
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +5 -7
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/array_intersect.rb +111 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -2
- data/lib/rubocop/cop/style/character_literal.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +8 -6
- data/lib/rubocop/cop/style/collection_compact.rb +12 -3
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +90 -22
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +32 -10
- data/lib/rubocop/cop/style/hash_except.rb +4 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
- data/lib/rubocop/cop/style/module_function.rb +28 -6
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +3 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +53 -0
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
- data/lib/rubocop/cop/style/redundant_constant_base.rb +72 -0
- data/lib/rubocop/cop/style/redundant_each.rb +116 -0
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +12 -3
- data/lib/rubocop/cop/style/redundant_return.rb +7 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +181 -0
- data/lib/rubocop/cop/style/require_order.rb +88 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +8 -4
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/string_literals.rb +1 -5
- data/lib/rubocop/cop/style/symbol_array.rb +2 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +3 -5
- data/lib/rubocop/cop/style/word_array.rb +2 -0
- data/lib/rubocop/cop/team.rb +4 -5
- data/lib/rubocop/cop/util.rb +2 -2
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +20 -29
- data/lib/rubocop/cops_documentation_generator.rb +2 -1
- data/lib/rubocop/ext/processed_source.rb +2 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +25 -8
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
- data/lib/rubocop/formatter.rb +3 -1
- data/lib/rubocop/optimized_patterns.rb +38 -0
- data/lib/rubocop/options.rb +28 -16
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +24 -1
- data/lib/rubocop/rspec/shared_contexts.rb +14 -1
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/runner.rb +15 -11
- data/lib/rubocop/server/cache.rb +5 -1
- data/lib/rubocop/server/cli.rb +9 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +19 -2
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +8 -3
- data/lib/rubocop.rb +18 -6
- metadata +18 -5
@@ -31,6 +31,7 @@ module RuboCop
|
|
31
31
|
minimum_target_ruby_version 2.3
|
32
32
|
|
33
33
|
MSG = 'Do not chain ordinary method call after safe navigation operator.'
|
34
|
+
PLUS_MINUS_METHODS = %i[+@ -@].freeze
|
34
35
|
|
35
36
|
# @!method bad_method?(node)
|
36
37
|
def_node_matcher :bad_method?, <<~PATTERN
|
@@ -42,7 +43,7 @@ module RuboCop
|
|
42
43
|
|
43
44
|
def on_send(node)
|
44
45
|
bad_method?(node) do |safe_nav, method|
|
45
|
-
return if nil_methods.include?(method)
|
46
|
+
return if nil_methods.include?(method) || PLUS_MINUS_METHODS.include?(node.method_name)
|
46
47
|
|
47
48
|
method_chain = method_chain(node)
|
48
49
|
location =
|
@@ -61,17 +62,18 @@ module RuboCop
|
|
61
62
|
# @param [RuboCop::AST::SendNode] send_node
|
62
63
|
# @return [String]
|
63
64
|
def add_safe_navigation_operator(offense_range:, send_node:)
|
64
|
-
source =
|
65
|
-
if
|
65
|
+
source =
|
66
|
+
if (brackets = find_brackets(send_node))
|
66
67
|
format(
|
67
|
-
'%<method_name>s(%<arguments>s)',
|
68
|
-
arguments:
|
69
|
-
method_name:
|
68
|
+
'%<method_name>s(%<arguments>s)%<method_chain>s',
|
69
|
+
arguments: brackets.arguments.map(&:source).join(', '),
|
70
|
+
method_name: brackets.method_name,
|
71
|
+
method_chain: brackets.source_range.end.join(send_node.source_range.end).source
|
70
72
|
)
|
71
73
|
else
|
72
|
-
offense_range.source
|
74
|
+
offense_range.source
|
73
75
|
end
|
74
|
-
source.prepend('.') unless
|
76
|
+
source.prepend('.') unless source.start_with?('.')
|
75
77
|
source.prepend('&')
|
76
78
|
end
|
77
79
|
|
@@ -93,6 +95,14 @@ module RuboCop
|
|
93
95
|
chain = chain.parent if chain.send_type? && chain.parent&.call_type?
|
94
96
|
chain
|
95
97
|
end
|
98
|
+
|
99
|
+
def find_brackets(send_node)
|
100
|
+
return send_node if send_node.method?(:[]) || send_node.method?(:[]=)
|
101
|
+
|
102
|
+
send_node.descendants.detect do |node|
|
103
|
+
node.send_type? && (node.method?(:[]) || node.method?(:[]=))
|
104
|
+
end
|
105
|
+
end
|
96
106
|
end
|
97
107
|
end
|
98
108
|
end
|
@@ -48,16 +48,17 @@ module RuboCop
|
|
48
48
|
(send
|
49
49
|
(const _ _) {:#{SEND_METHODS.join(' :')}}
|
50
50
|
({sym str} $#mixin_method?)
|
51
|
-
$(const _ _))
|
51
|
+
$(const _ _)+)
|
52
52
|
PATTERN
|
53
53
|
|
54
54
|
def on_send(node)
|
55
|
-
send_with_mixin_argument?(node) do |method,
|
56
|
-
|
55
|
+
send_with_mixin_argument?(node) do |method, module_names|
|
56
|
+
module_names_source = module_names.map(&:source).join(', ')
|
57
|
+
message = message(method, module_names_source, bad_location(node).source)
|
57
58
|
|
58
59
|
bad_location = bad_location(node)
|
59
60
|
add_offense(bad_location, message: message) do |corrector|
|
60
|
-
corrector.replace(bad_location, "#{method} #{
|
61
|
+
corrector.replace(bad_location, "#{method} #{module_names_source}")
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
@@ -155,16 +155,6 @@ module RuboCop
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
158
|
-
# @param [RuboCop::AST::Node] rescue_group is a node of array_type
|
159
|
-
def rescued_exceptions(rescue_group)
|
160
|
-
klasses = *rescue_group
|
161
|
-
klasses.map do |klass|
|
162
|
-
next unless klass.const_type?
|
163
|
-
|
164
|
-
klass.source
|
165
|
-
end.compact
|
166
|
-
end
|
167
|
-
|
168
158
|
def find_shadowing_rescue(rescues)
|
169
159
|
rescued_groups = rescued_groups_for(rescues)
|
170
160
|
rescued_groups.zip(rescues).each do |group, res|
|
@@ -12,9 +12,12 @@ module RuboCop
|
|
12
12
|
# because `Ractor` should not access outer variables.
|
13
13
|
# eg. following style is encouraged:
|
14
14
|
#
|
15
|
+
# [source,ruby]
|
16
|
+
# ----
|
15
17
|
# worker_id, pipe = env
|
16
18
|
# Ractor.new(worker_id, pipe) do |worker_id, pipe|
|
17
19
|
# end
|
20
|
+
# ----
|
18
21
|
#
|
19
22
|
# @example
|
20
23
|
#
|
@@ -70,10 +73,11 @@ module RuboCop
|
|
70
73
|
outer_local_variable_node =
|
71
74
|
find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
|
72
75
|
return true unless outer_local_variable_node
|
76
|
+
return false unless outer_local_variable_node.conditional?
|
77
|
+
return true if variable_node == outer_local_variable_node
|
73
78
|
|
74
|
-
outer_local_variable_node.
|
75
|
-
|
76
|
-
variable_node == outer_local_variable_node.else_branch)
|
79
|
+
outer_local_variable_node.if_type? &&
|
80
|
+
variable_node == outer_local_variable_node.else_branch
|
77
81
|
end
|
78
82
|
|
79
83
|
def variable_node(variable)
|
@@ -116,7 +116,7 @@ module RuboCop
|
|
116
116
|
private
|
117
117
|
|
118
118
|
def comment_between_rescue_and_end?(node)
|
119
|
-
ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block).first
|
119
|
+
ancestor = node.each_ancestor(:kwbegin, :def, :defs, :block, :numblock).first
|
120
120
|
return unless ancestor
|
121
121
|
|
122
122
|
end_line = ancestor.loc.end.line
|
@@ -79,7 +79,7 @@ module RuboCop
|
|
79
79
|
# # bad
|
80
80
|
# 2.times { raise ArgumentError }
|
81
81
|
#
|
82
|
-
# @example AllowedPatterns: [
|
82
|
+
# @example AllowedPatterns: ['(exactly|at_least|at_most)\(\d+\)\.times'] (default)
|
83
83
|
#
|
84
84
|
# # good
|
85
85
|
# exactly(2).times { raise StandardError }
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
|
-
# Checks for operators, variables, literals, and nonmutating
|
6
|
+
# Checks for operators, variables, literals, lambda, proc and nonmutating
|
7
7
|
# methods used in void context.
|
8
8
|
#
|
9
9
|
# @example CheckForMethodsWithNoSideEffects: false (default)
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
VAR_MSG = 'Variable `%<var>s` used in void context.'
|
46
46
|
LIT_MSG = 'Literal `%<lit>s` used in void context.'
|
47
47
|
SELF_MSG = '`self` used in void context.'
|
48
|
-
|
48
|
+
EXPRESSION_MSG = '`%<expression>s` used in void context.'
|
49
49
|
NONMUTATING_MSG = 'Method `#%<method>s` used in void context. Did you mean `#%<method>s!`?'
|
50
50
|
|
51
51
|
BINARY_OPERATORS = %i[* / % + - == === != < > <= >= <=>].freeze
|
@@ -87,7 +87,7 @@ module RuboCop
|
|
87
87
|
check_literal(expr)
|
88
88
|
check_var(expr)
|
89
89
|
check_self(expr)
|
90
|
-
|
90
|
+
check_void_expression(expr)
|
91
91
|
return unless cop_config['CheckForMethodsWithNoSideEffects']
|
92
92
|
|
93
93
|
check_nonmutating(expr)
|
@@ -117,10 +117,10 @@ module RuboCop
|
|
117
117
|
add_offense(node, message: SELF_MSG)
|
118
118
|
end
|
119
119
|
|
120
|
-
def
|
121
|
-
return unless node.defined_type?
|
120
|
+
def check_void_expression(node)
|
121
|
+
return unless node.defined_type? || node.lambda_or_proc?
|
122
122
|
|
123
|
-
add_offense(node, message: format(
|
123
|
+
add_offense(node, message: format(EXPRESSION_MSG, expression: node.source))
|
124
124
|
end
|
125
125
|
|
126
126
|
def check_nonmutating(node)
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
#
|
21
21
|
# @example CountRepeatedAttributes: false (default is true)
|
22
22
|
#
|
23
|
-
# # `model` and `current_user`,
|
23
|
+
# # `model` and `current_user`, referenced 3 times each,
|
24
24
|
# # are each counted as only 1 branch each if
|
25
25
|
# # `CountRepeatedAttributes` is set to 'false'
|
26
26
|
#
|
@@ -8,8 +8,8 @@ module RuboCop
|
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
# The cop can be configured to ignore blocks passed to certain methods.
|
10
10
|
#
|
11
|
-
# You can set
|
12
|
-
# Available are: 'array', 'hash', and '
|
11
|
+
# You can set constructs you want to fold with `CountAsOne`.
|
12
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
13
13
|
# will be counted as one line regardless of its actual size.
|
14
14
|
#
|
15
15
|
#
|
@@ -17,7 +17,7 @@ module RuboCop
|
|
17
17
|
# for backwards compatibility. Please use `AllowedMethods` and `AllowedPatterns`
|
18
18
|
# instead. By default, there are no methods to allowed.
|
19
19
|
#
|
20
|
-
# @example CountAsOne: ['array', 'heredoc']
|
20
|
+
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
21
21
|
#
|
22
22
|
# something do
|
23
23
|
# array = [ # +1
|
@@ -33,7 +33,12 @@ module RuboCop
|
|
33
33
|
# Heredoc
|
34
34
|
# content.
|
35
35
|
# HEREDOC
|
36
|
-
#
|
36
|
+
#
|
37
|
+
# foo( # +1
|
38
|
+
# 1,
|
39
|
+
# 2
|
40
|
+
# )
|
41
|
+
# end # 6 points
|
37
42
|
#
|
38
43
|
# NOTE: This cop does not apply for `Struct` definitions.
|
39
44
|
class BlockLength < Base
|
@@ -7,11 +7,11 @@ module RuboCop
|
|
7
7
|
# Comment lines can optionally be ignored.
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
|
-
# You can set
|
11
|
-
# Available are: 'array', 'hash', and '
|
10
|
+
# You can set constructs you want to fold with `CountAsOne`.
|
11
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
12
12
|
# will be counted as one line regardless of its actual size.
|
13
13
|
#
|
14
|
-
# @example CountAsOne: ['array', 'heredoc']
|
14
|
+
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
15
15
|
#
|
16
16
|
# class Foo
|
17
17
|
# ARRAY = [ # +1
|
@@ -27,7 +27,12 @@ module RuboCop
|
|
27
27
|
# Heredoc
|
28
28
|
# content.
|
29
29
|
# HEREDOC
|
30
|
-
#
|
30
|
+
#
|
31
|
+
# foo( # +1
|
32
|
+
# 1,
|
33
|
+
# 2
|
34
|
+
# )
|
35
|
+
# end # 6 points
|
31
36
|
#
|
32
37
|
#
|
33
38
|
# NOTE: This cop also applies for `Struct` definitions.
|
@@ -7,8 +7,8 @@ module RuboCop
|
|
7
7
|
# Comment lines can optionally be allowed.
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
|
-
# You can set
|
11
|
-
# Available are: 'array', 'hash', and '
|
10
|
+
# You can set constructs you want to fold with `CountAsOne`.
|
11
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
12
12
|
# will be counted as one line regardless of its actual size.
|
13
13
|
#
|
14
14
|
# NOTE: The `ExcludedMethods` and `IgnoredMethods` configuration is
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
# Please use `AllowedMethods` and `AllowedPatterns` instead.
|
17
17
|
# By default, there are no methods to allowed.
|
18
18
|
#
|
19
|
-
# @example CountAsOne: ['array', 'heredoc']
|
19
|
+
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
20
20
|
#
|
21
21
|
# def m
|
22
22
|
# array = [ # +1
|
@@ -32,7 +32,12 @@ module RuboCop
|
|
32
32
|
# Heredoc
|
33
33
|
# content.
|
34
34
|
# HEREDOC
|
35
|
-
#
|
35
|
+
#
|
36
|
+
# foo( # +1
|
37
|
+
# 1,
|
38
|
+
# 2
|
39
|
+
# )
|
40
|
+
# end # 6 points
|
36
41
|
#
|
37
42
|
class MethodLength < Base
|
38
43
|
include CodeLength
|
@@ -7,11 +7,11 @@ module RuboCop
|
|
7
7
|
# Comment lines can optionally be ignored.
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
|
-
# You can set
|
11
|
-
# Available are: 'array', 'hash', and '
|
10
|
+
# You can set constructs you want to fold with `CountAsOne`.
|
11
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
12
12
|
# will be counted as one line regardless of its actual size.
|
13
13
|
#
|
14
|
-
# @example CountAsOne: ['array', 'heredoc']
|
14
|
+
# @example CountAsOne: ['array', 'heredoc', 'method_call']
|
15
15
|
#
|
16
16
|
# module M
|
17
17
|
# ARRAY = [ # +1
|
@@ -27,7 +27,12 @@ module RuboCop
|
|
27
27
|
# Heredoc
|
28
28
|
# content.
|
29
29
|
# HEREDOC
|
30
|
-
#
|
30
|
+
#
|
31
|
+
# foo( # +1
|
32
|
+
# 1,
|
33
|
+
# 2
|
34
|
+
# )
|
35
|
+
# end # 6 points
|
31
36
|
#
|
32
37
|
class ModuleLength < Base
|
33
38
|
include CodeLength
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
9
9
|
extend NodePattern::Macros
|
10
10
|
include Util
|
11
11
|
|
12
|
-
FOLDABLE_TYPES = %i[array hash heredoc].freeze
|
12
|
+
FOLDABLE_TYPES = %i[array hash heredoc send csend].freeze
|
13
13
|
CLASSLIKE_TYPES = %i[class module].freeze
|
14
14
|
private_constant :FOLDABLE_TYPES, :CLASSLIKE_TYPES
|
15
15
|
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
39
39
|
|
40
40
|
private
|
41
41
|
|
42
|
-
def build_foldable_checks(types)
|
42
|
+
def build_foldable_checks(types) # rubocop:disable Metrics/MethodLength
|
43
43
|
types.map do |type|
|
44
44
|
case type
|
45
45
|
when :array
|
@@ -48,6 +48,8 @@ module RuboCop
|
|
48
48
|
->(node) { node.hash_type? }
|
49
49
|
when :heredoc
|
50
50
|
->(node) { heredoc_node?(node) }
|
51
|
+
when :method_call
|
52
|
+
->(node) { node.call_type? }
|
51
53
|
else
|
52
54
|
raise ArgumentError, "Unknown foldable type: #{type.inspect}. " \
|
53
55
|
"Valid foldable types are: #{FOLDABLE_TYPES.join(', ')}."
|
@@ -57,6 +59,7 @@ module RuboCop
|
|
57
59
|
|
58
60
|
def normalize_foldable_types(types)
|
59
61
|
types.concat(%i[str dstr]) if types.delete(:heredoc)
|
62
|
+
types.concat(%i[send csend]) if types.delete(:method_call)
|
60
63
|
types
|
61
64
|
end
|
62
65
|
|
@@ -22,6 +22,18 @@ module RuboCop
|
|
22
22
|
processed_source.each_comment_in_lines(start_line...end_line)
|
23
23
|
end
|
24
24
|
|
25
|
+
def comments_contain_disables?(node, cop_name)
|
26
|
+
disabled_ranges = processed_source.disabled_line_ranges[cop_name]
|
27
|
+
|
28
|
+
return unless disabled_ranges
|
29
|
+
|
30
|
+
node_range = node.source_range.line...find_end_line(node)
|
31
|
+
|
32
|
+
disabled_ranges.any? do |disable_range|
|
33
|
+
disable_range.cover?(node_range) || node_range.cover?(disable_range)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
25
37
|
private
|
26
38
|
|
27
39
|
def end_position_for(node)
|
@@ -47,6 +47,12 @@ module RuboCop
|
|
47
47
|
|
48
48
|
def register_offense(node, message, replacement)
|
49
49
|
add_offense(node.value, message: message) do |corrector|
|
50
|
+
if (def_node = def_node_that_require_parentheses(node))
|
51
|
+
white_spaces = range_between(def_node.loc.selector.end_pos,
|
52
|
+
def_node.first_argument.source_range.begin_pos)
|
53
|
+
corrector.replace(white_spaces, '(')
|
54
|
+
corrector.insert_after(def_node.arguments.last, ')')
|
55
|
+
end
|
50
56
|
corrector.replace(node, replacement)
|
51
57
|
end
|
52
58
|
end
|
@@ -76,12 +82,25 @@ module RuboCop
|
|
76
82
|
end
|
77
83
|
|
78
84
|
def require_hash_value_for_around_hash_literal?(node)
|
79
|
-
return false unless (
|
80
|
-
|
85
|
+
return false unless (send_node = find_ancestor_send_node(node))
|
86
|
+
|
87
|
+
!node.parent.braces? && !use_element_of_hash_literal_as_receiver?(send_node, node.parent) &&
|
88
|
+
use_modifier_form_without_parenthesized_method_call?(send_node)
|
89
|
+
end
|
90
|
+
|
91
|
+
def def_node_that_require_parentheses(node)
|
92
|
+
return unless (send_node = find_ancestor_send_node(node))
|
93
|
+
return unless without_parentheses_call_expr_follows?(send_node)
|
94
|
+
|
95
|
+
def_node = node.each_ancestor(:send, :csend).first
|
81
96
|
|
82
|
-
|
83
|
-
|
84
|
-
|
97
|
+
def_node unless def_node && def_node.arguments.empty?
|
98
|
+
end
|
99
|
+
|
100
|
+
def find_ancestor_send_node(node)
|
101
|
+
ancestor = node.parent.parent
|
102
|
+
|
103
|
+
ancestor if ancestor&.call_type? && !ancestor&.method?(:[])
|
85
104
|
end
|
86
105
|
|
87
106
|
def use_element_of_hash_literal_as_receiver?(ancestor, parent)
|
@@ -96,11 +115,14 @@ module RuboCop
|
|
96
115
|
end
|
97
116
|
|
98
117
|
def without_parentheses_call_expr_follows?(ancestor)
|
118
|
+
return false unless ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized?
|
119
|
+
|
99
120
|
right_sibling = ancestor.right_sibling
|
100
|
-
right_sibling ||= ancestor.each_ancestor.find
|
101
|
-
|
121
|
+
right_sibling ||= ancestor.each_ancestor.find do |node|
|
122
|
+
node.assignment? || node.send_type?
|
123
|
+
end&.right_sibling
|
102
124
|
|
103
|
-
|
125
|
+
!!right_sibling
|
104
126
|
end
|
105
127
|
|
106
128
|
def breakdown_value_types_of_hash(hash_node)
|
@@ -126,6 +126,29 @@ module RuboCop
|
|
126
126
|
pos += size * step while condition && src[pos + offset, size] == needle
|
127
127
|
pos.negative? ? 0 : pos
|
128
128
|
end
|
129
|
+
|
130
|
+
def range_with_comments_and_lines(node)
|
131
|
+
range_by_whole_lines(range_with_comments(node), include_final_newline: true)
|
132
|
+
end
|
133
|
+
|
134
|
+
def range_with_comments(node)
|
135
|
+
ranges = [
|
136
|
+
node,
|
137
|
+
*@processed_source.ast_with_comments[node]
|
138
|
+
].map do |element|
|
139
|
+
element.location.expression
|
140
|
+
end
|
141
|
+
ranges.reduce do |result, range|
|
142
|
+
add_range(result, range)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_range(range1, range2)
|
147
|
+
range1.with(
|
148
|
+
begin_pos: [range1.begin_pos, range2.begin_pos].min,
|
149
|
+
end_pos: [range1.end_pos, range2.end_pos].max
|
150
|
+
)
|
151
|
+
end
|
129
152
|
end
|
130
153
|
end
|
131
154
|
end
|
@@ -11,7 +11,9 @@ module RuboCop
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def rescue_modifier?(node)
|
14
|
-
|
14
|
+
return false unless node.respond_to?(:resbody_type?)
|
15
|
+
|
16
|
+
node.resbody_type? && @modifier_locations.include?(node.loc.keyword)
|
15
17
|
end
|
16
18
|
|
17
19
|
# @deprecated Use ResbodyNode#exceptions instead
|
@@ -48,11 +48,25 @@ module RuboCop
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def to_modifier_form(node)
|
51
|
-
|
51
|
+
body = if_body_source(node.body)
|
52
|
+
expression = [body, node.keyword, node.condition.source].compact.join(' ')
|
52
53
|
parenthesized = parenthesize?(node) ? "(#{expression})" : expression
|
53
54
|
[parenthesized, first_line_comment(node)].compact.join(' ')
|
54
55
|
end
|
55
56
|
|
57
|
+
def if_body_source(if_body)
|
58
|
+
if if_body.call_type? &&
|
59
|
+
if_body.last_argument&.hash_type? && if_body.last_argument.pairs.last.value_omission?
|
60
|
+
"#{method_source(if_body)}(#{if_body.arguments.map(&:source).join(', ')})"
|
61
|
+
else
|
62
|
+
if_body.source
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def method_source(if_body)
|
67
|
+
range_between(if_body.loc.expression.begin_pos, if_body.loc.selector.end_pos).source
|
68
|
+
end
|
69
|
+
|
56
70
|
def first_line_comment(node)
|
57
71
|
comment = processed_source.find_comment { |c| same_line?(c, node) }
|
58
72
|
return unless comment
|
@@ -13,7 +13,7 @@ module RuboCop
|
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def side_space_range(range:, side:)
|
16
|
+
def side_space_range(range:, side:, include_newlines: false)
|
17
17
|
buffer = processed_source.buffer
|
18
18
|
src = buffer.source
|
19
19
|
|
@@ -21,11 +21,11 @@ module RuboCop
|
|
21
21
|
end_pos = range.end_pos
|
22
22
|
if side == :left
|
23
23
|
end_pos = begin_pos
|
24
|
-
begin_pos = reposition(src, begin_pos, -1)
|
24
|
+
begin_pos = reposition(src, begin_pos, -1, include_newlines: include_newlines)
|
25
25
|
end
|
26
26
|
if side == :right
|
27
27
|
begin_pos = end_pos
|
28
|
-
end_pos = reposition(src, end_pos, 1)
|
28
|
+
end_pos = reposition(src, end_pos, 1, include_newlines: include_newlines)
|
29
29
|
end
|
30
30
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
31
31
|
end
|
@@ -75,9 +75,10 @@ module RuboCop
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def reposition(src, pos, step)
|
78
|
+
def reposition(src, pos, step, include_newlines: false)
|
79
79
|
offset = step == -1 ? -1 : 0
|
80
|
-
pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset])
|
80
|
+
pos += step while SINGLE_SPACE_REGEXP.match?(src[pos + offset]) ||
|
81
|
+
(include_newlines && src[pos + offset] == "\n")
|
81
82
|
pos.negative? ? 0 : pos
|
82
83
|
end
|
83
84
|
|
@@ -117,14 +118,15 @@ module RuboCop
|
|
117
118
|
end
|
118
119
|
|
119
120
|
def offending_empty_no_space?(config, left_token, right_token)
|
120
|
-
config == 'no_space' && !
|
121
|
+
config == 'no_space' && !no_character_between?(left_token, right_token)
|
121
122
|
end
|
122
123
|
|
123
124
|
def space_between?(left_bracket_token, right_bracket_token)
|
124
|
-
left_bracket_token.end_pos + 1 == right_bracket_token.begin_pos
|
125
|
+
left_bracket_token.end_pos + 1 == right_bracket_token.begin_pos &&
|
126
|
+
processed_source.buffer.source[left_bracket_token.end_pos] == ' '
|
125
127
|
end
|
126
128
|
|
127
|
-
def
|
129
|
+
def no_character_between?(left_bracket_token, right_bracket_token)
|
128
130
|
left_bracket_token.end_pos == right_bracket_token.begin_pos
|
129
131
|
end
|
130
132
|
end
|
@@ -1,18 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'set'
|
4
|
+
|
3
5
|
module RuboCop
|
4
6
|
module Cop
|
5
7
|
# Help methods for determining node visibility.
|
6
8
|
module VisibilityHelp
|
7
9
|
extend NodePattern::Macros
|
8
10
|
|
9
|
-
VISIBILITY_SCOPES =
|
11
|
+
VISIBILITY_SCOPES = ::Set[:private, :protected, :public].freeze
|
10
12
|
|
11
13
|
private
|
12
14
|
|
13
15
|
def node_visibility(node)
|
14
|
-
|
15
|
-
|
16
|
+
node_visibility_from_visibility_inline(node) ||
|
17
|
+
node_visibility_from_visibility_block(node) ||
|
18
|
+
:public
|
19
|
+
end
|
20
|
+
|
21
|
+
def node_visibility_from_visibility_inline(node)
|
22
|
+
return unless node.def_type?
|
23
|
+
|
24
|
+
node_visibility_from_visibility_inline_on_def(node) ||
|
25
|
+
node_visibility_from_visibility_inline_on_method_name(node)
|
26
|
+
end
|
27
|
+
|
28
|
+
def node_visibility_from_visibility_inline_on_def(node)
|
29
|
+
parent = node.parent
|
30
|
+
parent.method_name if visibility_inline_on_def?(parent)
|
31
|
+
end
|
32
|
+
|
33
|
+
def node_visibility_from_visibility_inline_on_method_name(node)
|
34
|
+
node.right_siblings.reverse.find do |sibling|
|
35
|
+
visibility_inline_on_method_name?(sibling, method_name: node.method_name)
|
36
|
+
end&.method_name
|
37
|
+
end
|
38
|
+
|
39
|
+
def node_visibility_from_visibility_block(node)
|
40
|
+
find_visibility_start(node)&.method_name
|
16
41
|
end
|
17
42
|
|
18
43
|
def find_visibility_start(node)
|
@@ -21,7 +46,7 @@ module RuboCop
|
|
21
46
|
|
22
47
|
# Navigate to find the last protected method
|
23
48
|
def find_visibility_end(node)
|
24
|
-
possible_visibilities = VISIBILITY_SCOPES - [node_visibility(node)]
|
49
|
+
possible_visibilities = VISIBILITY_SCOPES - ::Set[node_visibility(node)]
|
25
50
|
right = node.right_siblings
|
26
51
|
right.find do |child_node|
|
27
52
|
possible_visibilities.include?(node_visibility(child_node))
|
@@ -30,7 +55,17 @@ module RuboCop
|
|
30
55
|
|
31
56
|
# @!method visibility_block?(node)
|
32
57
|
def_node_matcher :visibility_block?, <<~PATTERN
|
33
|
-
(send nil?
|
58
|
+
(send nil? VISIBILITY_SCOPES)
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
# @!method visibility_inline_on_def?(node)
|
62
|
+
def_node_matcher :visibility_inline_on_def?, <<~PATTERN
|
63
|
+
(send nil? VISIBILITY_SCOPES def)
|
64
|
+
PATTERN
|
65
|
+
|
66
|
+
# @!method visibility_inline_on_method_name?(node, method_name:)
|
67
|
+
def_node_matcher :visibility_inline_on_method_name?, <<~PATTERN
|
68
|
+
(send nil? VISIBILITY_SCOPES (sym %method_name))
|
34
69
|
PATTERN
|
35
70
|
end
|
36
71
|
end
|