rubocop 1.53.1 → 1.57.2
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 +3 -1
- data/config/default.yml +34 -8
- data/config/obsoletion.yml +5 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config_finder.rb +2 -2
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
- data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/base.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
- data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
- data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
- data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/layout/dot_position.rb +1 -5
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +26 -3
- data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +3 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
- data/lib/rubocop/cop/layout/redundant_line_break.rb +13 -3
- data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -1
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
- data/lib/rubocop/cop/lint/debugger.rb +17 -4
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_case_range.rb +3 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +10 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +20 -4
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +11 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +5 -3
- data/lib/rubocop/cop/lint/useless_assignment.rb +38 -12
- data/lib/rubocop/cop/lint/void.rb +32 -20
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/class_length.rb +8 -3
- data/lib/rubocop/cop/metrics/method_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +32 -4
- data/lib/rubocop/cop/mixin/comments_help.rb +16 -12
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
- data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +5 -7
- data/lib/rubocop/cop/mixin/string_help.rb +4 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/file_name.rb +1 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
- data/lib/rubocop/cop/style/alias.rb +9 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +280 -63
- data/lib/rubocop/cop/style/array_intersect.rb +13 -5
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +7 -0
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +4 -2
- data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
- data/lib/rubocop/cop/style/for.rb +1 -1
- data/lib/rubocop/cop/style/format_string.rb +24 -3
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
- data/lib/rubocop/cop/style/guard_clause.rb +26 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +25 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/lambda.rb +3 -3
- data/lib/rubocop/cop/style/lambda_call.rb +5 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +8 -1
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +6 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +6 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +9 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -9
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
- data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +22 -5
- data/lib/rubocop/cop/style/redundant_parentheses.rb +41 -15
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
- data/lib/rubocop/cop/style/redundant_return.rb +7 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +5 -0
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +23 -9
- data/lib/rubocop/cop/style/semicolon.rb +0 -3
- data/lib/rubocop/cop/style/single_argument_dig.rb +2 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
- data/lib/rubocop/cop/style/symbol_array.rb +35 -15
- data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/cop/utils/regexp_ranges.rb +26 -13
- data/lib/rubocop/cop/variable_force/assignment.rb +14 -5
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/formatter/html_formatter.rb +4 -2
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +41 -18
- data/lib/rubocop/lsp/runtime.rb +22 -2
- data/lib/rubocop/lsp/server.rb +10 -4
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/result_cache.rb +4 -0
- data/lib/rubocop/rspec/shared_contexts.rb +2 -3
- data/lib/rubocop/runner.rb +5 -3
- data/lib/rubocop/server/cache.rb +1 -0
- data/lib/rubocop/server/client_command/exec.rb +1 -1
- data/lib/rubocop/string_interpreter.rb +3 -3
- data/lib/rubocop/target_finder.rb +7 -3
- data/lib/rubocop/target_ruby.rb +9 -5
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- metadata +16 -14
@@ -6,27 +6,40 @@ module RuboCop
|
|
6
6
|
# Helper to abstract complexity of building range pairs
|
7
7
|
# with octal escape reconstruction (needed for regexp_parser < 2.7).
|
8
8
|
class RegexpRanges
|
9
|
-
attr_reader :
|
9
|
+
attr_reader :root
|
10
10
|
|
11
11
|
def initialize(root)
|
12
12
|
@root = root
|
13
13
|
@compound_token = []
|
14
|
+
@pairs = []
|
15
|
+
@populated = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def compound_token
|
19
|
+
populate_all unless @populated
|
20
|
+
|
21
|
+
@compound_token
|
14
22
|
end
|
15
23
|
|
16
24
|
def pairs
|
17
|
-
unless @
|
18
|
-
|
19
|
-
|
20
|
-
|
25
|
+
populate_all unless @populated
|
26
|
+
|
27
|
+
@pairs
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def populate_all
|
33
|
+
populate(@root)
|
21
34
|
|
22
35
|
# If either bound is a compound the first one is an escape
|
23
36
|
# and that's all we need to work with.
|
24
37
|
# If there are any cops that wanted to operate on the compound
|
25
38
|
# expression we could wrap it with a facade class.
|
26
|
-
@pairs.map { |pair| pair.map(&:first) }
|
27
|
-
end
|
39
|
+
@pairs.map! { |pair| pair.map(&:first) }
|
28
40
|
|
29
|
-
|
41
|
+
@populated = true
|
42
|
+
end
|
30
43
|
|
31
44
|
def populate(expr)
|
32
45
|
expressions = expr.expressions.to_a
|
@@ -35,15 +48,15 @@ module RuboCop
|
|
35
48
|
current = expressions.shift
|
36
49
|
|
37
50
|
if escaped_octal?(current)
|
38
|
-
compound_token << current
|
39
|
-
compound_token.concat(pop_octal_digits(expressions))
|
51
|
+
@compound_token << current
|
52
|
+
@compound_token.concat(pop_octal_digits(expressions))
|
40
53
|
# If we have all the digits we can discard.
|
41
54
|
end
|
42
55
|
|
43
56
|
next unless current.type == :set
|
44
57
|
|
45
58
|
process_set(expressions, current)
|
46
|
-
compound_token.clear
|
59
|
+
@compound_token.clear
|
47
60
|
end
|
48
61
|
end
|
49
62
|
|
@@ -64,8 +77,8 @@ module RuboCop
|
|
64
77
|
|
65
78
|
def compose_range(expressions, current)
|
66
79
|
range_start, range_end = current.expressions
|
67
|
-
range_start = if compound_token.size.between?(1, 2) && octal_digit?(range_start.text)
|
68
|
-
compound_token.dup << range_start
|
80
|
+
range_start = if @compound_token.size.between?(1, 2) && octal_digit?(range_start.text)
|
81
|
+
@compound_token.dup << range_start
|
69
82
|
else
|
70
83
|
[range_start]
|
71
84
|
end
|
@@ -102,10 +102,11 @@ module RuboCop
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def multiple_assignment_node
|
105
|
-
grandparent_node = node.parent&.parent
|
106
|
-
|
105
|
+
return nil unless (grandparent_node = node.parent&.parent)
|
106
|
+
if (node = find_multiple_assignment_node(grandparent_node))
|
107
|
+
return node
|
108
|
+
end
|
107
109
|
return nil unless grandparent_node.type == MULTIPLE_ASSIGNMENT_TYPE
|
108
|
-
return nil unless node.parent.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
|
109
110
|
|
110
111
|
grandparent_node
|
111
112
|
end
|
@@ -118,9 +119,17 @@ module RuboCop
|
|
118
119
|
end
|
119
120
|
|
120
121
|
def for_assignment_node
|
121
|
-
|
122
|
+
node.ancestors.find(&:for_type?)
|
123
|
+
end
|
122
124
|
|
123
|
-
|
125
|
+
def find_multiple_assignment_node(grandparent_node)
|
126
|
+
return unless grandparent_node.type == MULTIPLE_LEFT_HAND_SIDE_TYPE
|
127
|
+
return if grandparent_node.children.any?(&:splat_type?)
|
128
|
+
|
129
|
+
parent = grandparent_node.parent
|
130
|
+
return parent if parent.type == MULTIPLE_ASSIGNMENT_TYPE
|
131
|
+
|
132
|
+
find_multiple_assignment_node(parent)
|
124
133
|
end
|
125
134
|
end
|
126
135
|
end
|
data/lib/rubocop/file_finder.rb
CHANGED
@@ -6,12 +6,8 @@ module RuboCop
|
|
6
6
|
# Common methods for finding files.
|
7
7
|
# @api private
|
8
8
|
module FileFinder
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.root_level?(path, stop_dir)
|
14
|
-
(@root_level || stop_dir) == path.to_s
|
9
|
+
class << self
|
10
|
+
attr_accessor :root_level
|
15
11
|
end
|
16
12
|
|
17
13
|
def find_file_upwards(filename, start_dir, stop_dir = nil)
|
@@ -34,7 +30,8 @@ module RuboCop
|
|
34
30
|
file = dir + filename
|
35
31
|
yield(file.to_s) if file.exist?
|
36
32
|
|
37
|
-
|
33
|
+
dir = dir.to_s
|
34
|
+
break if dir == stop_dir || dir == FileFinder.root_level
|
38
35
|
end
|
39
36
|
end
|
40
37
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'base64'
|
4
3
|
require 'cgi'
|
5
4
|
require 'erb'
|
6
5
|
require 'ostruct'
|
@@ -124,7 +123,10 @@ module RuboCop
|
|
124
123
|
|
125
124
|
def base64_encoded_logo_image
|
126
125
|
image = File.read(LOGO_IMAGE_PATH, binmode: true)
|
127
|
-
|
126
|
+
|
127
|
+
# `Base64.encode64` compatible:
|
128
|
+
# https://github.com/ruby/base64/blob/v0.1.1/lib/base64.rb#L27-L40
|
129
|
+
[image].pack('m')
|
128
130
|
end
|
129
131
|
end
|
130
132
|
end
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
|
64
64
|
def classname_attribute_value(file)
|
65
65
|
@classname_attribute_value_cache ||= Hash.new do |hash, key|
|
66
|
-
hash[key] = key.
|
66
|
+
hash[key] = key.delete_suffix('.rb').gsub("#{Dir.pwd}/", '').tr('/', '.')
|
67
67
|
end
|
68
68
|
@classname_attribute_value_cache[file]
|
69
69
|
end
|
data/lib/rubocop/lsp/routes.rb
CHANGED
@@ -36,12 +36,19 @@ module RuboCop
|
|
36
36
|
end
|
37
37
|
|
38
38
|
handle 'initialize' do |request|
|
39
|
+
initialization_options = extract_initialization_options_from(request)
|
40
|
+
|
41
|
+
@server.configure(initialization_options)
|
42
|
+
|
39
43
|
@server.write(
|
40
44
|
id: request[:id],
|
41
45
|
result: LanguageServer::Protocol::Interface::InitializeResult.new(
|
42
46
|
capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
|
43
47
|
document_formatting_provider: true,
|
44
|
-
diagnostic_provider:
|
48
|
+
diagnostic_provider: LanguageServer::Protocol::Interface::DiagnosticOptions.new(
|
49
|
+
inter_file_dependencies: false,
|
50
|
+
workspace_diagnostics: false
|
51
|
+
),
|
45
52
|
text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
|
46
53
|
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
|
47
54
|
open_close: true
|
@@ -108,23 +115,29 @@ module RuboCop
|
|
108
115
|
end
|
109
116
|
|
110
117
|
handle 'workspace/executeCommand' do |request|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
params: {
|
117
|
-
label: 'Format with RuboCop autocorrects',
|
118
|
-
edit: {
|
119
|
-
changes: {
|
120
|
-
uri => format_file(uri)
|
121
|
-
}
|
122
|
-
}
|
123
|
-
}
|
124
|
-
)
|
118
|
+
case (command = request[:params][:command])
|
119
|
+
when 'rubocop.formatAutocorrects'
|
120
|
+
label = 'Format with RuboCop autocorrects'
|
121
|
+
when 'rubocop.formatAutocorrectsAll'
|
122
|
+
label = 'Format all with RuboCop autocorrects'
|
125
123
|
else
|
126
|
-
handle_unsupported_method(request,
|
124
|
+
handle_unsupported_method(request, command)
|
125
|
+
return
|
127
126
|
end
|
127
|
+
|
128
|
+
uri = request[:params][:arguments][0][:uri]
|
129
|
+
@server.write(
|
130
|
+
id: request[:id],
|
131
|
+
method: 'workspace/applyEdit',
|
132
|
+
params: {
|
133
|
+
label: label,
|
134
|
+
edit: {
|
135
|
+
changes: {
|
136
|
+
uri => format_file(uri, command: command)
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
)
|
128
141
|
end
|
129
142
|
|
130
143
|
handle 'textDocument/willSave' do |_request|
|
@@ -162,14 +175,24 @@ module RuboCop
|
|
162
175
|
|
163
176
|
private
|
164
177
|
|
165
|
-
def
|
178
|
+
def extract_initialization_options_from(request)
|
179
|
+
safe_autocorrect = request.dig(:params, :initializationOptions, :safeAutocorrect)
|
180
|
+
|
181
|
+
{
|
182
|
+
safe_autocorrect: safe_autocorrect.nil? || safe_autocorrect == true,
|
183
|
+
lint_mode: request.dig(:params, :initializationOptions, :lintMode) == true,
|
184
|
+
layout_mode: request.dig(:params, :initializationOptions, :layoutMode) == true
|
185
|
+
}
|
186
|
+
end
|
187
|
+
|
188
|
+
def format_file(file_uri, command: nil)
|
166
189
|
unless (text = @text_cache[file_uri])
|
167
190
|
Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
|
168
191
|
|
169
192
|
return []
|
170
193
|
end
|
171
194
|
|
172
|
-
new_text = @server.format(remove_file_protocol_from(file_uri), text)
|
195
|
+
new_text = @server.format(remove_file_protocol_from(file_uri), text, command: command)
|
173
196
|
|
174
197
|
return [] if new_text == text
|
175
198
|
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
@@ -14,9 +14,14 @@ module RuboCop
|
|
14
14
|
# Runtime for Language Server Protocol of RuboCop.
|
15
15
|
# @api private
|
16
16
|
class Runtime
|
17
|
+
attr_writer :safe_autocorrect, :lint_mode, :layout_mode
|
18
|
+
|
17
19
|
def initialize(config_store)
|
18
20
|
@config_store = config_store
|
19
21
|
@logged_paths = []
|
22
|
+
@safe_autocorrect = true
|
23
|
+
@lint_mode = false
|
24
|
+
@layout_mode = false
|
20
25
|
end
|
21
26
|
|
22
27
|
# This abuses the `--stdin` option of rubocop and reads the formatted text
|
@@ -30,10 +35,17 @@ module RuboCop
|
|
30
35
|
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
|
31
36
|
# Setting `parallel: true` would break this here:
|
32
37
|
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
|
33
|
-
def format(path, text)
|
38
|
+
def format(path, text, command:)
|
39
|
+
safe_autocorrect = if command
|
40
|
+
command == 'rubocop.formatAutocorrects'
|
41
|
+
else
|
42
|
+
@safe_autocorrect
|
43
|
+
end
|
44
|
+
|
34
45
|
formatting_options = {
|
35
|
-
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect:
|
46
|
+
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: safe_autocorrect
|
36
47
|
}
|
48
|
+
formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
|
37
49
|
|
38
50
|
redirect_stdout { run_rubocop(formatting_options, path) }
|
39
51
|
|
@@ -44,6 +56,7 @@ module RuboCop
|
|
44
56
|
diagnostic_options = {
|
45
57
|
stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
|
46
58
|
}
|
59
|
+
diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
|
47
60
|
|
48
61
|
json = redirect_stdout { run_rubocop(diagnostic_options, path) }
|
49
62
|
results = JSON.parse(json, symbolize_names: true)
|
@@ -61,6 +74,13 @@ module RuboCop
|
|
61
74
|
|
62
75
|
private
|
63
76
|
|
77
|
+
def config_only_options
|
78
|
+
only_options = []
|
79
|
+
only_options << 'Lint' if @lint_mode
|
80
|
+
only_options << 'Layout' if @layout_mode
|
81
|
+
only_options
|
82
|
+
end
|
83
|
+
|
64
84
|
def redirect_stdout(&block)
|
65
85
|
stdout = StringIO.new
|
66
86
|
|
data/lib/rubocop/lsp/server.rb
CHANGED
@@ -36,8 +36,8 @@ module RuboCop
|
|
36
36
|
@routes.handle_unsupported_method(request)
|
37
37
|
end
|
38
38
|
rescue StandardError => e
|
39
|
-
log("Error #{e.class} #{e.message[0..100]}")
|
40
|
-
log(e.backtrace.inspect)
|
39
|
+
Logger.log("Error #{e.class} #{e.message[0..100]}")
|
40
|
+
Logger.log(e.backtrace.inspect)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -45,14 +45,20 @@ module RuboCop
|
|
45
45
|
@writer.write(response)
|
46
46
|
end
|
47
47
|
|
48
|
-
def format(path, text)
|
49
|
-
@runtime.format(path, text)
|
48
|
+
def format(path, text, command:)
|
49
|
+
@runtime.format(path, text, command: command)
|
50
50
|
end
|
51
51
|
|
52
52
|
def offenses(path, text)
|
53
53
|
@runtime.offenses(path, text)
|
54
54
|
end
|
55
55
|
|
56
|
+
def configure(options)
|
57
|
+
@runtime.safe_autocorrect = options[:safe_autocorrect]
|
58
|
+
@runtime.lint_mode = options[:lint_mode]
|
59
|
+
@runtime.layout_mode = options[:layout_mode]
|
60
|
+
end
|
61
|
+
|
56
62
|
def stop(&block)
|
57
63
|
at_exit(&block) if block
|
58
64
|
exit
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
class MagicComment
|
8
8
|
# IRB's pattern for matching magic comment tokens.
|
9
9
|
# @see https://github.com/ruby/ruby/blob/b4a55c1/lib/irb/magic-file.rb#L5
|
10
|
-
TOKEN =
|
10
|
+
TOKEN = '(?<token>[[:alnum:]\-_]+)'
|
11
11
|
KEYWORDS = {
|
12
12
|
encoding: '(?:en)?coding',
|
13
13
|
frozen_string_literal: 'frozen[_-]string[_-]literal',
|
@@ -129,7 +129,7 @@ module RuboCop
|
|
129
129
|
# @return [String] if pattern matched
|
130
130
|
# @return [nil] otherwise
|
131
131
|
def extract(pattern)
|
132
|
-
@comment[pattern,
|
132
|
+
@comment[pattern, :token]
|
133
133
|
end
|
134
134
|
|
135
135
|
# Parent to Vim and Emacs magic comment handling.
|
@@ -157,10 +157,10 @@ module RuboCop
|
|
157
157
|
# @return [String] extracted value if it is found
|
158
158
|
# @return [nil] otherwise
|
159
159
|
def match(keyword)
|
160
|
-
pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s
|
160
|
+
pattern = /\A#{keyword}\s*#{self.class::OPERATOR}\s*#{TOKEN}\z/
|
161
161
|
|
162
162
|
tokens.each do |token|
|
163
|
-
next unless (value = token[pattern,
|
163
|
+
next unless (value = token[pattern, :token])
|
164
164
|
|
165
165
|
return value.downcase
|
166
166
|
end
|
@@ -188,7 +188,7 @@ module RuboCop
|
|
188
188
|
# @see https://www.gnu.org/software/emacs/manual/html_node/emacs/Specify-Coding.html
|
189
189
|
# @see https://github.com/ruby/ruby/blob/3f306dc/parse.y#L6873-L6892 Emacs handling in parse.y
|
190
190
|
class EmacsComment < EditorComment
|
191
|
-
REGEXP = /-\*-(
|
191
|
+
REGEXP = /-\*-(?<token>.+)-\*-/.freeze
|
192
192
|
FORMAT = '# -*- %s -*-'
|
193
193
|
SEPARATOR = ';'
|
194
194
|
OPERATOR = ':'
|
@@ -216,7 +216,7 @@ module RuboCop
|
|
216
216
|
#
|
217
217
|
# comment.encoding # => 'ascii-8bit'
|
218
218
|
class VimComment < EditorComment
|
219
|
-
REGEXP = /#\s*vim:\s*(
|
219
|
+
REGEXP = /#\s*vim:\s*(?<token>.+)/.freeze
|
220
220
|
FORMAT = '# vim: %s'
|
221
221
|
SEPARATOR = ', '
|
222
222
|
OPERATOR = '='
|
@@ -259,9 +259,11 @@ module RuboCop
|
|
259
259
|
# comment2.frozen_string_literal # => nil
|
260
260
|
# comment2.encoding # => 'utf-8'
|
261
261
|
class SimpleComment < MagicComment
|
262
|
+
FSTRING_LITERAL_COMMENT = 'frozen_string_literal:\s*(true|false)'
|
263
|
+
|
262
264
|
# Match `encoding` or `coding`
|
263
265
|
def encoding
|
264
|
-
extract(/\A\s
|
266
|
+
extract(/\A\s*\#\s*(#{FSTRING_LITERAL_COMMENT})?\s*#{KEYWORDS[:encoding]}: (#{TOKEN})/io)
|
265
267
|
end
|
266
268
|
|
267
269
|
# Rewrite the comment without a given token type
|
@@ -283,15 +285,15 @@ module RuboCop
|
|
283
285
|
# Case-insensitive and dashes/underscores are acceptable.
|
284
286
|
# @see https://github.com/ruby/ruby/blob/78b95b4/parse.y#L7134-L7138
|
285
287
|
def extract_frozen_string_literal
|
286
|
-
extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s
|
288
|
+
extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
|
287
289
|
end
|
288
290
|
|
289
291
|
def extract_shareable_constant_value
|
290
|
-
extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s
|
292
|
+
extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
|
291
293
|
end
|
292
294
|
|
293
295
|
def extract_typed
|
294
|
-
extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s
|
296
|
+
extract(/\A\s*#\s*#{KEYWORDS[:typed]}:\s*#{TOKEN}\s*\z/io)
|
295
297
|
end
|
296
298
|
end
|
297
299
|
end
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -202,6 +202,10 @@ module RuboCop
|
|
202
202
|
lib_root = File.join(File.dirname(__FILE__), '..')
|
203
203
|
exe_root = File.join(lib_root, '..', 'exe')
|
204
204
|
|
205
|
+
# Make sure to use an absolute path to prevent errors on Windows
|
206
|
+
# when traversing the relative paths with symlinks.
|
207
|
+
exe_root = File.absolute_path(exe_root)
|
208
|
+
|
205
209
|
# These are all the files we have `require`d plus everything in the
|
206
210
|
# exe directory. A change to any of them could affect the cop output
|
207
211
|
# so we include them in the cache hash.
|
@@ -11,6 +11,8 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
|
|
11
11
|
# Make sure to expand all symlinks in the path first. Otherwise we may
|
12
12
|
# get mismatched pathnames when loading config files later on.
|
13
13
|
tmpdir = File.realpath(tmpdir)
|
14
|
+
# Make upwards search for .rubocop.yml files stop at this directory.
|
15
|
+
RuboCop::FileFinder.root_level = tmpdir
|
14
16
|
|
15
17
|
virtual_home = File.expand_path(File.join(tmpdir, 'home'))
|
16
18
|
Dir.mkdir(virtual_home)
|
@@ -21,9 +23,6 @@ RSpec.shared_context 'isolated environment' do # rubocop:disable Metrics/BlockLe
|
|
21
23
|
root = example.metadata[:root]
|
22
24
|
working_dir = root ? File.join(base_dir, 'work', root) : File.join(base_dir, 'work')
|
23
25
|
|
24
|
-
# Make upwards search for .rubocop.yml files stop at this directory.
|
25
|
-
RuboCop::FileFinder.root_level = working_dir
|
26
|
-
|
27
26
|
begin
|
28
27
|
FileUtils.mkdir_p(working_dir)
|
29
28
|
|
data/lib/rubocop/runner.rb
CHANGED
@@ -421,10 +421,10 @@ module RuboCop
|
|
421
421
|
end
|
422
422
|
|
423
423
|
def considered_failure?(offense)
|
424
|
-
# For :autocorrect level, any offense - corrected or not - is a failure.
|
425
424
|
return false if offense.disabled?
|
426
425
|
|
427
|
-
|
426
|
+
# For :autocorrect level, any correctable offense is a failure, regardless of severity
|
427
|
+
return true if @options[:fail_level] == :autocorrect && offense.correctable?
|
428
428
|
|
429
429
|
!offense.corrected? && offense.severity >= minimum_severity_to_fail
|
430
430
|
end
|
@@ -461,7 +461,9 @@ module RuboCop
|
|
461
461
|
@minimum_severity_to_fail ||= begin
|
462
462
|
# Unless given explicitly as `fail_level`, `:info` severity offenses do not fail
|
463
463
|
name = @options[:fail_level] || :refactor
|
464
|
-
|
464
|
+
|
465
|
+
# autocorrect is a fake level - use the default
|
466
|
+
RuboCop::Cop::Severity.new(name == :autocorrect ? :refactor : name)
|
465
467
|
end
|
466
468
|
end
|
467
469
|
|
data/lib/rubocop/server/cache.rb
CHANGED
@@ -32,7 +32,7 @@ module RuboCop
|
|
32
32
|
|
33
33
|
def ensure_server!
|
34
34
|
if incompatible_version?
|
35
|
-
|
35
|
+
warn 'RuboCop version incompatibility found, RuboCop server restarting...'
|
36
36
|
ClientCommand::Stop.new.run
|
37
37
|
elsif check_running_server
|
38
38
|
return
|
@@ -32,9 +32,9 @@ module RuboCop
|
|
32
32
|
|
33
33
|
def interpret_string_escape(escape)
|
34
34
|
case escape[1]
|
35
|
-
when 'u'
|
36
|
-
when 'x'
|
37
|
-
when /\d/
|
35
|
+
when 'u' then interpret_unicode(escape)
|
36
|
+
when 'x' then interpret_hex(escape)
|
37
|
+
when /\d/ then interpret_octal(escape)
|
38
38
|
else
|
39
39
|
escape[1] # literal escaped char, like \\
|
40
40
|
end
|
@@ -94,8 +94,12 @@ module RuboCop
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def wanted_dir_patterns(base_dir, exclude_pattern, flags)
|
97
|
-
base_dir
|
98
|
-
|
97
|
+
# Escape glob characters in base_dir to avoid unwanted behavior.
|
98
|
+
base_dir = base_dir.gsub(/[\\\{\}\[\]\*\?]/) do |reserved_glob_character|
|
99
|
+
"\\#{reserved_glob_character}"
|
100
|
+
end
|
101
|
+
|
102
|
+
dirs = Dir.glob(File.join(base_dir, '*/'), flags)
|
99
103
|
.reject do |dir|
|
100
104
|
next true if dir.end_with?('/./', '/../')
|
101
105
|
next true if File.fnmatch?(exclude_pattern, dir, flags)
|
@@ -114,7 +118,7 @@ module RuboCop
|
|
114
118
|
end
|
115
119
|
|
116
120
|
def combined_exclude_glob_patterns(base_dir)
|
117
|
-
exclude = @config_store.for(base_dir).for_all_cops['Exclude']
|
121
|
+
exclude = @config_store.for(base_dir).for_all_cops['Exclude'] || []
|
118
122
|
patterns = exclude.select { |pattern| pattern.is_a?(String) && pattern.end_with?('/**/*') }
|
119
123
|
.map { |pattern| pattern.sub("#{base_dir}/", '') }
|
120
124
|
"#{base_dir}/{#{patterns.join(',')}}"
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -155,9 +155,11 @@ module RuboCop
|
|
155
155
|
(send _ :required_ruby_version= $_)
|
156
156
|
PATTERN
|
157
157
|
|
158
|
-
# @!method
|
159
|
-
def_node_matcher :
|
160
|
-
(send (const(const _ :Gem):Requirement) :new
|
158
|
+
# @!method gem_requirement_versions(node)
|
159
|
+
def_node_matcher :gem_requirement_versions, <<~PATTERN
|
160
|
+
(send (const(const _ :Gem):Requirement) :new
|
161
|
+
{$str+ | (send $str :freeze)+ | (array $str+) | (array (send $str :freeze)+)}
|
162
|
+
)
|
161
163
|
PATTERN
|
162
164
|
|
163
165
|
def name
|
@@ -194,10 +196,12 @@ module RuboCop
|
|
194
196
|
end
|
195
197
|
|
196
198
|
def version_from_right_hand_side(right_hand_side)
|
199
|
+
gem_requirement_versions = gem_requirement_versions(right_hand_side)
|
200
|
+
|
197
201
|
if right_hand_side.array_type?
|
198
202
|
version_from_array(right_hand_side)
|
199
|
-
elsif
|
200
|
-
|
203
|
+
elsif gem_requirement_versions
|
204
|
+
gem_requirement_versions.map(&:value)
|
201
205
|
else
|
202
206
|
right_hand_side.value
|
203
207
|
end
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -162,6 +162,7 @@ require_relative 'rubocop/cop/correctors/string_literal_corrector'
|
|
162
162
|
require_relative 'rubocop/cop/correctors/unused_arg_corrector'
|
163
163
|
|
164
164
|
require_relative 'rubocop/cop/bundler/duplicated_gem'
|
165
|
+
require_relative 'rubocop/cop/bundler/duplicated_group'
|
165
166
|
require_relative 'rubocop/cop/bundler/gem_comment'
|
166
167
|
require_relative 'rubocop/cop/bundler/gem_filename'
|
167
168
|
require_relative 'rubocop/cop/bundler/gem_version'
|
@@ -579,6 +580,7 @@ require_relative 'rubocop/cop/style/redundant_regexp_constructor'
|
|
579
580
|
require_relative 'rubocop/cop/style/redundant_self_assignment'
|
580
581
|
require_relative 'rubocop/cop/style/redundant_self_assignment_branch'
|
581
582
|
require_relative 'rubocop/cop/style/require_order'
|
583
|
+
require_relative 'rubocop/cop/style/single_line_do_end_block'
|
582
584
|
require_relative 'rubocop/cop/style/sole_nested_conditional'
|
583
585
|
require_relative 'rubocop/cop/style/static_class'
|
584
586
|
require_relative 'rubocop/cop/style/map_compact_with_conditional_block'
|