rubocop 1.32.0 → 1.37.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 +2 -2
- data/config/default.yml +104 -16
- data/config/obsoletion.yml +23 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +2 -2
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +53 -15
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_finder.rb +68 -0
- data/lib/rubocop/config_loader.rb +12 -40
- data/lib/rubocop/config_loader_resolver.rb +1 -5
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +7 -2
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
- data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
- data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +16 -12
- data/lib/rubocop/cop/layout/block_end_newline.rb +35 -5
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +5 -2
- data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
- data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +6 -2
- data/lib/rubocop/cop/layout/line_length.rb +4 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +25 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
- data/lib/rubocop/cop/legacy/corrector.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
- data/lib/rubocop/cop/lint/debugger.rb +26 -16
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +107 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +9 -9
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +6 -6
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
- 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/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +9 -3
- data/lib/rubocop/cop/lint/redundant_with_index.rb +13 -10
- data/lib/rubocop/cop/lint/redundant_with_object.rb +12 -11
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +15 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +27 -3
- data/lib/rubocop/cop/lint/unreachable_loop.rb +9 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +8 -6
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +2 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_length.rb +6 -7
- data/lib/rubocop/cop/metrics/method_length.rb +8 -8
- data/lib/rubocop/cop/mixin/allowed_methods.rb +20 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +17 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +17 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +82 -4
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +10 -6
- data/lib/rubocop/cop/mixin/method_complexity.rb +8 -13
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +4 -5
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +97 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/arguments_forwarding.rb +2 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
- data/lib/rubocop/cop/style/case_equality.rb +40 -10
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
- data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
- data/lib/rubocop/cop/style/collection_compact.rb +6 -1
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -1
- data/lib/rubocop/cop/style/double_negation.rb +2 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +41 -6
- data/lib/rubocop/cop/style/each_with_object.rb +39 -8
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
- data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
- 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/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +21 -8
- data/lib/rubocop/cop/style/guard_clause.rb +27 -16
- data/lib/rubocop/cop/style/hash_each_methods.rb +3 -1
- data/lib/rubocop/cop/style/hash_except.rb +0 -4
- data/lib/rubocop/cop/style/hash_syntax.rb +17 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -6
- data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +15 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/next.rb +3 -5
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
- data/lib/rubocop/cop/style/object_then.rb +2 -0
- data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
- data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
- data/lib/rubocop/cop/style/proc.rb +4 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +3 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +24 -6
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +19 -22
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_self.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
- data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
- data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +14 -5
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +3 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +38 -12
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
- data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +3 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/ext/range.rb +15 -0
- data/lib/rubocop/feature_loader.rb +94 -0
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +9 -3
- data/lib/rubocop/formatter/html_formatter.rb +3 -3
- data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/options.rb +13 -13
- data/lib/rubocop/result_cache.rb +22 -20
- data/lib/rubocop/rspec/shared_contexts.rb +13 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/server/cache.rb +41 -2
- data/lib/rubocop/server/cli.rb +26 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +2 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -2
- data/lib/rubocop.rb +8 -3
- metadata +20 -9
- data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'erb'
|
4
4
|
require 'yaml'
|
5
5
|
require 'pathname'
|
6
|
+
require_relative 'config_finder'
|
6
7
|
|
7
8
|
module RuboCop
|
8
9
|
# Raised when a RuboCop configuration file is not found.
|
@@ -15,8 +16,7 @@ module RuboCop
|
|
15
16
|
# during a run of the rubocop program, if files in several
|
16
17
|
# directories are inspected.
|
17
18
|
class ConfigLoader
|
18
|
-
DOTFILE =
|
19
|
-
XDG_CONFIG = 'config.yml'
|
19
|
+
DOTFILE = ConfigFinder::DOTFILE
|
20
20
|
RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
|
21
21
|
DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml')
|
22
22
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
|
26
26
|
attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
|
27
27
|
:ignore_unrecognized_cops
|
28
|
-
attr_writer :default_configuration
|
28
|
+
attr_writer :default_configuration
|
29
29
|
attr_reader :loaded_features
|
30
30
|
|
31
31
|
alias debug? debug
|
@@ -95,8 +95,7 @@ module RuboCop
|
|
95
95
|
# user's home directory is checked. If there's no .rubocop.yml
|
96
96
|
# there either, the path to the default file is returned.
|
97
97
|
def configuration_file_for(target_dir)
|
98
|
-
|
99
|
-
find_user_xdg_config || DEFAULT_FILE
|
98
|
+
ConfigFinder.find_config_path(target_dir)
|
100
99
|
end
|
101
100
|
|
102
101
|
def configuration_from_file(config_file, check: true)
|
@@ -122,7 +121,7 @@ module RuboCop
|
|
122
121
|
end
|
123
122
|
|
124
123
|
def add_excludes_from_files(config, config_file)
|
125
|
-
exclusion_file = find_last_file_upwards(DOTFILE, config_file, project_root)
|
124
|
+
exclusion_file = find_last_file_upwards(DOTFILE, config_file, ConfigFinder.project_root)
|
126
125
|
|
127
126
|
return unless exclusion_file
|
128
127
|
return if PathUtil.relative_path(exclusion_file) == PathUtil.relative_path(config_file)
|
@@ -140,8 +139,14 @@ module RuboCop
|
|
140
139
|
|
141
140
|
# Returns the path RuboCop inferred as the root of the project. No file
|
142
141
|
# searches will go past this directory.
|
142
|
+
# @deprecated Use `RuboCop::ConfigFinder.project_root` instead.
|
143
143
|
def project_root
|
144
|
-
|
144
|
+
warn Rainbow(<<~WARNING).yellow
|
145
|
+
`RuboCop::ConfigLoader.project_root` is deprecated and will be removed in RuboCop 2.0. \
|
146
|
+
Use `RuboCop::ConfigFinder.project_root` instead.
|
147
|
+
WARNING
|
148
|
+
|
149
|
+
ConfigFinder.project_root
|
145
150
|
end
|
146
151
|
|
147
152
|
PENDING_BANNER = <<~BANNER
|
@@ -187,39 +192,6 @@ module RuboCop
|
|
187
192
|
File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
|
188
193
|
end
|
189
194
|
|
190
|
-
def find_project_dotfile(target_dir)
|
191
|
-
find_file_upwards(DOTFILE, target_dir, project_root)
|
192
|
-
end
|
193
|
-
|
194
|
-
def find_project_root
|
195
|
-
pwd = Dir.pwd
|
196
|
-
gems_file = find_last_file_upwards('Gemfile', pwd) || find_last_file_upwards('gems.rb', pwd)
|
197
|
-
return unless gems_file
|
198
|
-
|
199
|
-
File.dirname(gems_file)
|
200
|
-
end
|
201
|
-
|
202
|
-
def find_user_dotfile
|
203
|
-
return unless ENV.key?('HOME')
|
204
|
-
|
205
|
-
file = File.join(Dir.home, DOTFILE)
|
206
|
-
return file if File.exist?(file)
|
207
|
-
end
|
208
|
-
|
209
|
-
def find_user_xdg_config
|
210
|
-
xdg_config_home = expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config'))
|
211
|
-
xdg_config = File.join(xdg_config_home, 'rubocop', XDG_CONFIG)
|
212
|
-
return xdg_config if File.exist?(xdg_config)
|
213
|
-
end
|
214
|
-
|
215
|
-
def expand_path(path)
|
216
|
-
File.expand_path(path)
|
217
|
-
rescue ArgumentError
|
218
|
-
# Could happen because HOME or ID could not be determined. Fall back on
|
219
|
-
# using the path literally in that case.
|
220
|
-
path
|
221
|
-
end
|
222
|
-
|
223
195
|
def resolver
|
224
196
|
@resolver ||= ConfigLoaderResolver.new
|
225
197
|
end
|
@@ -11,11 +11,7 @@ module RuboCop
|
|
11
11
|
config_dir = File.dirname(path)
|
12
12
|
hash.delete('require').tap do |loaded_features|
|
13
13
|
Array(loaded_features).each do |feature|
|
14
|
-
|
15
|
-
require(File.join(config_dir, feature))
|
16
|
-
else
|
17
|
-
require(feature)
|
18
|
-
end
|
14
|
+
FeatureLoader.load(config_directory_path: config_dir, feature: feature)
|
19
15
|
end
|
20
16
|
end
|
21
17
|
end
|
@@ -12,6 +12,11 @@ module RuboCop
|
|
12
12
|
|
13
13
|
if alternative
|
14
14
|
"#{base}\n`#{parameter}` has been renamed to `#{alternative.chomp}`."
|
15
|
+
elsif alternatives
|
16
|
+
"#{base}\n`#{parameter}` has been renamed to #{to_sentence(alternatives.map do |item|
|
17
|
+
"`#{item}`"
|
18
|
+
end,
|
19
|
+
connector: 'and/or')}."
|
15
20
|
else
|
16
21
|
"#{base}\n#{reason.chomp}"
|
17
22
|
end
|
@@ -47,10 +47,15 @@ module RuboCop
|
|
47
47
|
|
48
48
|
# Default rules for obsoletions are in config/obsoletion.yml
|
49
49
|
# Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
|
50
|
-
def load_rules
|
50
|
+
def load_rules # rubocop:disable Metrics/AbcSize
|
51
51
|
rules = self.class.files.each_with_object({}) do |filename, hash|
|
52
52
|
hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
|
53
|
-
first
|
53
|
+
case first
|
54
|
+
when Hash
|
55
|
+
first.merge(second)
|
56
|
+
when Array
|
57
|
+
first.concat(second)
|
58
|
+
end
|
54
59
|
end
|
55
60
|
end
|
56
61
|
|
data/lib/rubocop/cop/cop.rb
CHANGED
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
module Cop
|
8
8
|
# @deprecated Use Cop::Base instead
|
9
9
|
# Legacy scaffold for Cops.
|
10
|
-
# See https://docs.rubocop.org/rubocop/
|
10
|
+
# See https://docs.rubocop.org/rubocop/v1_upgrade_notes.html
|
11
11
|
class Cop < Base
|
12
12
|
attr_reader :offenses
|
13
13
|
|
@@ -5,9 +5,15 @@ module RuboCop
|
|
5
5
|
# This autocorrects parentheses
|
6
6
|
class ParenthesesCorrector
|
7
7
|
class << self
|
8
|
+
include RangeHelp
|
9
|
+
|
10
|
+
COMMA_REGEXP = /(?<=\))\s*,/.freeze
|
11
|
+
|
8
12
|
def correct(corrector, node)
|
9
13
|
corrector.remove(node.loc.begin)
|
10
14
|
corrector.remove(node.loc.end)
|
15
|
+
handle_orphaned_comma(corrector, node)
|
16
|
+
|
11
17
|
return unless ternary_condition?(node) && next_char_is_question_mark?(node)
|
12
18
|
|
13
19
|
corrector.insert_after(node.loc.end, ' ')
|
@@ -22,6 +28,58 @@ module RuboCop
|
|
22
28
|
def next_char_is_question_mark?(node)
|
23
29
|
node.loc.last_column == node.parent.loc.question.column
|
24
30
|
end
|
31
|
+
|
32
|
+
def only_closing_paren_before_comma?(node)
|
33
|
+
source_buffer = node.source_range.source_buffer
|
34
|
+
line_range = source_buffer.line_range(node.loc.end.line)
|
35
|
+
|
36
|
+
line_range.source.start_with?(/\s*\)\s*,/)
|
37
|
+
end
|
38
|
+
|
39
|
+
# If removing parentheses leaves a comma on its own line, remove all the whitespace
|
40
|
+
# preceding it to prevent a syntax error.
|
41
|
+
def handle_orphaned_comma(corrector, node)
|
42
|
+
return unless only_closing_paren_before_comma?(node)
|
43
|
+
|
44
|
+
range = extend_range_for_heredoc(node, parens_range(node))
|
45
|
+
corrector.remove(range)
|
46
|
+
|
47
|
+
add_heredoc_comma(corrector, node)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get a range for the closing parenthesis and all whitespace to the left of it
|
51
|
+
def parens_range(node)
|
52
|
+
range_with_surrounding_space(
|
53
|
+
range: node.loc.end,
|
54
|
+
buffer: node.source_range.source_buffer,
|
55
|
+
side: :left,
|
56
|
+
newlines: true,
|
57
|
+
whitespace: true,
|
58
|
+
continuations: true
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
# If the node contains a heredoc, remove the comma too
|
63
|
+
# It'll be added back in the right place later
|
64
|
+
def extend_range_for_heredoc(node, range)
|
65
|
+
return range unless heredoc?(node)
|
66
|
+
|
67
|
+
comma_line = range_by_whole_lines(node.loc.end, buffer: node.source_range.source_buffer)
|
68
|
+
offset = comma_line.source.match(COMMA_REGEXP)[0]&.size || 0
|
69
|
+
|
70
|
+
range.adjust(end_pos: offset)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Add a comma back after the heredoc identifier
|
74
|
+
def add_heredoc_comma(corrector, node)
|
75
|
+
return unless heredoc?(node)
|
76
|
+
|
77
|
+
corrector.insert_after(node.child_nodes.last.loc.expression, ',')
|
78
|
+
end
|
79
|
+
|
80
|
+
def heredoc?(node)
|
81
|
+
node.child_nodes.last.loc.is_a?(Parser::Source::Map::Heredoc)
|
82
|
+
end
|
25
83
|
end
|
26
84
|
end
|
27
85
|
end
|
@@ -84,7 +84,7 @@ module RuboCop
|
|
84
84
|
(str "true")
|
85
85
|
PATTERN
|
86
86
|
|
87
|
-
def on_block(node) # rubocop:disable Metrics/MethodLength
|
87
|
+
def on_block(node) # rubocop:disable Metrics/MethodLength, InternalAffairs/NumblockHandler
|
88
88
|
gem_specification(node) do |block_var|
|
89
89
|
metadata_value = metadata(node)
|
90
90
|
mfa_value = mfa_value(metadata_value)
|
@@ -55,8 +55,8 @@ module RuboCop
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
def require_path_fragments(
|
59
|
-
path =
|
58
|
+
def require_path_fragments(require_directive)
|
59
|
+
path = require_directive.match(REQUIRE_PATH)
|
60
60
|
|
61
61
|
path ? path.captures.first.split('/') : []
|
62
62
|
end
|
@@ -206,9 +206,8 @@ module RuboCop
|
|
206
206
|
end
|
207
207
|
|
208
208
|
def snake_case(camel_case_string)
|
209
|
-
return 'rspec' if camel_case_string == 'RSpec'
|
210
|
-
|
211
209
|
camel_case_string
|
210
|
+
.gsub('RSpec', 'Rspec')
|
212
211
|
.gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2')
|
213
212
|
.gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2')
|
214
213
|
.downcase
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Checks for missing `numblock handlers. The blocks with numbered
|
7
|
+
# arguments introduced in Ruby 2.7 are parsed with a node type of
|
8
|
+
# `numblock` instead of block. Cops that define `block` handlers
|
9
|
+
# need to define `numblock` handlers or disable this cope for them.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# class BlockRelatedCop < Base
|
15
|
+
# def on_block(node)
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# class BlockRelatedCop < Base
|
21
|
+
# def on_block(node)
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# alias on_numblock on_block
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# class BlockRelatedCop < Base
|
28
|
+
# def on_block(node)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# alias_method :on_numblock, :on_block
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# class BlockRelatedCop < Base
|
35
|
+
# def on_block(node)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# def on_numblock(node)
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
class NumblockHandler < Base
|
42
|
+
MSG = 'Define on_numblock to handle blocks with numbered arguments.'
|
43
|
+
|
44
|
+
def on_def(node)
|
45
|
+
return unless block_handler?(node)
|
46
|
+
return unless node.parent
|
47
|
+
|
48
|
+
add_offense(node) unless numblock_handler?(node.parent)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# @!method block_handler?(node)
|
54
|
+
def_node_matcher :block_handler?, <<~PATTERN
|
55
|
+
(def :on_block (args (arg :node)) ...)
|
56
|
+
PATTERN
|
57
|
+
|
58
|
+
# @!method numblock_handler?(node)
|
59
|
+
def_node_matcher :numblock_handler?, <<~PATTERN
|
60
|
+
{
|
61
|
+
`(def :on_numblock (args (arg :node)) ...)
|
62
|
+
`(alias (sym :on_numblock) (sym :on_block))
|
63
|
+
`(send nil? :alias_method (sym :on_numblock) (sym :on_block))
|
64
|
+
}
|
65
|
+
PATTERN
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InternalAffairs
|
6
|
+
# Enforces the use of `node.single_line?` instead of
|
7
|
+
# comparing `first_line` and `last_line` for equality.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# node.loc.first_line == node.loc.last_line
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# node.loc.last_line == node.loc.first_line
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# node.loc.line == node.loc.last_line
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
# node.loc.last_line == node.loc.line
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# node.first_line == node.last_line
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# node.single_line?
|
27
|
+
#
|
28
|
+
class SingleLineComparison < Base
|
29
|
+
extend AutoCorrector
|
30
|
+
|
31
|
+
MSG = 'Use `%<preferred>s`.'
|
32
|
+
RESTRICT_ON_SEND = %i[== !=].freeze
|
33
|
+
|
34
|
+
# @!method single_line_comparison(node)
|
35
|
+
def_node_matcher :single_line_comparison, <<~PATTERN
|
36
|
+
{
|
37
|
+
(send (send $_receiver {:line :first_line}) {:== :!=} (send _receiver :last_line))
|
38
|
+
(send (send $_receiver :last_line) {:== :!=} (send _receiver {:line :first_line}))
|
39
|
+
}
|
40
|
+
PATTERN
|
41
|
+
|
42
|
+
def on_send(node)
|
43
|
+
return unless (receiver = single_line_comparison(node))
|
44
|
+
|
45
|
+
bang = node.method?(:!=) ? '!' : ''
|
46
|
+
preferred = "#{bang}#{extract_receiver(receiver)}.single_line?"
|
47
|
+
|
48
|
+
add_offense(node, message: format(MSG, preferred: preferred)) do |corrector|
|
49
|
+
corrector.replace(node, preferred)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def extract_receiver(node)
|
56
|
+
node = node.receiver if node.send_type? && %i[loc source_range].include?(node.method_name)
|
57
|
+
node.source
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -10,6 +10,7 @@ require_relative 'internal_affairs/method_name_equal'
|
|
10
10
|
require_relative 'internal_affairs/node_destructuring'
|
11
11
|
require_relative 'internal_affairs/node_matcher_directive'
|
12
12
|
require_relative 'internal_affairs/node_type_predicate'
|
13
|
+
require_relative 'internal_affairs/numblock_handler'
|
13
14
|
require_relative 'internal_affairs/offense_location_keyword'
|
14
15
|
require_relative 'internal_affairs/redundant_context_config_parameter'
|
15
16
|
require_relative 'internal_affairs/redundant_described_class_as_subject'
|
@@ -17,6 +18,7 @@ require_relative 'internal_affairs/redundant_let_rubocop_config_new'
|
|
17
18
|
require_relative 'internal_affairs/redundant_location_argument'
|
18
19
|
require_relative 'internal_affairs/redundant_message_argument'
|
19
20
|
require_relative 'internal_affairs/redundant_method_dispatch_node'
|
21
|
+
require_relative 'internal_affairs/single_line_comparison'
|
20
22
|
require_relative 'internal_affairs/style_detected_api_use'
|
21
23
|
require_relative 'internal_affairs/undefined_config'
|
22
24
|
require_relative 'internal_affairs/useless_message_assertion'
|
@@ -22,23 +22,24 @@ module RuboCop
|
|
22
22
|
# # bad
|
23
23
|
#
|
24
24
|
# foo.bar
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
25
|
+
# .each do
|
26
|
+
# baz
|
27
|
+
# end
|
28
28
|
#
|
29
29
|
# # good
|
30
30
|
#
|
31
|
-
#
|
32
|
-
#
|
31
|
+
# foo.bar
|
32
|
+
# .each do
|
33
|
+
# baz
|
33
34
|
# end
|
34
35
|
#
|
35
36
|
# @example EnforcedStyleAlignWith: start_of_block
|
36
37
|
# # bad
|
37
38
|
#
|
38
39
|
# foo.bar
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
40
|
+
# .each do
|
41
|
+
# baz
|
42
|
+
# end
|
42
43
|
#
|
43
44
|
# # good
|
44
45
|
#
|
@@ -51,16 +52,17 @@ module RuboCop
|
|
51
52
|
# # bad
|
52
53
|
#
|
53
54
|
# foo.bar
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
55
|
+
# .each do
|
56
|
+
# baz
|
57
|
+
# end
|
57
58
|
#
|
58
59
|
# # good
|
59
60
|
#
|
60
61
|
# foo.bar
|
61
62
|
# .each do
|
62
|
-
#
|
63
|
+
# baz
|
63
64
|
# end
|
65
|
+
#
|
64
66
|
class BlockAlignment < Base
|
65
67
|
include ConfigurableEnforcedStyle
|
66
68
|
include RangeHelp
|
@@ -82,6 +84,8 @@ module RuboCop
|
|
82
84
|
check_block_alignment(start_for_block_node(node), node)
|
83
85
|
end
|
84
86
|
|
87
|
+
alias on_numblock on_block
|
88
|
+
|
85
89
|
def style_parameter_name
|
86
90
|
'EnforcedStyleAlignWith'
|
87
91
|
end
|
@@ -36,24 +36,54 @@ module RuboCop
|
|
36
36
|
# If the end is on its own line, there is no offense
|
37
37
|
return if begins_its_line?(node.loc.end)
|
38
38
|
|
39
|
-
|
40
|
-
corrector.replace(delimiter_range(node), "\n#{node.loc.end.source}#{offset(node)}")
|
41
|
-
end
|
39
|
+
register_offense(node)
|
42
40
|
end
|
43
41
|
|
42
|
+
alias on_numblock on_block
|
43
|
+
|
44
44
|
private
|
45
45
|
|
46
|
+
def register_offense(node)
|
47
|
+
add_offense(node.loc.end, message: message(node)) do |corrector|
|
48
|
+
offense_range = offense_range(node)
|
49
|
+
replacement = "\n#{offense_range.source.strip}"
|
50
|
+
|
51
|
+
if (heredoc = last_heredoc_argument(node.body))
|
52
|
+
corrector.remove(offense_range)
|
53
|
+
corrector.insert_after(heredoc.loc.heredoc_end, replacement)
|
54
|
+
else
|
55
|
+
corrector.replace(offense_range, replacement)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
46
60
|
def message(node)
|
47
61
|
format(MSG, line: node.loc.end.line, column: node.loc.end.column + 1)
|
48
62
|
end
|
49
63
|
|
50
|
-
def
|
64
|
+
def last_heredoc_argument(node)
|
65
|
+
return unless node&.call_type?
|
66
|
+
return unless (arguments = node&.arguments)
|
67
|
+
|
68
|
+
heredoc = arguments.reverse.detect { |arg| arg.str_type? && arg.heredoc? }
|
69
|
+
return heredoc if heredoc
|
70
|
+
|
71
|
+
last_heredoc_argument(node.children.first)
|
72
|
+
end
|
73
|
+
|
74
|
+
def offense_range(node)
|
51
75
|
Parser::Source::Range.new(
|
52
76
|
node.loc.expression.source_buffer,
|
53
77
|
node.children.compact.last.loc.expression.end_pos,
|
54
|
-
node.loc.expression.end_pos
|
78
|
+
end_of_method_chain(node).loc.expression.end_pos
|
55
79
|
)
|
56
80
|
end
|
81
|
+
|
82
|
+
def end_of_method_chain(node)
|
83
|
+
return node unless node.parent&.call_type?
|
84
|
+
|
85
|
+
end_of_method_chain(node.parent)
|
86
|
+
end
|
57
87
|
end
|
58
88
|
end
|
59
89
|
end
|
@@ -80,8 +80,11 @@ module RuboCop
|
|
80
80
|
@block_line = node.source_range.first_line
|
81
81
|
end
|
82
82
|
|
83
|
-
|
84
|
-
|
83
|
+
alias on_numblock on_block
|
84
|
+
|
85
|
+
def on_send(node) # rubocop:disable Metrics/CyclomaticComplexity
|
86
|
+
return unless node.bare_access_modifier? &&
|
87
|
+
!(node.parent&.block_type? || node.parent&.numblock_type?)
|
85
88
|
return if expected_empty_lines?(node)
|
86
89
|
|
87
90
|
message = message(node)
|
@@ -22,20 +22,20 @@ module RuboCop
|
|
22
22
|
# # all platforms.
|
23
23
|
#
|
24
24
|
# # bad
|
25
|
-
# puts 'Hello' # Return character is CR+LF on all
|
25
|
+
# puts 'Hello' # Return character is CR+LF on all platforms.
|
26
26
|
#
|
27
27
|
# # good
|
28
|
-
# puts 'Hello' # Return character is LF on all
|
28
|
+
# puts 'Hello' # Return character is LF on all platforms.
|
29
29
|
#
|
30
30
|
# @example EnforcedStyle: crlf
|
31
31
|
# # The `crlf` style means that CR+LF (Carriage Return + Line Feed) is
|
32
32
|
# # enforced on all platforms.
|
33
33
|
#
|
34
34
|
# # bad
|
35
|
-
# puts 'Hello' # Return character is LF on all
|
35
|
+
# puts 'Hello' # Return character is LF on all platforms.
|
36
36
|
#
|
37
37
|
# # good
|
38
|
-
# puts 'Hello' # Return character is CR+LF on all
|
38
|
+
# puts 'Hello' # Return character is CR+LF on all platforms.
|
39
39
|
#
|
40
40
|
class EndOfLine < Base
|
41
41
|
include ConfigurableEnforcedStyle
|
@@ -153,7 +153,8 @@ module RuboCop
|
|
153
153
|
MSG = 'Indent the first argument one step more than %<base>s.'
|
154
154
|
|
155
155
|
def on_send(node)
|
156
|
-
return if style != :consistent && enforce_first_argument_with_fixed_indentation?
|
156
|
+
return if style != :consistent && enforce_first_argument_with_fixed_indentation? &&
|
157
|
+
!enable_layout_first_method_argument_line_break?
|
157
158
|
return if !node.arguments? || bare_operator?(node) || node.setter_method?
|
158
159
|
|
159
160
|
indent = base_indentation(node) + configured_indentation_width
|
@@ -161,6 +162,7 @@ module RuboCop
|
|
161
162
|
check_alignment([node.first_argument], indent)
|
162
163
|
end
|
163
164
|
alias on_csend on_send
|
165
|
+
alias on_super on_send
|
164
166
|
|
165
167
|
private
|
166
168
|
|
@@ -267,6 +269,10 @@ module RuboCop
|
|
267
269
|
argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
|
268
270
|
end
|
269
271
|
|
272
|
+
def enable_layout_first_method_argument_line_break?
|
273
|
+
config.for_cop('Layout/FirstMethodArgumentLineBreak')['Enabled']
|
274
|
+
end
|
275
|
+
|
270
276
|
def argument_alignment_config
|
271
277
|
config.for_cop('Layout/ArgumentAlignment')
|
272
278
|
end
|
@@ -143,7 +143,7 @@ module RuboCop
|
|
143
143
|
case indent_base_type
|
144
144
|
when :left_brace_or_bracket
|
145
145
|
'the position of the opening bracket'
|
146
|
-
when :
|
146
|
+
when :first_column_after_left_parenthesis
|
147
147
|
'the first position after the preceding left parenthesis'
|
148
148
|
when :parent_hash_key
|
149
149
|
'the parent hash key'
|
@@ -164,7 +164,7 @@ module RuboCop
|
|
164
164
|
case indent_base_type
|
165
165
|
when :left_brace_or_bracket
|
166
166
|
'Indent the right bracket the same as the left bracket.'
|
167
|
-
when :
|
167
|
+
when :first_column_after_left_parenthesis
|
168
168
|
'Indent the right bracket the same as the first position ' \
|
169
169
|
'after the preceding left parenthesis.'
|
170
170
|
when :parent_hash_key
|
@@ -192,7 +192,7 @@ module RuboCop
|
|
192
192
|
case indent_base_type
|
193
193
|
when :left_brace_or_bracket
|
194
194
|
'the position of the opening brace'
|
195
|
-
when :
|
195
|
+
when :first_column_after_left_parenthesis
|
196
196
|
'the first position after the preceding left parenthesis'
|
197
197
|
when :parent_hash_key
|
198
198
|
'the parent hash key'
|
@@ -213,7 +213,7 @@ module RuboCop
|
|
213
213
|
case indent_base_type
|
214
214
|
when :left_brace_or_bracket
|
215
215
|
'Indent the right brace the same as the left brace.'
|
216
|
-
when :
|
216
|
+
when :first_column_after_left_parenthesis
|
217
217
|
'Indent the right brace the same as the first position ' \
|
218
218
|
'after the preceding left parenthesis.'
|
219
219
|
when :parent_hash_key
|