rubocop 1.71.2 → 1.72.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +28 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +40 -8
- data/lib/rubocop/config_loader_resolver.rb +21 -7
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
- data/lib/rubocop/cop/internal_affairs.rb +1 -16
- data/lib/rubocop/cop/layout/block_alignment.rb +2 -0
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +22 -2
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +221 -0
- data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +74 -0
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
- data/lib/rubocop/cop/mixin/alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +18 -18
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +3 -3
- data/lib/rubocop/cop/mixin/string_help.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
- data/lib/rubocop/cop/style/redundant_format.rb +222 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +17 -3
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/format_string.rb +7 -5
- data/lib/rubocop/directive_comment.rb +35 -2
- data/lib/rubocop/lsp/runtime.rb +2 -0
- data/lib/rubocop/lsp/server.rb +0 -2
- data/lib/rubocop/options.rb +26 -11
- data/lib/rubocop/path_util.rb +4 -0
- data/lib/rubocop/plugin/configuration_integrator.rb +141 -0
- data/lib/rubocop/plugin/load_error.rb +35 -0
- data/lib/rubocop/plugin/loader.rb +100 -0
- data/lib/rubocop/plugin/not_supported_error.rb +29 -0
- data/lib/rubocop/plugin.rb +39 -0
- data/lib/rubocop/rake_task.rb +4 -1
- data/lib/rubocop/server/cache.rb +35 -2
- data/lib/rubocop/server/cli.rb +2 -2
- data/lib/rubocop/version.rb +17 -2
- data/lib/rubocop.rb +5 -0
- data/lib/ruby_lsp/rubocop/addon.rb +7 -10
- data/lib/ruby_lsp/rubocop/{wraps_built_in_lsp_runtime.rb → runtime_adapter.rb} +5 -8
- metadata +35 -9
data/lib/rubocop/lsp/server.rb
CHANGED
@@ -22,8 +22,6 @@ module RuboCop
|
|
22
22
|
def initialize(config_store)
|
23
23
|
$PROGRAM_NAME = "rubocop --lsp #{ConfigFinder.project_root}"
|
24
24
|
|
25
|
-
RuboCop::LSP.enable
|
26
|
-
|
27
25
|
@reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
|
28
26
|
@writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
|
29
27
|
@runtime = RuboCop::LSP::Runtime.new(config_store)
|
data/lib/rubocop/options.rb
CHANGED
@@ -243,6 +243,7 @@ module RuboCop
|
|
243
243
|
option(opts, '--init')
|
244
244
|
option(opts, '-c', '--config FILE')
|
245
245
|
option(opts, '-d', '--debug')
|
246
|
+
option(opts, '--plugin FILE') { |f| plugin_feature(f) }
|
246
247
|
option(opts, '-r', '--require FILE') { |f| require_feature(f) }
|
247
248
|
option(opts, '--[no-]color')
|
248
249
|
option(opts, '-v', '--version')
|
@@ -299,11 +300,25 @@ module RuboCop
|
|
299
300
|
long_opt[2..].sub('[no-]', '').sub(/ .*/, '').tr('-', '_').gsub(/[\[\]]/, '').to_sym
|
300
301
|
end
|
301
302
|
|
302
|
-
def
|
303
|
-
# If any features were added on the CLI from `--
|
303
|
+
def plugin_feature(file)
|
304
|
+
# If any features were added on the CLI from `--plugin`,
|
304
305
|
# add them to the config.
|
305
|
-
|
306
|
-
|
306
|
+
ConfigLoaderResolver.new.resolve_plugins(Config.new, file)
|
307
|
+
end
|
308
|
+
|
309
|
+
def require_feature(file)
|
310
|
+
if Plugin.plugin_capable?(file)
|
311
|
+
# NOTE: Compatibility for before plugins style.
|
312
|
+
warn Rainbow(<<~MESSAGE).yellow
|
313
|
+
#{file} gem supports plugin, use `--plugin` instead of `--require`.
|
314
|
+
MESSAGE
|
315
|
+
plugin_feature(file)
|
316
|
+
else
|
317
|
+
# If any features were added on the CLI from `--require`,
|
318
|
+
# add them to the config.
|
319
|
+
require file
|
320
|
+
ConfigLoader.add_loaded_features(file)
|
321
|
+
end
|
307
322
|
end
|
308
323
|
end
|
309
324
|
|
@@ -397,7 +412,7 @@ module RuboCop
|
|
397
412
|
return if @options[:format] == 'junit'
|
398
413
|
|
399
414
|
raise OptionArgumentError,
|
400
|
-
|
415
|
+
'--display-only-failed can only be used together with --format junit.'
|
401
416
|
end
|
402
417
|
|
403
418
|
def validate_display_only_correctable_and_autocorrect
|
@@ -415,14 +430,13 @@ module RuboCop
|
|
415
430
|
!@options.key?(:display_only_safe_correctable)
|
416
431
|
|
417
432
|
raise OptionArgumentError,
|
418
|
-
|
433
|
+
'--display-only-failed cannot be used together with other display options.'
|
419
434
|
end
|
420
435
|
|
421
436
|
def validate_lsp_and_editor_mode
|
422
437
|
return if !@options.key?(:lsp) || !@options.key?(:editor_mode)
|
423
438
|
|
424
|
-
raise OptionArgumentError,
|
425
|
-
format('Do not specify `--editor-mode` as it is redundant in `--lsp`.')
|
439
|
+
raise OptionArgumentError, 'Do not specify `--editor-mode` as it is redundant in `--lsp`.'
|
426
440
|
end
|
427
441
|
|
428
442
|
def validate_autocorrect
|
@@ -436,7 +450,7 @@ module RuboCop
|
|
436
450
|
return unless @options.key?(:disable_uncorrectable)
|
437
451
|
|
438
452
|
raise OptionArgumentError,
|
439
|
-
|
453
|
+
'--disable-uncorrectable can only be used together with --autocorrect.'
|
440
454
|
end
|
441
455
|
|
442
456
|
def disable_parallel_when_invalid_option_combo
|
@@ -504,6 +518,7 @@ module RuboCop
|
|
504
518
|
only_guide_cops: ['Run only cops for rules that link to a',
|
505
519
|
'style guide.'],
|
506
520
|
except: 'Exclude the given cop(s).',
|
521
|
+
plugin: 'Load a RuboCop plugin.',
|
507
522
|
require: 'Require Ruby file.',
|
508
523
|
config: 'Specify configuration file.',
|
509
524
|
auto_gen_config: ['Generate a configuration file acting as a',
|
@@ -542,8 +557,8 @@ module RuboCop
|
|
542
557
|
only_recognized_file_types: ['Inspect files given on the command line only if',
|
543
558
|
'they are listed in `AllCops/Include` parameters',
|
544
559
|
'of user configuration or default configuration.'],
|
545
|
-
ignore_disable_comments: ['
|
546
|
-
'
|
560
|
+
ignore_disable_comments: ['Report offenses even if they have been manually disabled',
|
561
|
+
'with a `rubocop:disable` or `rubocop:todo` directive.'],
|
547
562
|
ignore_parent_exclusion: ['Prevent from inheriting `AllCops/Exclude` from',
|
548
563
|
'parent folders.'],
|
549
564
|
ignore_unrecognized_cops: ['Ignore unrecognized cops or departments in the config.'],
|
data/lib/rubocop/path_util.rb
CHANGED
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'lint_roller/context'
|
4
|
+
require_relative 'not_supported_error'
|
5
|
+
|
6
|
+
module RuboCop
|
7
|
+
module Plugin
|
8
|
+
# A class for integrating plugin configurations into RuboCop.
|
9
|
+
# Handles configuration merging, validation, and compatibility for plugins.
|
10
|
+
# @api private
|
11
|
+
class ConfigurationIntegrator
|
12
|
+
class << self
|
13
|
+
def integrate_plugins_into_rubocop_config(rubocop_config, plugins)
|
14
|
+
default_config = ConfigLoader.default_configuration
|
15
|
+
runner_context = create_context(rubocop_config)
|
16
|
+
|
17
|
+
validate_plugins!(plugins, runner_context)
|
18
|
+
|
19
|
+
plugin_config = combine_rubocop_configs(default_config, runner_context, plugins).to_h
|
20
|
+
|
21
|
+
merge_plugin_config_into_all_cops!(default_config, plugin_config)
|
22
|
+
merge_plugin_config_into_default_config!(default_config, plugin_config)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_context(rubocop_config)
|
28
|
+
LintRoller::Context.new(
|
29
|
+
runner: :rubocop,
|
30
|
+
runner_version: Version.version,
|
31
|
+
engine: :rubocop,
|
32
|
+
engine_version: Version.version,
|
33
|
+
target_ruby_version: rubocop_config.target_ruby_version
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_plugins!(plugins, runner_context)
|
38
|
+
unsupported_plugins = plugins.reject { |plugin| plugin.supported?(runner_context) }
|
39
|
+
return if unsupported_plugins.none?
|
40
|
+
|
41
|
+
raise Plugin::NotSupportedError, unsupported_plugins
|
42
|
+
end
|
43
|
+
|
44
|
+
def combine_rubocop_configs(default_config, runner_context, plugins)
|
45
|
+
fake_out_rubocop_default_configuration(default_config) do |fake_config|
|
46
|
+
all_cop_keys_configured_by_plugins = []
|
47
|
+
|
48
|
+
plugins.reduce(fake_config) do |combined_config, plugin|
|
49
|
+
RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, combined_config)
|
50
|
+
|
51
|
+
print 'Plugin ' if ConfigLoader.debug
|
52
|
+
|
53
|
+
plugin_config, plugin_config_path = load_plugin_rubocop_config(plugin, runner_context)
|
54
|
+
|
55
|
+
plugin_config['AllCops'], all_cop_keys_configured_by_plugins = merge_all_cop_settings(
|
56
|
+
combined_config['AllCops'], plugin_config['AllCops'],
|
57
|
+
all_cop_keys_configured_by_plugins
|
58
|
+
)
|
59
|
+
|
60
|
+
ConfigLoader.merge_with_default(plugin_config, plugin_config_path)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def merge_plugin_config_into_all_cops!(rubocop_config, plugin_config)
|
66
|
+
rubocop_config['AllCops'].merge!(plugin_config['AllCops'])
|
67
|
+
end
|
68
|
+
|
69
|
+
def merge_plugin_config_into_default_config!(default_config, plugin_config)
|
70
|
+
plugin_config.each do |key, value|
|
71
|
+
default_config[key] = if default_config[key].is_a?(Hash)
|
72
|
+
resolver.merge(default_config[key], value)
|
73
|
+
else
|
74
|
+
value
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def fake_out_rubocop_default_configuration(default_config)
|
80
|
+
orig_default_config = ConfigLoader.instance_variable_get(:@default_configuration)
|
81
|
+
|
82
|
+
result = yield default_config
|
83
|
+
|
84
|
+
ConfigLoader.instance_variable_set(:@default_configuration, orig_default_config)
|
85
|
+
|
86
|
+
result
|
87
|
+
end
|
88
|
+
|
89
|
+
# rubocop:disable Metrics/AbcSize
|
90
|
+
def load_plugin_rubocop_config(plugin, runner_context)
|
91
|
+
rules = plugin.rules(runner_context)
|
92
|
+
|
93
|
+
case rules.type
|
94
|
+
when :path
|
95
|
+
[ConfigLoader.load_file(rules.value, check: false), rules.value]
|
96
|
+
when :object
|
97
|
+
path = plugin.method(:rules).source_location[0]
|
98
|
+
[Config.create(rules.value, path, check: true), path]
|
99
|
+
when :error
|
100
|
+
plugin_name = plugin.about&.name || plugin.inspect
|
101
|
+
error_message = rules.value.respond_to?(:message) ? rules.value.message : rules.value
|
102
|
+
|
103
|
+
raise "Plugin `#{plugin_name}' failed to load with error: #{error_message}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
# rubocop:enable Metrics/AbcSize
|
107
|
+
|
108
|
+
# This is how we ensure "first-in wins": plugins can override AllCops settings that are
|
109
|
+
# set by RuboCop's default configuration, but once a plugin sets an AllCop setting, they
|
110
|
+
# have exclusive first-in-wins rights to that setting.
|
111
|
+
#
|
112
|
+
# The one exception to this are array fields, because we don't want to
|
113
|
+
# overwrite the AllCops defaults but rather munge the arrays (`existing |
|
114
|
+
# new`) to allow plugins to add to the array, for example Include and
|
115
|
+
# Exclude paths and patterns.
|
116
|
+
def merge_all_cop_settings(existing_all_cops, new_all_cops, already_configured_keys)
|
117
|
+
return [existing_all_cops, already_configured_keys] unless new_all_cops.is_a?(Hash)
|
118
|
+
|
119
|
+
combined_all_cops = existing_all_cops.dup
|
120
|
+
combined_configured_keys = already_configured_keys.dup
|
121
|
+
|
122
|
+
new_all_cops.each do |key, value|
|
123
|
+
if combined_all_cops[key].is_a?(Array) && value.is_a?(Array)
|
124
|
+
combined_all_cops[key] |= value
|
125
|
+
combined_configured_keys |= [key]
|
126
|
+
elsif !combined_configured_keys.include?(key)
|
127
|
+
combined_all_cops[key] = value
|
128
|
+
combined_configured_keys << key
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
[combined_all_cops, combined_configured_keys]
|
133
|
+
end
|
134
|
+
|
135
|
+
def resolver
|
136
|
+
@resolver ||= ConfigLoaderResolver.new
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Plugin
|
5
|
+
# An exception raised when a plugin fails to load.
|
6
|
+
# @api private
|
7
|
+
class LoadError < Error
|
8
|
+
def initialize(plugin_name)
|
9
|
+
super
|
10
|
+
|
11
|
+
@plugin_name = plugin_name
|
12
|
+
end
|
13
|
+
|
14
|
+
def message
|
15
|
+
<<~MESSAGE
|
16
|
+
Failed loading plugin `#{@plugin_name}` because we couldn't determine the corresponding plugin class to instantiate.
|
17
|
+
First, try upgrading it. If the issue persists, please check with the developer regarding the following points.
|
18
|
+
|
19
|
+
RuboCop plugin class names must either be:
|
20
|
+
|
21
|
+
- If the plugin is a gem, defined in the gemspec as `default_lint_roller_plugin'
|
22
|
+
|
23
|
+
spec.metadata['default_lint_roller_plugin'] = 'MyModule::Plugin'
|
24
|
+
|
25
|
+
- Set in YAML as `plugin_class_name'; example:
|
26
|
+
|
27
|
+
plugins:
|
28
|
+
- incomplete:
|
29
|
+
require_path: my_module/plugin
|
30
|
+
plugin_class_name: "MyModule::Plugin"
|
31
|
+
MESSAGE
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../feature_loader'
|
4
|
+
require_relative 'load_error'
|
5
|
+
|
6
|
+
module RuboCop
|
7
|
+
module Plugin
|
8
|
+
# A class for loading and resolving plugins.
|
9
|
+
# @api private
|
10
|
+
class Loader
|
11
|
+
# rubocop:disable Layout/LineLength
|
12
|
+
DEFAULT_PLUGIN_CONFIG = {
|
13
|
+
'enabled' => true,
|
14
|
+
'require_path' => nil, # If not set, will be set to the plugin name
|
15
|
+
'plugin_class_name' => nil # If not set, looks for gemspec `spec.metadata["default_lint_roller_plugin"]`
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
# rubocop:enable Layout/LineLength
|
19
|
+
class << self
|
20
|
+
def load(plugins)
|
21
|
+
normalized_plugin_configs = normalize(plugins)
|
22
|
+
normalized_plugin_configs.filter_map do |plugin_name, plugin_config|
|
23
|
+
next unless plugin_config['enabled']
|
24
|
+
|
25
|
+
plugin_class = constantize_plugin_from(plugin_name, plugin_config)
|
26
|
+
|
27
|
+
plugin_class.new(plugin_config)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
34
|
+
def normalize(plugin_configs)
|
35
|
+
plugin_configs.to_h do |plugin_config|
|
36
|
+
if plugin_config == Plugin::OBSOLETE_INTERNAL_AFFAIRS_PLUGIN_NAME
|
37
|
+
warn Rainbow(<<~MESSAGE).yellow
|
38
|
+
Specify `rubocop-internal_affairs` instead of `rubocop/cop/internal_affairs` in your configuration.
|
39
|
+
MESSAGE
|
40
|
+
plugin_config = Plugin::INTERNAL_AFFAIRS_PLUGIN_NAME
|
41
|
+
end
|
42
|
+
|
43
|
+
if plugin_config.is_a?(Hash)
|
44
|
+
plugin_name = plugin_config.keys.first
|
45
|
+
|
46
|
+
[
|
47
|
+
plugin_name, DEFAULT_PLUGIN_CONFIG.merge(
|
48
|
+
{ 'require_path' => plugin_name }, plugin_config.values.first
|
49
|
+
)
|
50
|
+
]
|
51
|
+
# NOTE: Compatibility is maintained when `require: rubocop/cop/internal_affairs` remains
|
52
|
+
# specified in `.rubocop.yml`.
|
53
|
+
elsif (builtin_plugin_config = Plugin::BUILTIN_INTERNAL_PLUGINS[plugin_config])
|
54
|
+
[plugin_config, builtin_plugin_config]
|
55
|
+
else
|
56
|
+
[plugin_config, DEFAULT_PLUGIN_CONFIG.merge('require_path' => plugin_config)]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def constantize_plugin_from(plugin_name, plugin_config)
|
62
|
+
if plugin_name.is_a?(String) || plugin_name.is_a?(Symbol)
|
63
|
+
constantize(plugin_name, plugin_config)
|
64
|
+
else
|
65
|
+
plugin_name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# rubocop:enable Metrics/MethodLength
|
70
|
+
def constantize(plugin_name, plugin_config)
|
71
|
+
require_plugin(plugin_config['require_path'])
|
72
|
+
|
73
|
+
if (constant_name = plugin_config['plugin_class_name'])
|
74
|
+
begin
|
75
|
+
Kernel.const_get(constant_name)
|
76
|
+
rescue StandardError
|
77
|
+
raise <<~MESSAGE
|
78
|
+
Failed while configuring plugin `#{plugin_name}': no constant with name `#{constant_name}' was found.
|
79
|
+
MESSAGE
|
80
|
+
end
|
81
|
+
else
|
82
|
+
constantize_plugin_from_gemspec_metadata(plugin_name)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def require_plugin(require_path)
|
87
|
+
FeatureLoader.load(config_directory_path: Dir.pwd, feature: require_path)
|
88
|
+
end
|
89
|
+
|
90
|
+
def constantize_plugin_from_gemspec_metadata(plugin_name)
|
91
|
+
plugin_class_name = Gem.loaded_specs[plugin_name].metadata['default_lint_roller_plugin']
|
92
|
+
|
93
|
+
Kernel.const_get(plugin_class_name)
|
94
|
+
rescue LoadError, StandardError
|
95
|
+
raise Plugin::LoadError, plugin_name
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Plugin
|
5
|
+
# An exception raised when a plugin is not supported by the RuboCop engine.
|
6
|
+
# @api private
|
7
|
+
class NotSupportedError < Error
|
8
|
+
def initialize(unsupported_plugins)
|
9
|
+
super
|
10
|
+
|
11
|
+
@unsupported_plugins = unsupported_plugins
|
12
|
+
end
|
13
|
+
|
14
|
+
def message
|
15
|
+
if @unsupported_plugins.one?
|
16
|
+
about = @unsupported_plugins.first.about
|
17
|
+
|
18
|
+
"#{about.name} #{about.version} is not a plugin supported by RuboCop engine."
|
19
|
+
else
|
20
|
+
unsupported_plugin_names = @unsupported_plugins.map do |plugin|
|
21
|
+
"#{plugin.about.name} #{plugin.about.version}"
|
22
|
+
end.join(', ')
|
23
|
+
|
24
|
+
"#{unsupported_plugin_names} are not plugins supported by RuboCop engine."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'plugin/configuration_integrator'
|
4
|
+
require_relative 'plugin/loader'
|
5
|
+
|
6
|
+
module RuboCop
|
7
|
+
# Provides a plugin for RuboCop extensions that conform to lint_roller.
|
8
|
+
# https://github.com/standardrb/lint_roller
|
9
|
+
# @api private
|
10
|
+
module Plugin
|
11
|
+
BUILTIN_INTERNAL_PLUGINS = {
|
12
|
+
'rubocop-internal_affairs' => {
|
13
|
+
'enabled' => true,
|
14
|
+
'require_path' => 'rubocop/cop/internal_affairs/plugin',
|
15
|
+
'plugin_class_name' => 'RuboCop::InternalAffairs::Plugin'
|
16
|
+
}
|
17
|
+
}.freeze
|
18
|
+
INTERNAL_AFFAIRS_PLUGIN_NAME = Plugin::BUILTIN_INTERNAL_PLUGINS.keys.first
|
19
|
+
OBSOLETE_INTERNAL_AFFAIRS_PLUGIN_NAME = 'rubocop/cop/internal_affairs'
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def plugin_capable?(feature_name)
|
23
|
+
return true if BUILTIN_INTERNAL_PLUGINS.key?(feature_name)
|
24
|
+
return true if feature_name == OBSOLETE_INTERNAL_AFFAIRS_PLUGIN_NAME
|
25
|
+
return false unless (gem = Gem.loaded_specs[feature_name])
|
26
|
+
|
27
|
+
!!gem.metadata['default_lint_roller_plugin']
|
28
|
+
end
|
29
|
+
|
30
|
+
def integrate_plugins(rubocop_config, plugins)
|
31
|
+
plugins = Plugin::Loader.load(plugins)
|
32
|
+
|
33
|
+
ConfigurationIntegrator.integrate_plugins_into_rubocop_config(rubocop_config, plugins)
|
34
|
+
|
35
|
+
plugins
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/rubocop/rake_task.rb
CHANGED
@@ -12,7 +12,8 @@ module RuboCop
|
|
12
12
|
# Use global Rake namespace here to avoid namespace issues with custom
|
13
13
|
# rubocop-rake tasks
|
14
14
|
class RakeTask < ::Rake::TaskLib
|
15
|
-
attr_accessor :name, :verbose, :fail_on_error, :patterns, :formatters, :
|
15
|
+
attr_accessor :name, :verbose, :fail_on_error, :patterns, :formatters, :plugins, :requires,
|
16
|
+
:options
|
16
17
|
|
17
18
|
def initialize(name = :rubocop, *args, &task_block)
|
18
19
|
super()
|
@@ -54,6 +55,7 @@ module RuboCop
|
|
54
55
|
|
55
56
|
def full_options
|
56
57
|
formatters.map { |f| ['--format', f] }.flatten
|
58
|
+
.concat(plugins.map { |plugin| ['--plugin', plugin] }.flatten)
|
57
59
|
.concat(requires.map { |r| ['--require', r] }.flatten)
|
58
60
|
.concat(options.flatten)
|
59
61
|
.concat(patterns)
|
@@ -64,6 +66,7 @@ module RuboCop
|
|
64
66
|
@verbose = true
|
65
67
|
@fail_on_error = true
|
66
68
|
@patterns = []
|
69
|
+
@plugins = []
|
67
70
|
@requires = []
|
68
71
|
@options = []
|
69
72
|
@formatters = []
|
data/lib/rubocop/server/cache.rb
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'digest'
|
4
4
|
require 'pathname'
|
5
|
+
require 'yaml'
|
5
6
|
require_relative '../cache_config'
|
6
7
|
require_relative '../config_finder'
|
8
|
+
require_relative '../path_util'
|
7
9
|
|
8
10
|
#
|
9
11
|
# This code is based on https://github.com/fohte/rubocop-daemon.
|
@@ -50,9 +52,11 @@ module RuboCop
|
|
50
52
|
end.find(&:exist?)
|
51
53
|
version_data = lockfile_path&.read || RuboCop::Version::STRING
|
52
54
|
config_data = Pathname(ConfigFinder.find_config_path(Dir.pwd)).read
|
53
|
-
|
55
|
+
yaml = YAML.safe_load(config_data, permitted_classes: [Regexp, Symbol], aliases: true)
|
56
|
+
inherit_from_data = inherit_from_data(yaml)
|
57
|
+
require_data = require_data(yaml)
|
54
58
|
|
55
|
-
Digest::SHA1.hexdigest(version_data + config_data +
|
59
|
+
Digest::SHA1.hexdigest(version_data + config_data + inherit_from_data + require_data)
|
56
60
|
end
|
57
61
|
# rubocop:enable Metrics/AbcSize
|
58
62
|
|
@@ -164,6 +168,35 @@ module RuboCop
|
|
164
168
|
def write_version_file(version)
|
165
169
|
version_path.write(version)
|
166
170
|
end
|
171
|
+
|
172
|
+
def inherit_from_data(yaml)
|
173
|
+
return '' unless (inherit_from_paths = yaml['inherit_from'])
|
174
|
+
|
175
|
+
Array(inherit_from_paths).map do |path|
|
176
|
+
next if PathUtil.remote_file?(path)
|
177
|
+
|
178
|
+
path = Pathname(path)
|
179
|
+
|
180
|
+
path.exist? ? path.read : ''
|
181
|
+
end.join
|
182
|
+
end
|
183
|
+
|
184
|
+
def require_data(yaml)
|
185
|
+
return '' unless (require_paths = yaml['require'])
|
186
|
+
|
187
|
+
Array(require_paths).map do |path|
|
188
|
+
# NOTE: This targets only relative or absolute path specifications.
|
189
|
+
# For example, specifications like `require: rubocop-performance`,
|
190
|
+
# which can be loaded from `$LOAD_PATH`, are ignored.
|
191
|
+
next unless path.start_with?('.', '/')
|
192
|
+
|
193
|
+
# NOTE: `.so` files are not typically specified, so only `.rb` files are targeted.
|
194
|
+
path = "#{path}.rb" unless path.end_with?('.rb')
|
195
|
+
path = Pathname(path)
|
196
|
+
|
197
|
+
path.exist? ? path.read : ''
|
198
|
+
end.join
|
199
|
+
end
|
167
200
|
end
|
168
201
|
end
|
169
202
|
end
|
data/lib/rubocop/server/cli.rb
CHANGED
@@ -86,7 +86,7 @@ module RuboCop
|
|
86
86
|
end
|
87
87
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
88
88
|
|
89
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
89
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
90
90
|
def run_command(server_command, detach:)
|
91
91
|
case server_command
|
92
92
|
when '--server'
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
Server::ClientCommand::Status.new.run
|
108
108
|
end
|
109
109
|
end
|
110
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
110
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
111
111
|
|
112
112
|
def fetch_cache_root_path_from(arguments)
|
113
113
|
cache_root = arguments.detect { |argument| argument.start_with?('--cache-root') }
|
data/lib/rubocop/version.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
# This module holds the RuboCop version information.
|
5
5
|
module Version
|
6
|
-
STRING = '1.
|
6
|
+
STRING = '1.72.0'
|
7
7
|
|
8
8
|
MSG = '%<version>s (using %<parser_version>s, ' \
|
9
9
|
'rubocop-ast %<rubocop_ast_version>s, ' \
|
@@ -63,9 +63,21 @@ module RuboCop
|
|
63
63
|
end
|
64
64
|
|
65
65
|
# @api private
|
66
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
66
67
|
def self.extension_versions(env)
|
68
|
+
plugins = config_for_pwd(env).loaded_plugins
|
69
|
+
plugin_versions = plugins.filter_map do |plugin|
|
70
|
+
next if Plugin::BUILTIN_INTERNAL_PLUGINS.key?(plugin.about.name)
|
71
|
+
next unless (plugin_name = plugin.about.name)
|
72
|
+
|
73
|
+
" - #{plugin_name} #{plugin.about.version}"
|
74
|
+
end
|
75
|
+
|
76
|
+
# TODO: It needs to be maintained for a while to ensure compatibility with extensions that
|
77
|
+
# don't support plugins. It should be removed in future once the old style becomes obsolete.
|
67
78
|
features = config_for_pwd(env).loaded_features.sort
|
68
|
-
features.
|
79
|
+
features -= plugins.map { |plugin| plugin.about.name }
|
80
|
+
feature_versions = features.filter_map do |loaded_feature|
|
69
81
|
next unless (match = loaded_feature.match(/rubocop-(?<feature>.*)/))
|
70
82
|
|
71
83
|
# Get the expected name of the folder containing the extension code.
|
@@ -84,7 +96,10 @@ module RuboCop
|
|
84
96
|
|
85
97
|
" - #{loaded_feature} #{feature_version}"
|
86
98
|
end
|
99
|
+
|
100
|
+
plugin_versions + feature_versions
|
87
101
|
end
|
102
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
88
103
|
|
89
104
|
# @api private
|
90
105
|
def self.target_ruby_version(env)
|
data/lib/rubocop.rb
CHANGED
@@ -304,6 +304,7 @@ require_relative 'rubocop/cop/lint/constant_definition_in_block'
|
|
304
304
|
require_relative 'rubocop/cop/lint/constant_overwritten_in_rescue'
|
305
305
|
require_relative 'rubocop/cop/lint/constant_reassignment'
|
306
306
|
require_relative 'rubocop/cop/lint/constant_resolution'
|
307
|
+
require_relative 'rubocop/cop/lint/cop_directive_syntax'
|
307
308
|
require_relative 'rubocop/cop/lint/debugger'
|
308
309
|
require_relative 'rubocop/cop/lint/deprecated_class_methods'
|
309
310
|
require_relative 'rubocop/cop/lint/deprecated_constants'
|
@@ -384,6 +385,7 @@ require_relative 'rubocop/cop/lint/redundant_require_statement'
|
|
384
385
|
require_relative 'rubocop/cop/lint/redundant_safe_navigation'
|
385
386
|
require_relative 'rubocop/cop/lint/redundant_splat_expansion'
|
386
387
|
require_relative 'rubocop/cop/lint/redundant_string_coercion'
|
388
|
+
require_relative 'rubocop/cop/lint/redundant_type_conversion'
|
387
389
|
require_relative 'rubocop/cop/lint/redundant_with_index'
|
388
390
|
require_relative 'rubocop/cop/lint/redundant_with_object'
|
389
391
|
require_relative 'rubocop/cop/lint/refinement_import_methods'
|
@@ -405,6 +407,7 @@ require_relative 'rubocop/cop/lint/shadowed_exception'
|
|
405
407
|
require_relative 'rubocop/cop/lint/shadowing_outer_local_variable'
|
406
408
|
require_relative 'rubocop/cop/lint/struct_new_override'
|
407
409
|
require_relative 'rubocop/cop/lint/suppressed_exception'
|
410
|
+
require_relative 'rubocop/cop/lint/suppressed_exception_in_number_conversion'
|
408
411
|
require_relative 'rubocop/cop/lint/symbol_conversion'
|
409
412
|
require_relative 'rubocop/cop/lint/syntax'
|
410
413
|
require_relative 'rubocop/cop/lint/to_enum_arguments'
|
@@ -425,6 +428,7 @@ require_relative 'rubocop/cop/lint/uri_escape_unescape'
|
|
425
428
|
require_relative 'rubocop/cop/lint/uri_regexp'
|
426
429
|
require_relative 'rubocop/cop/lint/useless_access_modifier'
|
427
430
|
require_relative 'rubocop/cop/lint/useless_assignment'
|
431
|
+
require_relative 'rubocop/cop/lint/useless_constant_scoping'
|
428
432
|
require_relative 'rubocop/cop/lint/useless_defined'
|
429
433
|
require_relative 'rubocop/cop/lint/useless_else_without_rescue'
|
430
434
|
require_relative 'rubocop/cop/lint/useless_method_definition'
|
@@ -604,6 +608,7 @@ require_relative 'rubocop/cop/style/redundant_each'
|
|
604
608
|
require_relative 'rubocop/cop/style/redundant_fetch_block'
|
605
609
|
require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
|
606
610
|
require_relative 'rubocop/cop/style/redundant_filter_chain'
|
611
|
+
require_relative 'rubocop/cop/style/redundant_format'
|
607
612
|
require_relative 'rubocop/cop/style/redundant_heredoc_delimiter_quotes'
|
608
613
|
require_relative 'rubocop/cop/style/redundant_initialize'
|
609
614
|
require_relative 'rubocop/cop/style/redundant_interpolation_unfreeze'
|