rubocop 1.60.2 → 1.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +64 -15
- data/lib/rubocop/cli/command/auto_generate_config.rb +12 -3
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli.rb +6 -1
- data/lib/rubocop/config.rb +37 -10
- data/lib/rubocop/config_finder.rb +12 -2
- data/lib/rubocop/config_obsoletion.rb +1 -1
- data/lib/rubocop/config_validator.rb +14 -5
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
- data/lib/rubocop/cop/base.rb +52 -6
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +122 -28
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +11 -3
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -4
- data/lib/rubocop/cop/lint/debugger.rb +27 -2
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
- data/lib/rubocop/cop/lint/redundant_with_index.rb +4 -0
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/syntax.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +7 -2
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +6 -1
- data/lib/rubocop/cop/mixin/code_length.rb +12 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +31 -12
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -2
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +29 -8
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_vars.rb +3 -3
- data/lib/rubocop/cop/style/collection_compact.rb +3 -3
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -5
- data/lib/rubocop/cop/style/copyright.rb +16 -11
- data/lib/rubocop/cop/style/eval_with_location.rb +2 -0
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
- data/lib/rubocop/cop/style/for.rb +2 -0
- data/lib/rubocop/cop/style/format_string.rb +9 -9
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +5 -8
- data/lib/rubocop/cop/style/map_into_array.rb +175 -0
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/map_to_set.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +4 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/raise_args.rb +4 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +25 -2
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +5 -4
- data/lib/rubocop/cop/style/redundant_each.rb +1 -1
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +5 -0
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/redundant_return.rb +6 -0
- data/lib/rubocop/cop/style/sample.rb +1 -3
- data/lib/rubocop/cop/team.rb +3 -0
- data/lib/rubocop/cop/utils/regexp_ranges.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +4 -2
- data/lib/rubocop/directive_comment.rb +10 -8
- data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
- data/lib/rubocop/formatter/html_formatter.rb +30 -10
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/formatter/tap_formatter.rb +3 -7
- data/lib/rubocop/lockfile.rb +34 -4
- data/lib/rubocop/lsp/logger.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/lsp/runtime.rb +1 -1
- data/lib/rubocop/lsp/server.rb +5 -2
- data/lib/rubocop/lsp/severity.rb +1 -1
- data/lib/rubocop/lsp.rb +29 -0
- data/lib/rubocop/magic_comment.rb +1 -1
- data/lib/rubocop/options.rb +11 -0
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/rspec/cop_helper.rb +8 -2
- data/lib/rubocop/rspec/expect_offense.rb +16 -8
- data/lib/rubocop/rspec/shared_contexts.rb +49 -18
- data/lib/rubocop/rspec/support.rb +2 -1
- data/lib/rubocop/runner.rb +12 -2
- data/lib/rubocop/target_finder.rb +84 -78
- data/lib/rubocop/target_ruby.rb +82 -80
- data/lib/rubocop/version.rb +19 -4
- data/lib/rubocop.rb +1 -0
- metadata +10 -6
@@ -38,6 +38,7 @@ module RuboCop
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
+
# rubocop:disable Metrics/AbcSize
|
41
42
|
def autocorrect(corrector, node, begin_of_arguments)
|
42
43
|
arguments = node.arguments
|
43
44
|
joined_arguments = arguments.map(&:source).join(', ')
|
@@ -49,9 +50,17 @@ module RuboCop
|
|
49
50
|
corrector.remove(range_by_whole_lines(arguments.loc.end, include_final_newline: true))
|
50
51
|
end
|
51
52
|
|
52
|
-
|
53
|
+
arguments_range = arguments_range(node)
|
54
|
+
# If the method name isn't on the same line as def, move it directly after def
|
55
|
+
if arguments_range.first_line != opening_line(node)
|
56
|
+
corrector.remove(node.loc.name)
|
57
|
+
corrector.insert_after(node.loc.keyword, " #{node.loc.name.source}")
|
58
|
+
end
|
59
|
+
|
60
|
+
corrector.remove(arguments_range)
|
53
61
|
corrector.insert_after(begin_of_arguments, joined_arguments)
|
54
62
|
end
|
63
|
+
# rubocop:enable Metrics/AbcSize
|
55
64
|
|
56
65
|
def last_line_source_of_arguments(arguments)
|
57
66
|
processed_source[arguments.last_line - 1].strip
|
@@ -47,7 +47,11 @@ module RuboCop
|
|
47
47
|
message = enforce_single_line_ternary_operator?(node) ? MSG_SINGLE_LINE : MSG_IF
|
48
48
|
|
49
49
|
add_offense(node, message: message) do |corrector|
|
50
|
+
next if part_of_ignored_node?(node)
|
51
|
+
|
50
52
|
autocorrect(corrector, node)
|
53
|
+
|
54
|
+
ignore_node(node)
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
@@ -46,15 +46,17 @@ module RuboCop
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def check_method_node(node)
|
49
|
-
return unless preferred_method(node)
|
49
|
+
return unless preferred_method?(node)
|
50
50
|
|
51
51
|
message = message(node)
|
52
52
|
add_offense(node.loc.selector, message: message) do |corrector|
|
53
|
-
|
53
|
+
prefer = style == :then && node.receiver.nil? ? 'self.then' : style
|
54
|
+
|
55
|
+
corrector.replace(node.loc.selector, prefer)
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
57
|
-
def preferred_method(node)
|
59
|
+
def preferred_method?(node)
|
58
60
|
case style
|
59
61
|
when :then
|
60
62
|
node.method?(:yield_self)
|
@@ -289,9 +289,7 @@ module RuboCop
|
|
289
289
|
private
|
290
290
|
|
291
291
|
def modifier_range(node)
|
292
|
-
|
293
|
-
node.loc.keyword.begin_pos,
|
294
|
-
node.source_range.end_pos)
|
292
|
+
node.loc.keyword.join(node.source_range.end)
|
295
293
|
end
|
296
294
|
end
|
297
295
|
end
|
@@ -16,6 +16,9 @@ module RuboCop
|
|
16
16
|
# The exploded style has an `AllowedCompactTypes` configuration
|
17
17
|
# option that takes an Array of exception name Strings.
|
18
18
|
#
|
19
|
+
# @safety
|
20
|
+
# This cop is unsafe because `raise Foo` calls `Foo.exception`, not `Foo.new`.
|
21
|
+
#
|
19
22
|
# @example EnforcedStyle: exploded (default)
|
20
23
|
# # bad
|
21
24
|
# raise StandardError.new('message')
|
@@ -77,7 +80,7 @@ module RuboCop
|
|
77
80
|
|
78
81
|
def correction_exploded_to_compact(node)
|
79
82
|
exception_node, *message_nodes = *node.arguments
|
80
|
-
return
|
83
|
+
return if message_nodes.size > 1
|
81
84
|
|
82
85
|
argument = message_nodes.first.source
|
83
86
|
exception_class = exception_node.receiver&.source || exception_node.source
|
@@ -81,14 +81,20 @@ module RuboCop
|
|
81
81
|
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
82
82
|
return false if redundant_argument.nil?
|
83
83
|
|
84
|
-
node.first_argument
|
84
|
+
target_argument = if node.first_argument.respond_to?(:value)
|
85
|
+
node.first_argument.value
|
86
|
+
else
|
87
|
+
node.first_argument
|
88
|
+
end
|
89
|
+
|
90
|
+
argument_matched?(target_argument, redundant_argument)
|
85
91
|
end
|
86
92
|
|
87
93
|
def redundant_arg_for_method(method_name)
|
88
94
|
arg = cop_config['Methods'].fetch(method_name) { return }
|
89
95
|
|
90
96
|
@mem ||= {}
|
91
|
-
@mem[method_name] ||=
|
97
|
+
@mem[method_name] ||= arg.inspect
|
92
98
|
end
|
93
99
|
|
94
100
|
def argument_range(node)
|
@@ -98,6 +104,23 @@ module RuboCop
|
|
98
104
|
range_with_surrounding_space(node.first_argument.source_range, newlines: false)
|
99
105
|
end
|
100
106
|
end
|
107
|
+
|
108
|
+
def argument_matched?(target_argument, redundant_argument)
|
109
|
+
argument = if target_argument.is_a?(AST::Node)
|
110
|
+
target_argument.source
|
111
|
+
elsif exclude_cntrl_character?(target_argument, redundant_argument)
|
112
|
+
target_argument.inspect
|
113
|
+
else
|
114
|
+
target_argument.to_s
|
115
|
+
end
|
116
|
+
|
117
|
+
argument == redundant_argument
|
118
|
+
end
|
119
|
+
|
120
|
+
def exclude_cntrl_character?(target_argument, redundant_argument)
|
121
|
+
!target_argument.to_s.sub(/\A'/, '"').sub(/'\z/, '"').match?(/[[:cntrl:]]/) ||
|
122
|
+
!redundant_argument.match?(/[[:cntrl:]]/)
|
123
|
+
end
|
101
124
|
end
|
102
125
|
end
|
103
126
|
end
|
@@ -54,12 +54,14 @@ module RuboCop
|
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
57
58
|
def check_branch(node)
|
58
59
|
return unless node
|
59
60
|
|
60
61
|
case node.type
|
61
|
-
when :case
|
62
|
-
when :
|
62
|
+
when :case then check_case_node(node)
|
63
|
+
when :case_match then check_case_match_node(node)
|
64
|
+
when :if then check_if_node(node)
|
63
65
|
when :rescue, :resbody
|
64
66
|
check_rescue_node(node)
|
65
67
|
when :ensure then check_ensure_node(node)
|
@@ -67,12 +69,18 @@ module RuboCop
|
|
67
69
|
check_begin_node(node)
|
68
70
|
end
|
69
71
|
end
|
72
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
70
73
|
|
71
74
|
def check_case_node(node)
|
72
75
|
node.when_branches.each { |when_node| check_branch(when_node.body) }
|
73
76
|
check_branch(node.else_branch)
|
74
77
|
end
|
75
78
|
|
79
|
+
def check_case_match_node(node)
|
80
|
+
node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
|
81
|
+
check_branch(node.else_branch)
|
82
|
+
end
|
83
|
+
|
76
84
|
def check_if_node(node)
|
77
85
|
return if node.modifier_form? || node.ternary?
|
78
86
|
|
@@ -18,14 +18,15 @@ module RuboCop
|
|
18
18
|
extend AutoCorrector
|
19
19
|
|
20
20
|
MSG = 'Remove the redundant current directory path.'
|
21
|
+
RESTRICT_ON_SEND = %i[require_relative].freeze
|
21
22
|
CURRENT_DIRECTORY_PATH = './'
|
22
23
|
|
23
24
|
def on_send(node)
|
24
|
-
return unless node.
|
25
|
-
return unless
|
26
|
-
return unless (index =
|
25
|
+
return unless (first_argument = node.first_argument)
|
26
|
+
return unless first_argument.str_content&.start_with?(CURRENT_DIRECTORY_PATH)
|
27
|
+
return unless (index = first_argument.source.index(CURRENT_DIRECTORY_PATH))
|
27
28
|
|
28
|
-
begin_pos =
|
29
|
+
begin_pos = first_argument.source_range.begin.begin_pos + index
|
29
30
|
range = range_between(begin_pos, begin_pos + 2)
|
30
31
|
|
31
32
|
add_offense(range) do |corrector|
|
@@ -79,7 +79,7 @@ module RuboCop
|
|
79
79
|
private_constant :REPLACEMENT_METHODS
|
80
80
|
|
81
81
|
def on_send(node)
|
82
|
-
return if node.arguments? || node.
|
82
|
+
return if node.arguments? || node.block_literal?
|
83
83
|
|
84
84
|
select_predicate?(node) do |select_node, filter_method|
|
85
85
|
return if RAILS_METHODS.include?(filter_method) && !active_support_extensions_enabled?
|
@@ -140,7 +140,11 @@ module RuboCop
|
|
140
140
|
current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
|
141
141
|
end
|
142
142
|
|
143
|
+
# rubocop:disable Metrics/AbcSize
|
143
144
|
def argument_newline?(node)
|
145
|
+
node = node.to_a.last if node.assignment?
|
146
|
+
return false if node.parenthesized_call?
|
147
|
+
|
144
148
|
node = node.children.first if node.root? && node.begin_type?
|
145
149
|
|
146
150
|
if argument_is_method?(node)
|
@@ -151,6 +155,7 @@ module RuboCop
|
|
151
155
|
node.loc.selector.line != node.first_argument.loc.line
|
152
156
|
end
|
153
157
|
end
|
158
|
+
# rubocop:enable Metrics/AbcSize
|
154
159
|
|
155
160
|
def find_node_for_line(line)
|
156
161
|
processed_source.ast.each_node do |node|
|
@@ -53,7 +53,7 @@ module RuboCop
|
|
53
53
|
return if interpolated_quotes?(node) || allowed_percent_q?(node)
|
54
54
|
|
55
55
|
add_offense(node) do |corrector|
|
56
|
-
delimiter =
|
56
|
+
delimiter = /\A%Q[^"]+\z|'/.match?(node.source) ? QUOTE : SINGLE_QUOTE
|
57
57
|
|
58
58
|
corrector.replace(node.loc.begin, delimiter)
|
59
59
|
corrector.replace(node.loc.end, delimiter)
|
@@ -113,6 +113,7 @@ module RuboCop
|
|
113
113
|
case node.type
|
114
114
|
when :return then check_return_node(node)
|
115
115
|
when :case then check_case_node(node)
|
116
|
+
when :case_match then check_case_match_node(node)
|
116
117
|
when :if then check_if_node(node)
|
117
118
|
when :rescue then check_rescue_node(node)
|
118
119
|
when :resbody then check_resbody_node(node)
|
@@ -140,6 +141,11 @@ module RuboCop
|
|
140
141
|
check_branch(node.else_branch)
|
141
142
|
end
|
142
143
|
|
144
|
+
def check_case_match_node(node)
|
145
|
+
node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
|
146
|
+
check_branch(node.else_branch)
|
147
|
+
end
|
148
|
+
|
143
149
|
def check_if_node(node)
|
144
150
|
return if node.ternary?
|
145
151
|
|
@@ -110,9 +110,7 @@ module RuboCop
|
|
110
110
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
111
111
|
|
112
112
|
def source_range(shuffle_node, node)
|
113
|
-
|
114
|
-
shuffle_node.loc.selector.begin_pos,
|
115
|
-
node.source_range.end_pos)
|
113
|
+
shuffle_node.loc.selector.join(node.source_range.end)
|
116
114
|
end
|
117
115
|
|
118
116
|
def message(shuffle_arg, method, method_args, range)
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -174,6 +174,9 @@ module RuboCop
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def support_target_rails_version?(cop)
|
177
|
+
# In this case, the rails version was already checked by `#excluded_file?`
|
178
|
+
return true if defined?(RuboCop::Rails::TargetRailsVersion::USES_REQUIRES_GEM_API)
|
179
|
+
|
177
180
|
return true unless cop.class.respond_to?(:support_target_rails_version?)
|
178
181
|
|
179
182
|
cop.class.support_target_rails_version?(cop.target_rails_version)
|
@@ -97,7 +97,9 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
97
97
|
'Version Changed'
|
98
98
|
]
|
99
99
|
autocorrect = if cop.support_autocorrect?
|
100
|
-
|
100
|
+
context = cop.new.always_autocorrect? ? 'Always' : 'Command-line only'
|
101
|
+
|
102
|
+
"#{context}#{' (Unsafe)' unless cop.new(config).safe_autocorrect?}"
|
101
103
|
else
|
102
104
|
'No'
|
103
105
|
end
|
@@ -276,7 +278,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
276
278
|
def print_cop_with_doc(cop) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
|
277
279
|
cop_config = config.for_cop(cop)
|
278
280
|
non_display_keys = %w[
|
279
|
-
Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
|
281
|
+
AutoCorrect Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
|
280
282
|
VersionChanged
|
281
283
|
]
|
282
284
|
pars = cop_config.reject { |k| non_display_keys.include? k }
|
@@ -6,9 +6,11 @@ module RuboCop
|
|
6
6
|
# cops it contains.
|
7
7
|
class DirectiveComment
|
8
8
|
# @api private
|
9
|
-
|
9
|
+
LINT_DEPARTMENT = 'Lint'
|
10
10
|
# @api private
|
11
|
-
|
11
|
+
LINT_REDUNDANT_DIRECTIVE_COP = "#{LINT_DEPARTMENT}/RedundantCopDisableDirective"
|
12
|
+
# @api private
|
13
|
+
LINT_SYNTAX_COP = "#{LINT_DEPARTMENT}/Syntax"
|
12
14
|
# @api private
|
13
15
|
COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
|
14
16
|
# @api private
|
@@ -118,9 +120,10 @@ module RuboCop
|
|
118
120
|
end
|
119
121
|
|
120
122
|
def parsed_cop_names
|
121
|
-
splitted_cops_string.map do |name|
|
123
|
+
cops = splitted_cops_string.map do |name|
|
122
124
|
department?(name) ? cop_names_for_department(name) : name
|
123
125
|
end.flatten
|
126
|
+
cops - [LINT_SYNTAX_COP]
|
124
127
|
end
|
125
128
|
|
126
129
|
def department?(name)
|
@@ -128,17 +131,16 @@ module RuboCop
|
|
128
131
|
end
|
129
132
|
|
130
133
|
def all_cop_names
|
131
|
-
|
134
|
+
exclude_lint_department_cops(cop_registry.names)
|
132
135
|
end
|
133
136
|
|
134
137
|
def cop_names_for_department(department)
|
135
138
|
names = cop_registry.names_for_department(department)
|
136
|
-
|
137
|
-
has_redundant_directive_cop ? exclude_redundant_directive_cop(names) : names
|
139
|
+
department == LINT_DEPARTMENT ? exclude_lint_department_cops(names) : names
|
138
140
|
end
|
139
141
|
|
140
|
-
def
|
141
|
-
cops - [
|
142
|
+
def exclude_lint_department_cops(cops)
|
143
|
+
cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
|
142
144
|
end
|
143
145
|
end
|
144
146
|
end
|
@@ -24,14 +24,10 @@ module RuboCop
|
|
24
24
|
message: message(offense)
|
25
25
|
)
|
26
26
|
|
27
|
-
|
28
|
-
return unless valid_line?(offense)
|
27
|
+
return unless valid_line?(offense)
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
rescue IndexError
|
33
|
-
# range is not on a valid line; perhaps the source file is empty
|
34
|
-
end
|
29
|
+
report_line(offense.location)
|
30
|
+
report_highlighted_area(offense.highlighted_area)
|
35
31
|
end
|
36
32
|
|
37
33
|
def valid_line?(offense)
|
@@ -9,6 +9,7 @@ module RuboCop
|
|
9
9
|
class HTMLFormatter < BaseFormatter
|
10
10
|
ELLIPSES = '<span class="extra-code">...</span>'
|
11
11
|
TEMPLATE_PATH = File.expand_path('../../../assets/output.html.erb', __dir__)
|
12
|
+
CSS_PATH = File.expand_path('../../../assets/output.css.erb', __dir__)
|
12
13
|
|
13
14
|
Color = Struct.new(:red, :green, :blue, :alpha) do
|
14
15
|
def to_s
|
@@ -50,8 +51,8 @@ module RuboCop
|
|
50
51
|
context = ERBContext.new(files, summary)
|
51
52
|
|
52
53
|
template = File.read(TEMPLATE_PATH, encoding: Encoding::UTF_8)
|
53
|
-
erb = ERB.new(template
|
54
|
-
html = erb.result(context.binding)
|
54
|
+
erb = ERB.new(template)
|
55
|
+
html = erb.result(context.binding).lines.map { (_1 =~ /^\s*$/).nil? ? _1 : "\n" }.join
|
55
56
|
|
56
57
|
output.write html
|
57
58
|
end
|
@@ -61,14 +62,6 @@ module RuboCop
|
|
61
62
|
include PathUtil
|
62
63
|
include TextUtil
|
63
64
|
|
64
|
-
SEVERITY_COLORS = {
|
65
|
-
refactor: Color.new(0xED, 0x9C, 0x28, 1.0),
|
66
|
-
convention: Color.new(0xED, 0x9C, 0x28, 1.0),
|
67
|
-
warning: Color.new(0x96, 0x28, 0xEF, 1.0),
|
68
|
-
error: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
69
|
-
fatal: Color.new(0xD2, 0x32, 0x2D, 1.0)
|
70
|
-
}.freeze
|
71
|
-
|
72
65
|
LOGO_IMAGE_PATH = File.expand_path('../../../assets/logo.png', __dir__)
|
73
66
|
|
74
67
|
attr_reader :files, :summary
|
@@ -127,6 +120,33 @@ module RuboCop
|
|
127
120
|
# https://github.com/ruby/base64/blob/v0.1.1/lib/base64.rb#L27-L40
|
128
121
|
[image].pack('m')
|
129
122
|
end
|
123
|
+
|
124
|
+
def render_css
|
125
|
+
context = CSSContext.new
|
126
|
+
template = File.read(CSS_PATH, encoding: Encoding::UTF_8)
|
127
|
+
erb = ERB.new(template, trim_mode: '-')
|
128
|
+
erb.result(context.binding).lines.map do |line|
|
129
|
+
line == "\n" ? line : " #{line}"
|
130
|
+
end.join
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# This class provides helper methods used in the ERB CSS template.
|
135
|
+
class CSSContext
|
136
|
+
SEVERITY_COLORS = {
|
137
|
+
refactor: Color.new(0xED, 0x9C, 0x28, 1.0),
|
138
|
+
convention: Color.new(0xED, 0x9C, 0x28, 1.0),
|
139
|
+
warning: Color.new(0x96, 0x28, 0xEF, 1.0),
|
140
|
+
error: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
141
|
+
fatal: Color.new(0xD2, 0x32, 0x2D, 1.0)
|
142
|
+
}.freeze
|
143
|
+
|
144
|
+
# Make Kernel#binding public.
|
145
|
+
# rubocop:disable Lint/UselessMethodDefinition
|
146
|
+
def binding
|
147
|
+
super
|
148
|
+
end
|
149
|
+
# rubocop:enable Lint/UselessMethodDefinition
|
130
150
|
end
|
131
151
|
end
|
132
152
|
end
|
@@ -61,8 +61,7 @@ module RuboCop
|
|
61
61
|
|
62
62
|
column_width = total_count.to_s.length + 2
|
63
63
|
per_cop_counts.each do |cop_name, count|
|
64
|
-
output.puts "#{count.to_s.ljust(column_width)}#{cop_name}"
|
65
|
-
"#{@style_guide_links[cop_name]}\n"
|
64
|
+
output.puts "#{count.to_s.ljust(column_width)}#{cop_information(cop_name)}"
|
66
65
|
end
|
67
66
|
output.puts '--'
|
68
67
|
output.puts "#{total_count} Total in #{offending_files_count} files"
|
@@ -78,6 +77,17 @@ module RuboCop
|
|
78
77
|
def total_offense_count(offense_counts)
|
79
78
|
offense_counts.values.sum
|
80
79
|
end
|
80
|
+
|
81
|
+
def cop_information(cop_name)
|
82
|
+
cop = RuboCop::Cop::Registry.global.find_by_cop_name(cop_name).new
|
83
|
+
|
84
|
+
if cop.correctable?
|
85
|
+
safety = cop.safe_autocorrect? ? 'Safe' : 'Unsafe'
|
86
|
+
correctable = Rainbow(" [#{safety} Correctable]").yellow
|
87
|
+
end
|
88
|
+
|
89
|
+
"#{cop_name}#{correctable}#{@style_guide_links[cop_name]}"
|
90
|
+
end
|
81
91
|
end
|
82
92
|
end
|
83
93
|
end
|
@@ -53,14 +53,10 @@ module RuboCop
|
|
53
53
|
message: message(offense)
|
54
54
|
)
|
55
55
|
|
56
|
-
|
57
|
-
return unless valid_line?(offense)
|
56
|
+
return unless valid_line?(offense)
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
rescue IndexError
|
62
|
-
# range is not on a valid line; perhaps the source file is empty
|
63
|
-
end
|
58
|
+
report_line(offense.location)
|
59
|
+
report_highlighted_area(offense.highlighted_area)
|
64
60
|
end
|
65
61
|
|
66
62
|
def annotate_message(msg)
|
data/lib/rubocop/lockfile.rb
CHANGED
@@ -5,14 +5,23 @@ module RuboCop
|
|
5
5
|
# Does not actually resolve gems, just parses the lockfile.
|
6
6
|
# @api private
|
7
7
|
class Lockfile
|
8
|
-
#
|
8
|
+
# @param [String, Pathname, nil] lockfile_path
|
9
|
+
def initialize(lockfile_path = nil)
|
10
|
+
lockfile_path ||= defined?(Bundler) ? Bundler.default_lockfile : nil
|
11
|
+
|
12
|
+
@lockfile_path = lockfile_path
|
13
|
+
end
|
14
|
+
|
15
|
+
# Gems that the bundle directly depends on.
|
16
|
+
# @return [Array<Bundler::Dependency>, nil]
|
9
17
|
def dependencies
|
10
18
|
return [] unless parser
|
11
19
|
|
12
20
|
parser.dependencies.values
|
13
21
|
end
|
14
22
|
|
15
|
-
# All activated gems, including transitive dependencies
|
23
|
+
# All activated gems, including transitive dependencies.
|
24
|
+
# @return [Array<Bundler::Dependency>, nil]
|
16
25
|
def gems
|
17
26
|
return [] unless parser
|
18
27
|
|
@@ -21,17 +30,38 @@ module RuboCop
|
|
21
30
|
parser.dependencies.values.concat(parser.specs.flat_map(&:dependencies))
|
22
31
|
end
|
23
32
|
|
33
|
+
# Returns the locked versions of gems from this lockfile.
|
34
|
+
# @param [Boolean] include_transitive_dependencies: When false, only direct dependencies
|
35
|
+
# are returned, i.e. those listed explicitly in the `Gemfile`.
|
36
|
+
# @returns [Hash{String => Gem::Version}] The locked gem versions, keyed by the gems' names.
|
37
|
+
def gem_versions(include_transitive_dependencies: true)
|
38
|
+
return {} unless parser
|
39
|
+
|
40
|
+
all_gem_versions = parser.specs.to_h { |spec| [spec.name, spec.version] }
|
41
|
+
|
42
|
+
if include_transitive_dependencies
|
43
|
+
all_gem_versions
|
44
|
+
else
|
45
|
+
direct_dep_names = parser.dependencies.keys
|
46
|
+
all_gem_versions.slice(*direct_dep_names)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Whether this lockfile includes the named gem, directly or indirectly.
|
51
|
+
# @param [String] name
|
52
|
+
# @return [Boolean]
|
24
53
|
def includes_gem?(name)
|
25
54
|
gems.any? { |gem| gem.name == name }
|
26
55
|
end
|
27
56
|
|
28
57
|
private
|
29
58
|
|
59
|
+
# @return [Bundler::LockfileParser, nil]
|
30
60
|
def parser
|
31
|
-
return unless defined?(Bundler) && Bundler.default_lockfile
|
32
61
|
return @parser if defined?(@parser)
|
62
|
+
return unless @lockfile_path
|
33
63
|
|
34
|
-
lockfile = Bundler.read_file(
|
64
|
+
lockfile = Bundler.read_file(@lockfile_path)
|
35
65
|
@parser = lockfile ? Bundler::LockfileParser.new(lockfile) : nil
|
36
66
|
rescue Bundler::BundlerError
|
37
67
|
nil
|
data/lib/rubocop/lsp/logger.rb
CHANGED
data/lib/rubocop/lsp/routes.rb
CHANGED
data/lib/rubocop/lsp/runtime.rb
CHANGED
data/lib/rubocop/lsp/server.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'language_server-protocol'
|
4
|
+
require_relative '../lsp'
|
4
5
|
require_relative 'logger'
|
5
6
|
require_relative 'routes'
|
6
7
|
require_relative 'runtime'
|
@@ -15,14 +16,16 @@ require_relative 'runtime'
|
|
15
16
|
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
16
17
|
#
|
17
18
|
module RuboCop
|
18
|
-
module
|
19
|
+
module LSP
|
19
20
|
# Language Server Protocol of RuboCop.
|
20
21
|
# @api private
|
21
22
|
class Server
|
22
23
|
def initialize(config_store)
|
24
|
+
RuboCop::LSP.enable
|
25
|
+
|
23
26
|
@reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
|
24
27
|
@writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
|
25
|
-
@runtime = RuboCop::
|
28
|
+
@runtime = RuboCop::LSP::Runtime.new(config_store)
|
26
29
|
@routes = Routes.new(self)
|
27
30
|
end
|
28
31
|
|