rubocop 1.39.0 → 1.44.1
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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +149 -11
- data/exe/rubocop +1 -1
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/comment_config.rb +5 -0
- data/lib/rubocop/config.rb +39 -15
- data/lib/rubocop/config_loader.rb +26 -20
- data/lib/rubocop/config_loader_resolver.rb +6 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/badge.rb +9 -4
- data/lib/rubocop/cop/base.rb +84 -74
- data/lib/rubocop/cop/commissioner.rb +8 -3
- data/lib/rubocop/cop/cop.rb +29 -29
- data/lib/rubocop/cop/corrector.rb +30 -10
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -6
- data/lib/rubocop/cop/gemspec/dependency_version.rb +16 -18
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/block_end_newline.rb +7 -1
- data/lib/rubocop/cop/layout/class_structure.rb +32 -11
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
- data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
- data/lib/rubocop/cop/layout/empty_lines.rb +2 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +10 -6
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +38 -2
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +49 -2
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +61 -2
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +6 -9
- data/lib/rubocop/cop/layout/indentation_style.rb +7 -2
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -5
- data/lib/rubocop/cop/layout/line_length.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +51 -2
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +49 -2
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +53 -2
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +58 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +0 -2
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +11 -4
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
- data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
- data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +19 -8
- data/lib/rubocop/cop/lint/else_layout.rb +2 -6
- data/lib/rubocop/cop/lint/empty_block.rb +1 -5
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -7
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
- data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +19 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +15 -3
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +11 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +10 -12
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -3
- data/lib/rubocop/cop/lint/useless_rescue.rb +85 -0
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +14 -4
- data/lib/rubocop/cop/lint/void.rb +25 -16
- data/lib/rubocop/cop/metrics/block_length.rb +9 -4
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +10 -5
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +9 -4
- data/lib/rubocop/cop/metrics/module_length.rb +10 -5
- data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +3 -6
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -3
- data/lib/rubocop/cop/mixin/alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/annotation_comment.rb +13 -6
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +59 -6
- data/lib/rubocop/cop/mixin/line_length_help.rb +11 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -3
- data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/require_library.rb +2 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +16 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +5 -1
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -0
- data/lib/rubocop/cop/naming/inclusive_language.rb +4 -1
- data/lib/rubocop/cop/registry.rb +63 -43
- data/lib/rubocop/cop/security/compound_hash.rb +2 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +18 -10
- data/lib/rubocop/cop/style/alias.rb +9 -1
- data/lib/rubocop/cop/style/array_intersect.rb +111 -0
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +8 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +2 -9
- data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
- data/lib/rubocop/cop/style/concat_array_literals.rb +86 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +0 -6
- data/lib/rubocop/cop/style/documentation.rb +11 -5
- data/lib/rubocop/cop/style/guard_clause.rb +44 -9
- data/lib/rubocop/cop/style/hash_each_methods.rb +13 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +11 -7
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
- data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
- data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +114 -0
- data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
- data/lib/rubocop/cop/style/map_to_set.rb +61 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +23 -14
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
- data/lib/rubocop/cop/style/min_max_comparison.rb +83 -0
- data/lib/rubocop/cop/style/missing_else.rb +13 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -5
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
- data/lib/rubocop/cop/style/operator_method_call.rb +15 -1
- data/lib/rubocop/cop/style/parallel_assignment.rb +3 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
- data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +45 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- 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 +6 -3
- data/lib/rubocop/cop/style/require_order.rb +135 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
- data/lib/rubocop/cop/style/select_by_regexp.rb +13 -5
- data/lib/rubocop/cop/style/self_assignment.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +26 -3
- data/lib/rubocop/cop/style/signal_exception.rb +8 -6
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
- data/lib/rubocop/cop/style/string_literals.rb +1 -5
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
- data/lib/rubocop/cop/style/word_array.rb +41 -0
- data/lib/rubocop/cop/style/yoda_expression.rb +81 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +31 -14
- data/lib/rubocop/cop/team.rb +30 -30
- data/lib/rubocop/cop/util.rb +32 -5
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -1
- data/lib/rubocop/cop/variable_force.rb +18 -30
- data/lib/rubocop/cops_documentation_generator.rb +33 -11
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/file_patterns.rb +43 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter.rb +4 -1
- data/lib/rubocop/options.rb +8 -0
- data/lib/rubocop/path_util.rb +50 -22
- data/lib/rubocop/result_cache.rb +2 -2
- data/lib/rubocop/rspec/cop_helper.rb +4 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -4
- data/lib/rubocop/rspec/support.rb +2 -2
- data/lib/rubocop/runner.rb +10 -3
- data/lib/rubocop/server/cache.rb +3 -1
- data/lib/rubocop/server/core.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +23 -6
- metadata +23 -9
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Gemspec
|
6
|
+
# Enforce that development dependencies for a gem are specified in
|
7
|
+
# `Gemfile`, rather than in the `gemspec` using
|
8
|
+
# `add_development_dependency`. Alternatively, using `EnforcedStyle:
|
9
|
+
# gemspec`, enforce that all dependencies are specified in `gemspec`,
|
10
|
+
# rather than in `Gemfile`.
|
11
|
+
#
|
12
|
+
# @example EnforcedStyle: Gemfile (default)
|
13
|
+
# # Specify runtime dependencies in your gemspec,
|
14
|
+
# # but all other dependencies in your Gemfile.
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# # example.gemspec
|
18
|
+
# s.add_development_dependency "foo"
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# # Gemfile
|
22
|
+
# gem "foo"
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# # gems.rb
|
26
|
+
# gem "foo"
|
27
|
+
#
|
28
|
+
# # good (with AllowedGems: ["bar"])
|
29
|
+
# # example.gemspec
|
30
|
+
# s.add_development_dependency "bar"
|
31
|
+
#
|
32
|
+
# @example EnforcedStyle: gems.rb
|
33
|
+
# # Specify runtime dependencies in your gemspec,
|
34
|
+
# # but all other dependencies in your Gemfile.
|
35
|
+
# #
|
36
|
+
# # Identical to `EnforcedStyle: Gemfile`, but with a different error message.
|
37
|
+
# # Rely on Bundler/GemFilename to enforce the use of `Gemfile` vs `gems.rb`.
|
38
|
+
#
|
39
|
+
# # bad
|
40
|
+
# # example.gemspec
|
41
|
+
# s.add_development_dependency "foo"
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# # Gemfile
|
45
|
+
# gem "foo"
|
46
|
+
#
|
47
|
+
# # good
|
48
|
+
# # gems.rb
|
49
|
+
# gem "foo"
|
50
|
+
#
|
51
|
+
# # good (with AllowedGems: ["bar"])
|
52
|
+
# # example.gemspec
|
53
|
+
# s.add_development_dependency "bar"
|
54
|
+
#
|
55
|
+
# @example EnforcedStyle: gemspec
|
56
|
+
# # Specify all dependencies in your gemspec.
|
57
|
+
#
|
58
|
+
# # bad
|
59
|
+
# # Gemfile
|
60
|
+
# gem "foo"
|
61
|
+
#
|
62
|
+
# # good
|
63
|
+
# # example.gemspec
|
64
|
+
# s.add_development_dependency "foo"
|
65
|
+
#
|
66
|
+
# # good (with AllowedGems: ["bar"])
|
67
|
+
# # Gemfile
|
68
|
+
# gem "bar"
|
69
|
+
#
|
70
|
+
class DevelopmentDependencies < Base
|
71
|
+
include ConfigurableEnforcedStyle
|
72
|
+
|
73
|
+
MSG = 'Specify development dependencies in %<preferred>s.'
|
74
|
+
RESTRICT_ON_SEND = %i[add_development_dependency gem].freeze
|
75
|
+
|
76
|
+
# @!method add_development_dependency?(node)
|
77
|
+
def_node_matcher :add_development_dependency?, <<~PATTERN
|
78
|
+
(send _ :add_development_dependency (str #forbidden_gem? ...))
|
79
|
+
PATTERN
|
80
|
+
|
81
|
+
# @!method gem?(node)
|
82
|
+
def_node_matcher :gem?, <<~PATTERN
|
83
|
+
(send _ :gem (str #forbidden_gem? ...))
|
84
|
+
PATTERN
|
85
|
+
|
86
|
+
def on_send(node)
|
87
|
+
case style
|
88
|
+
when :Gemfile, :'gems.rb'
|
89
|
+
add_offense(node) if add_development_dependency?(node)
|
90
|
+
when :gemspec
|
91
|
+
add_offense(node) if gem?(node)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def forbidden_gem?(gem_name)
|
98
|
+
!cop_config['AllowedGems'].include?(gem_name)
|
99
|
+
end
|
100
|
+
|
101
|
+
def message(_range)
|
102
|
+
format(MSG, preferred: style)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -28,8 +28,9 @@ module RuboCop
|
|
28
28
|
/^\s+# This cop (?<special>#{SPECIAL_WORDS.join('|')})?\s*(?<word>.+?) .*/.freeze
|
29
29
|
REPLACEMENT_REGEX = /^\s+# This cop (#{SPECIAL_WORDS.join('|')})?\s*(.+?) /.freeze
|
30
30
|
|
31
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
31
32
|
def on_class(node)
|
32
|
-
return unless (module_node = node.parent)
|
33
|
+
return unless (module_node = node.parent) && node.parent_class
|
33
34
|
|
34
35
|
description_beginning = first_comment_line(module_node)
|
35
36
|
return unless description_beginning
|
@@ -48,6 +49,7 @@ module RuboCop
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
52
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
51
53
|
|
52
54
|
private
|
53
55
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Enforces the use of `node.lambda_or_proc?` instead of `node.lambda? || node.proc?`.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# node.lambda? || node.proc?
|
11
|
+
# node.proc? || node.lambda?
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# node.lambda_or_proc?
|
15
|
+
#
|
16
|
+
class LambdaOrProc < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
19
|
+
MSG = 'Use `%<prefer>s`.'
|
20
|
+
|
21
|
+
# @!method lambda_or_proc(node)
|
22
|
+
def_node_matcher :lambda_or_proc, <<~PATTERN
|
23
|
+
{
|
24
|
+
(or $(send _node :lambda?) $(send _node :proc?))
|
25
|
+
(or $(send _node :proc?) $(send _node :lambda?))
|
26
|
+
(or
|
27
|
+
(or _ $(send _node :lambda?)) $(send _node :proc?))
|
28
|
+
(or
|
29
|
+
(or _ $(send _node :proc?)) $(send _node :lambda?))
|
30
|
+
}
|
31
|
+
PATTERN
|
32
|
+
|
33
|
+
def on_or(node)
|
34
|
+
return unless (lhs, rhs = lambda_or_proc(node))
|
35
|
+
|
36
|
+
offense = lhs.receiver.source_range.join(rhs.source_range.end)
|
37
|
+
prefer = "#{lhs.receiver.source}.lambda_or_proc?"
|
38
|
+
|
39
|
+
add_offense(offense, message: format(MSG, prefer: prefer)) do |corrector|
|
40
|
+
corrector.replace(offense, prefer)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -31,9 +31,17 @@ module RuboCop
|
|
31
31
|
(send nil? :let
|
32
32
|
(sym :config))
|
33
33
|
(args)
|
34
|
-
|
35
|
-
(
|
36
|
-
(const
|
34
|
+
{
|
35
|
+
(send
|
36
|
+
(const
|
37
|
+
(const nil? :RuboCop) :Config) :new)
|
38
|
+
(send
|
39
|
+
(const
|
40
|
+
(const nil? :RuboCop) :Config) :new
|
41
|
+
(hash (pair (send (send (send nil? :described_class) :badge) :to_s)
|
42
|
+
(send nil? :cop_config))))
|
43
|
+
}
|
44
|
+
)
|
37
45
|
PATTERN
|
38
46
|
|
39
47
|
def on_block(node)
|
@@ -6,6 +6,7 @@ require_relative 'internal_affairs/empty_line_between_expect_offense_and_correct
|
|
6
6
|
require_relative 'internal_affairs/example_description'
|
7
7
|
require_relative 'internal_affairs/example_heredoc_delimiter'
|
8
8
|
require_relative 'internal_affairs/inherit_deprecated_cop_class'
|
9
|
+
require_relative 'internal_affairs/lambda_or_proc'
|
9
10
|
require_relative 'internal_affairs/location_line_equality_comparison'
|
10
11
|
require_relative 'internal_affairs/method_name_end_with'
|
11
12
|
require_relative 'internal_affairs/method_name_equal'
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
def register_offense(node)
|
47
47
|
add_offense(node.loc.end, message: message(node)) do |corrector|
|
48
48
|
offense_range = offense_range(node)
|
49
|
-
replacement =
|
49
|
+
replacement = replacement(node)
|
50
50
|
|
51
51
|
if (heredoc = last_heredoc_argument(node.body))
|
52
52
|
corrector.remove(offense_range)
|
@@ -79,6 +79,12 @@ module RuboCop
|
|
79
79
|
)
|
80
80
|
end
|
81
81
|
|
82
|
+
def replacement(node)
|
83
|
+
end_with_method_chain = node.loc.end.join(end_of_method_chain(node).loc.expression.end)
|
84
|
+
|
85
|
+
"\n#{end_with_method_chain.source.strip}"
|
86
|
+
end
|
87
|
+
|
82
88
|
def end_of_method_chain(node)
|
83
89
|
return node unless node.parent&.call_type?
|
84
90
|
|
@@ -132,25 +132,19 @@ module RuboCop
|
|
132
132
|
# end
|
133
133
|
# end
|
134
134
|
#
|
135
|
-
# @see https://rubystyle.guide#consistent-classes
|
136
135
|
class ClassStructure < Base
|
137
136
|
include VisibilityHelp
|
138
137
|
extend AutoCorrector
|
139
138
|
|
140
139
|
HUMANIZED_NODE_TYPE = {
|
141
140
|
casgn: :constants,
|
142
|
-
defs: :
|
141
|
+
defs: :public_class_methods,
|
143
142
|
def: :public_methods,
|
144
143
|
sclass: :class_singleton
|
145
144
|
}.freeze
|
146
145
|
|
147
146
|
MSG = '`%<category>s` is supposed to appear before `%<previous>s`.'
|
148
147
|
|
149
|
-
# @!method dynamic_constant?(node)
|
150
|
-
def_node_matcher :dynamic_constant?, <<~PATTERN
|
151
|
-
(casgn nil? _ (send ...))
|
152
|
-
PATTERN
|
153
|
-
|
154
148
|
# Validates code style on class declaration.
|
155
149
|
# Add offense when find a node out of expected order.
|
156
150
|
def on_class(class_node)
|
@@ -222,7 +216,7 @@ module RuboCop
|
|
222
216
|
def walk_over_nested_class_definition(class_node)
|
223
217
|
class_elements(class_node).each do |node|
|
224
218
|
classification = classify(node)
|
225
|
-
next if ignore?(classification)
|
219
|
+
next if ignore?(node, classification)
|
226
220
|
|
227
221
|
yield node, classification
|
228
222
|
end
|
@@ -240,17 +234,20 @@ module RuboCop
|
|
240
234
|
end
|
241
235
|
end
|
242
236
|
|
243
|
-
def ignore?(classification)
|
237
|
+
def ignore?(node, classification)
|
244
238
|
classification.nil? ||
|
245
239
|
classification.to_s.end_with?('=') ||
|
246
|
-
expected_order.index(classification).nil?
|
240
|
+
expected_order.index(classification).nil? ||
|
241
|
+
private_constant?(node)
|
247
242
|
end
|
248
243
|
|
249
244
|
def ignore_for_autocorrect?(node, sibling)
|
250
245
|
classification = classify(node)
|
251
246
|
sibling_class = classify(sibling)
|
252
247
|
|
253
|
-
ignore?(sibling_class) ||
|
248
|
+
ignore?(sibling, sibling_class) ||
|
249
|
+
classification == sibling_class ||
|
250
|
+
dynamic_constant?(node)
|
254
251
|
end
|
255
252
|
|
256
253
|
def humanize_node(node)
|
@@ -262,6 +259,30 @@ module RuboCop
|
|
262
259
|
HUMANIZED_NODE_TYPE[node.type] || node.type
|
263
260
|
end
|
264
261
|
|
262
|
+
def dynamic_constant?(node)
|
263
|
+
return false unless node.casgn_type? && node.namespace.nil?
|
264
|
+
|
265
|
+
expression = node.expression
|
266
|
+
expression.send_type? &&
|
267
|
+
!(expression.method?(:freeze) && expression.receiver&.recursive_basic_literal?)
|
268
|
+
end
|
269
|
+
|
270
|
+
def private_constant?(node)
|
271
|
+
return false unless node.casgn_type? && node.namespace.nil?
|
272
|
+
return false unless (parent = node.parent)
|
273
|
+
|
274
|
+
parent.each_child_node(:send) do |child_node|
|
275
|
+
return true if marked_as_private_constant?(child_node, node.name)
|
276
|
+
end
|
277
|
+
false
|
278
|
+
end
|
279
|
+
|
280
|
+
def marked_as_private_constant?(node, name)
|
281
|
+
return false unless node.method?(:private_constant)
|
282
|
+
|
283
|
+
node.arguments.any? { |arg| (arg.sym_type? || arg.str_type?) && arg.value == name }
|
284
|
+
end
|
285
|
+
|
265
286
|
def source_range_with_comment(node)
|
266
287
|
begin_pos, end_pos =
|
267
288
|
if (node.def_type? && !node.method?(:initialize)) ||
|
@@ -144,7 +144,7 @@ module RuboCop
|
|
144
144
|
def expected_column(left_paren, elements)
|
145
145
|
if line_break_after_left_paren?(left_paren, elements)
|
146
146
|
source_indent = processed_source.line_indentation(first_argument_line(elements))
|
147
|
-
new_indent = source_indent -
|
147
|
+
new_indent = source_indent - configured_indentation_width
|
148
148
|
|
149
149
|
new_indent.negative? ? 0 : new_indent
|
150
150
|
elsif all_elements_aligned?(elements)
|
@@ -157,7 +157,7 @@ module RuboCop
|
|
157
157
|
def all_elements_aligned?(elements)
|
158
158
|
elements.flat_map do |e|
|
159
159
|
if e.hash_type?
|
160
|
-
e.
|
160
|
+
e.each_child_node.map { |child| child.loc.column }
|
161
161
|
else
|
162
162
|
e.loc.column
|
163
163
|
end
|
@@ -184,10 +184,6 @@ module RuboCop
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
-
def indentation_width
|
188
|
-
@config.for_cop('Layout/IndentationWidth')['Width'] || 2
|
189
|
-
end
|
190
|
-
|
191
187
|
def line_break_after_left_paren?(left_paren, elements)
|
192
188
|
elements.first && elements.first.loc.line > left_paren.line
|
193
189
|
end
|
@@ -154,7 +154,9 @@ module RuboCop
|
|
154
154
|
end
|
155
155
|
|
156
156
|
def less_indented?(line)
|
157
|
-
|
157
|
+
rule = config.for_cop('Layout/AccessModifierIndentation')['EnforcedStyle'] == 'outdent'
|
158
|
+
access_modifier = 'private|protected|public'
|
159
|
+
/\A\s*(end\b|[)}\]])/.match?(line) || (rule && /\A\s*(#{access_modifier})\b/.match?(line))
|
158
160
|
end
|
159
161
|
|
160
162
|
def two_alternatives?(line)
|
@@ -27,6 +27,8 @@ module RuboCop
|
|
27
27
|
|
28
28
|
def on_new_investigation
|
29
29
|
return if processed_source.tokens.empty?
|
30
|
+
# Quick check if we possibly have consecutive blank lines.
|
31
|
+
return unless processed_source.raw_source.include?("\n\n\n")
|
30
32
|
|
31
33
|
lines = Set.new
|
32
34
|
processed_source.each_token { |token| lines << token.line }
|
@@ -119,12 +119,16 @@ module RuboCop
|
|
119
119
|
def ignored_ranges(ast)
|
120
120
|
return [] unless ast
|
121
121
|
|
122
|
-
@ignored_ranges ||=
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
122
|
+
@ignored_ranges ||= begin
|
123
|
+
ranges = []
|
124
|
+
on_node(:pair, ast) do |pair|
|
125
|
+
next if pair.parent.single_line?
|
126
|
+
|
127
|
+
key, value = *pair
|
128
|
+
ranges << (key.source_range.end_pos...value.source_range.begin_pos)
|
129
|
+
end
|
130
|
+
ranges
|
131
|
+
end
|
128
132
|
end
|
129
133
|
|
130
134
|
def force_equal_sign_alignment?
|
@@ -6,17 +6,49 @@ module RuboCop
|
|
6
6
|
# Checks for a line break before the first element in a
|
7
7
|
# multi-line array.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example AllowMultilineFinalElement: false (default)
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# [ :a,
|
13
|
+
# :b]
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# [ :a, {
|
17
|
+
# :b => :c
|
18
|
+
# }]
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# [:a, :b]
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# [
|
25
|
+
# :a,
|
26
|
+
# :b]
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# [
|
30
|
+
# :a, {
|
31
|
+
# :b => :c
|
32
|
+
# }]
|
33
|
+
#
|
34
|
+
# @example AllowMultilineFinalElement: true
|
10
35
|
#
|
11
36
|
# # bad
|
12
37
|
# [ :a,
|
13
38
|
# :b]
|
14
39
|
#
|
15
40
|
# # good
|
41
|
+
# [ :a, {
|
42
|
+
# :b => :c
|
43
|
+
# }]
|
44
|
+
#
|
45
|
+
# # good
|
16
46
|
# [
|
17
47
|
# :a,
|
18
48
|
# :b]
|
19
49
|
#
|
50
|
+
# # good
|
51
|
+
# [:a, :b]
|
20
52
|
class FirstArrayElementLineBreak < Base
|
21
53
|
include FirstElementLineBreak
|
22
54
|
extend AutoCorrector
|
@@ -26,7 +58,7 @@ module RuboCop
|
|
26
58
|
def on_array(node)
|
27
59
|
return if !node.loc.begin && !assignment_on_same_line?(node)
|
28
60
|
|
29
|
-
check_children_line_break(node, node.children)
|
61
|
+
check_children_line_break(node, node.children, ignore_last: ignore_last_element?)
|
30
62
|
end
|
31
63
|
|
32
64
|
private
|
@@ -35,6 +67,10 @@ module RuboCop
|
|
35
67
|
source = node.source_range.source_line[0...node.loc.column]
|
36
68
|
/\s*=\s*$/.match?(source)
|
37
69
|
end
|
70
|
+
|
71
|
+
def ignore_last_element?
|
72
|
+
!!cop_config['AllowMultilineFinalElement']
|
73
|
+
end
|
38
74
|
end
|
39
75
|
end
|
40
76
|
end
|
@@ -6,16 +6,55 @@ module RuboCop
|
|
6
6
|
# Checks for a line break before the first element in a
|
7
7
|
# multi-line hash.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example AllowMultilineFinalElement: false (default)
|
10
10
|
#
|
11
11
|
# # bad
|
12
12
|
# { a: 1,
|
13
13
|
# b: 2}
|
14
14
|
#
|
15
|
+
# # bad
|
16
|
+
# { a: 1, b: {
|
17
|
+
# c: 3
|
18
|
+
# }}
|
19
|
+
#
|
15
20
|
# # good
|
16
21
|
# {
|
17
22
|
# a: 1,
|
18
23
|
# b: 2 }
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# {
|
27
|
+
# a: 1, b: {
|
28
|
+
# c: 3
|
29
|
+
# }}
|
30
|
+
#
|
31
|
+
# @example AllowMultilineFinalElement: true
|
32
|
+
#
|
33
|
+
# # bad
|
34
|
+
# { a: 1,
|
35
|
+
# b: 2}
|
36
|
+
#
|
37
|
+
# # bad
|
38
|
+
# { a: 1,
|
39
|
+
# b: {
|
40
|
+
# c: 3
|
41
|
+
# }}
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# { a: 1, b: {
|
45
|
+
# c: 3
|
46
|
+
# }}
|
47
|
+
#
|
48
|
+
# # good
|
49
|
+
# {
|
50
|
+
# a: 1,
|
51
|
+
# b: 2 }
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# {
|
55
|
+
# a: 1, b: {
|
56
|
+
# c: 3
|
57
|
+
# }}
|
19
58
|
class FirstHashElementLineBreak < Base
|
20
59
|
include FirstElementLineBreak
|
21
60
|
extend AutoCorrector
|
@@ -25,7 +64,15 @@ module RuboCop
|
|
25
64
|
def on_hash(node)
|
26
65
|
# node.loc.begin tells us whether the hash opens with a {
|
27
66
|
# If it doesn't, Style/FirstMethodArgumentLineBreak will handle it
|
28
|
-
|
67
|
+
return unless node.loc.begin
|
68
|
+
|
69
|
+
check_children_line_break(node, node.children, ignore_last: ignore_last_element?)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def ignore_last_element?
|
75
|
+
!!cop_config['AllowMultilineFinalElement']
|
29
76
|
end
|
30
77
|
end
|
31
78
|
end
|
@@ -6,17 +6,70 @@ module RuboCop
|
|
6
6
|
# Checks for a line break before the first argument in a
|
7
7
|
# multi-line method call.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example AllowMultilineFinalElement: false (default)
|
10
10
|
#
|
11
11
|
# # bad
|
12
12
|
# method(foo, bar,
|
13
13
|
# baz)
|
14
14
|
#
|
15
|
+
# # bad
|
16
|
+
# method(foo, bar, {
|
17
|
+
# baz: "a",
|
18
|
+
# qux: "b",
|
19
|
+
# })
|
20
|
+
#
|
15
21
|
# # good
|
16
22
|
# method(
|
17
23
|
# foo, bar,
|
18
24
|
# baz)
|
19
25
|
#
|
26
|
+
# # good
|
27
|
+
# method(
|
28
|
+
# foo, bar, {
|
29
|
+
# baz: "a",
|
30
|
+
# qux: "b",
|
31
|
+
# })
|
32
|
+
#
|
33
|
+
# # ignored
|
34
|
+
# method foo, bar,
|
35
|
+
# baz
|
36
|
+
#
|
37
|
+
# @example AllowMultilineFinalElement: true
|
38
|
+
#
|
39
|
+
# # bad
|
40
|
+
# method(foo, bar,
|
41
|
+
# baz)
|
42
|
+
#
|
43
|
+
# # bad
|
44
|
+
# method(foo,
|
45
|
+
# bar,
|
46
|
+
# {
|
47
|
+
# baz: "a",
|
48
|
+
# qux: "b",
|
49
|
+
# }
|
50
|
+
# )
|
51
|
+
#
|
52
|
+
# # good
|
53
|
+
# method(foo, bar, {
|
54
|
+
# baz: "a",
|
55
|
+
# qux: "b",
|
56
|
+
# })
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# method(
|
60
|
+
# foo, bar,
|
61
|
+
# baz)
|
62
|
+
#
|
63
|
+
# # good
|
64
|
+
# method(
|
65
|
+
# foo,
|
66
|
+
# bar,
|
67
|
+
# {
|
68
|
+
# baz: "a",
|
69
|
+
# qux: "b",
|
70
|
+
# }
|
71
|
+
# )
|
72
|
+
#
|
20
73
|
# # ignored
|
21
74
|
# method foo, bar,
|
22
75
|
# baz
|
@@ -38,10 +91,16 @@ module RuboCop
|
|
38
91
|
last_arg = args.last
|
39
92
|
args.concat(args.pop.children) if last_arg&.hash_type? && !last_arg&.braces?
|
40
93
|
|
41
|
-
check_method_line_break(node, args)
|
94
|
+
check_method_line_break(node, args, ignore_last: ignore_last_element?)
|
42
95
|
end
|
43
96
|
alias on_csend on_send
|
44
97
|
alias on_super on_send
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def ignore_last_element?
|
102
|
+
!!cop_config['AllowMultilineFinalElement']
|
103
|
+
end
|
45
104
|
end
|
46
105
|
end
|
47
106
|
end
|