rubocop 1.50.2 → 1.59.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 +5 -3
- data/config/default.yml +153 -16
- data/config/obsoletion.yml +5 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
- data/lib/rubocop/cli/command/lsp.rb +19 -0
- data/lib/rubocop/cli.rb +4 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_finder.rb +2 -2
- data/lib/rubocop/config_loader_resolver.rb +4 -3
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
- data/lib/rubocop/config_obsoletion.rb +13 -10
- data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
- data/lib/rubocop/cop/base.rb +6 -2
- 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/gem_comment.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
- data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
- 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/cop_description.rb +32 -8
- 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/method_name_equal.rb +19 -20
- data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +7 -7
- 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/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
- 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 +27 -4
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
- data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -4
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
- 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 +16 -5
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
- 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 +53 -21
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
- data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +19 -5
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
- data/lib/rubocop/cop/lint/empty_block.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +6 -7
- data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
- data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
- data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
- data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
- data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +78 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_super.rb +34 -5
- data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
- data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -3
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +63 -4
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
- data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
- 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 +2 -2
- data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +5 -3
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
- data/lib/rubocop/cop/lint/useless_times.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +92 -11
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
- 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/abc_size_calculator.rb +1 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +32 -4
- data/lib/rubocop/cop/migration/department_name.rb +2 -2
- data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +19 -11
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.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/percent_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- 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/block_forwarding.rb +3 -3
- data/lib/rubocop/cop/naming/constant_name.rb +2 -3
- 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/naming/memoized_instance_variable_name.rb +26 -11
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
- data/lib/rubocop/cop/naming/variable_name.rb +6 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +6 -2
- data/lib/rubocop/cop/style/alias.rb +9 -8
- data/lib/rubocop/cop/style/arguments_forwarding.rb +342 -63
- data/lib/rubocop/cop/style/array_first_last.rb +64 -0
- data/lib/rubocop/cop/style/array_intersect.rb +13 -5
- data/lib/rubocop/cop/style/attr.rb +11 -1
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
- data/lib/rubocop/cop/style/begin_block.rb +1 -2
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
- data/lib/rubocop/cop/style/block_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +5 -4
- data/lib/rubocop/cop/style/case_like_if.rb +4 -4
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_check.rb +1 -0
- data/lib/rubocop/cop/style/class_equality_comparison.rb +24 -39
- data/lib/rubocop/cop/style/collection_compact.rb +22 -11
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
- data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
- data/lib/rubocop/cop/style/copyright.rb +5 -2
- data/lib/rubocop/cop/style/date_time.rb +5 -4
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/dir_empty.rb +8 -14
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +2 -2
- data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/eval_with_location.rb +8 -8
- data/lib/rubocop/cop/style/exact_regexp_match.rb +69 -0
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
- data/lib/rubocop/cop/style/file_read.rb +2 -2
- 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 +28 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +84 -32
- data/lib/rubocop/cop/style/hash_except.rb +21 -9
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +31 -5
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
- data/lib/rubocop/cop/style/lambda.rb +3 -3
- data/lib/rubocop/cop/style/lambda_call.rb +5 -0
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
- data/lib/rubocop/cop/style/map_to_hash.rb +10 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -5
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
- 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/multiple_comparison.rb +14 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
- data/lib/rubocop/cop/style/next.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +9 -3
- data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
- data/lib/rubocop/cop/style/redundant_conditional.rb +2 -10
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
- 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_fetch_block.rb +3 -3
- data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +9 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +54 -21
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
- data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- data/lib/rubocop/cop/style/redundant_return.rb +8 -3
- data/lib/rubocop/cop/style/redundant_self.rb +17 -2
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +10 -9
- data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
- data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -1
- data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
- data/lib/rubocop/cop/style/require_order.rb +11 -5
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
- data/lib/rubocop/cop/style/return_nil.rb +6 -2
- data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
- data/lib/rubocop/cop/style/sample.rb +2 -1
- data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +20 -4
- data/lib/rubocop/cop/style/signal_exception.rb +1 -1
- data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
- data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -2
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
- data/lib/rubocop/cop/style/string_chars.rb +1 -0
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
- data/lib/rubocop/cop/style/strip.rb +7 -4
- data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
- data/lib/rubocop/cop/style/symbol_array.rb +35 -15
- data/lib/rubocop/cop/style/unpack_first.rb +11 -14
- data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
- data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
- data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
- data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
- data/lib/rubocop/cop/variable_force.rb +1 -0
- data/lib/rubocop/cops_documentation_generator.rb +1 -1
- data/lib/rubocop/ext/regexp_parser.rb +4 -1
- data/lib/rubocop/file_finder.rb +4 -7
- data/lib/rubocop/formatter/html_formatter.rb +5 -4
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/lsp/logger.rb +22 -0
- data/lib/rubocop/lsp/routes.rb +246 -0
- data/lib/rubocop/lsp/runtime.rb +99 -0
- data/lib/rubocop/lsp/server.rb +68 -0
- data/lib/rubocop/lsp/severity.rb +27 -0
- data/lib/rubocop/magic_comment.rb +12 -10
- data/lib/rubocop/options.rb +11 -1
- data/lib/rubocop/result_cache.rb +5 -2
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +2 -3
- data/lib/rubocop/runner.rb +6 -4
- data/lib/rubocop/server/cache.rb +1 -0
- data/lib/rubocop/server/client_command/exec.rb +3 -2
- data/lib/rubocop/string_interpreter.rb +3 -3
- data/lib/rubocop/target_finder.rb +7 -3
- data/lib/rubocop/target_ruby.rb +12 -7
- data/lib/rubocop/version.rb +10 -6
- data/lib/rubocop.rb +19 -0
- metadata +54 -15
@@ -0,0 +1,246 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'severity'
|
4
|
+
|
5
|
+
#
|
6
|
+
# This code is based on https://github.com/standardrb/standard.
|
7
|
+
#
|
8
|
+
# Copyright (c) 2023 Test Double, Inc.
|
9
|
+
#
|
10
|
+
# The MIT License (MIT)
|
11
|
+
#
|
12
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
13
|
+
#
|
14
|
+
module RuboCop
|
15
|
+
module Lsp
|
16
|
+
# Routes for Language Server Protocol of RuboCop.
|
17
|
+
# @api private
|
18
|
+
class Routes
|
19
|
+
def self.handle(name, &block)
|
20
|
+
define_method("handle_#{name}", &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
private_class_method :handle
|
24
|
+
|
25
|
+
def initialize(server)
|
26
|
+
@server = server
|
27
|
+
|
28
|
+
@text_cache = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def for(name)
|
32
|
+
name = "handle_#{name}"
|
33
|
+
return unless respond_to?(name)
|
34
|
+
|
35
|
+
method(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
handle 'initialize' do |request|
|
39
|
+
initialization_options = extract_initialization_options_from(request)
|
40
|
+
|
41
|
+
@server.configure(initialization_options)
|
42
|
+
|
43
|
+
@server.write(
|
44
|
+
id: request[:id],
|
45
|
+
result: LanguageServer::Protocol::Interface::InitializeResult.new(
|
46
|
+
capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
|
47
|
+
document_formatting_provider: true,
|
48
|
+
diagnostic_provider: LanguageServer::Protocol::Interface::DiagnosticOptions.new(
|
49
|
+
inter_file_dependencies: false,
|
50
|
+
workspace_diagnostics: false
|
51
|
+
),
|
52
|
+
text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
|
53
|
+
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
|
54
|
+
open_close: true
|
55
|
+
)
|
56
|
+
)
|
57
|
+
)
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
handle 'initialized' do |_request|
|
62
|
+
version = RuboCop::Version::STRING
|
63
|
+
|
64
|
+
Logger.log("RuboCop #{version} language server initialized, PID #{Process.pid}")
|
65
|
+
end
|
66
|
+
|
67
|
+
handle 'shutdown' do |request|
|
68
|
+
Logger.log('Client asked to shutdown RuboCop language server.')
|
69
|
+
@server.stop do
|
70
|
+
@server.write(id: request[:id], result: nil)
|
71
|
+
Logger.log('Exiting...')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
handle 'textDocument/diagnostic' do |request|
|
76
|
+
doc = request[:params][:textDocument]
|
77
|
+
result = diagnostic(doc[:uri], doc[:text])
|
78
|
+
@server.write(result)
|
79
|
+
end
|
80
|
+
|
81
|
+
handle 'textDocument/didChange' do |request|
|
82
|
+
params = request[:params]
|
83
|
+
result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
|
84
|
+
@server.write(result)
|
85
|
+
end
|
86
|
+
|
87
|
+
handle 'textDocument/didOpen' do |request|
|
88
|
+
doc = request[:params][:textDocument]
|
89
|
+
result = diagnostic(doc[:uri], doc[:text])
|
90
|
+
@server.write(result)
|
91
|
+
end
|
92
|
+
|
93
|
+
handle 'textDocument/didClose' do |request|
|
94
|
+
@text_cache.delete(request.dig(:params, :textDocument, :uri))
|
95
|
+
end
|
96
|
+
|
97
|
+
handle 'textDocument/formatting' do |request|
|
98
|
+
uri = request[:params][:textDocument][:uri]
|
99
|
+
@server.write(id: request[:id], result: format_file(uri))
|
100
|
+
end
|
101
|
+
|
102
|
+
handle 'workspace/didChangeConfiguration' do |_request|
|
103
|
+
Logger.log('Ignoring workspace/didChangeConfiguration')
|
104
|
+
end
|
105
|
+
|
106
|
+
handle 'workspace/didChangeWatchedFiles' do |request|
|
107
|
+
changed = request[:params][:changes].any? do |change|
|
108
|
+
change[:uri].end_with?(RuboCop::ConfigFinder::DOTFILE)
|
109
|
+
end
|
110
|
+
|
111
|
+
if changed
|
112
|
+
Logger.log('Configuration file changed; restart required')
|
113
|
+
@server.stop
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
handle 'workspace/executeCommand' do |request|
|
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'
|
123
|
+
else
|
124
|
+
handle_unsupported_method(request, command)
|
125
|
+
return
|
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
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
handle 'textDocument/willSave' do |_request|
|
144
|
+
# Nothing to do
|
145
|
+
end
|
146
|
+
|
147
|
+
handle 'textDocument/didSave' do |_request|
|
148
|
+
# Nothing to do
|
149
|
+
end
|
150
|
+
|
151
|
+
handle '$/cancelRequest' do |_request|
|
152
|
+
# Can't cancel anything because single-threaded
|
153
|
+
end
|
154
|
+
|
155
|
+
handle '$/setTrace' do |_request|
|
156
|
+
# No-op, we log everything
|
157
|
+
end
|
158
|
+
|
159
|
+
def handle_unsupported_method(request, method = request[:method])
|
160
|
+
@server.write(
|
161
|
+
id: request[:id],
|
162
|
+
error: LanguageServer::Protocol::Interface::ResponseError.new(
|
163
|
+
code: LanguageServer::Protocol::Constant::ErrorCodes::METHOD_NOT_FOUND,
|
164
|
+
message: "Unsupported Method: #{method}"
|
165
|
+
)
|
166
|
+
)
|
167
|
+
Logger.log("Unsupported Method: #{method}")
|
168
|
+
end
|
169
|
+
|
170
|
+
def handle_method_missing(request)
|
171
|
+
return unless request.key?(:id)
|
172
|
+
|
173
|
+
@server.write(id: request[:id], result: nil)
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
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)
|
189
|
+
unless (text = @text_cache[file_uri])
|
190
|
+
Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
|
191
|
+
|
192
|
+
return []
|
193
|
+
end
|
194
|
+
|
195
|
+
new_text = @server.format(remove_file_protocol_from(file_uri), text, command: command)
|
196
|
+
|
197
|
+
return [] if new_text == text
|
198
|
+
|
199
|
+
[
|
200
|
+
newText: new_text,
|
201
|
+
range: {
|
202
|
+
start: { line: 0, character: 0 },
|
203
|
+
end: { line: text.count("\n") + 1, character: 0 }
|
204
|
+
}
|
205
|
+
]
|
206
|
+
end
|
207
|
+
|
208
|
+
def diagnostic(file_uri, text)
|
209
|
+
@text_cache[file_uri] = text
|
210
|
+
offenses = @server.offenses(remove_file_protocol_from(file_uri), text)
|
211
|
+
diagnostics = offenses.map { |offense| to_diagnostic(offense) }
|
212
|
+
|
213
|
+
{
|
214
|
+
method: 'textDocument/publishDiagnostics',
|
215
|
+
params: {
|
216
|
+
uri: file_uri,
|
217
|
+
diagnostics: diagnostics
|
218
|
+
}
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
def remove_file_protocol_from(uri)
|
223
|
+
uri.delete_prefix('file://')
|
224
|
+
end
|
225
|
+
|
226
|
+
def to_diagnostic(offense)
|
227
|
+
code = offense[:cop_name]
|
228
|
+
message = offense[:message]
|
229
|
+
loc = offense[:location]
|
230
|
+
rubocop_severity = offense[:severity]
|
231
|
+
severity = Severity.find_by(rubocop_severity)
|
232
|
+
|
233
|
+
{
|
234
|
+
code: code, message: message, range: to_range(loc), severity: severity, source: 'rubocop'
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
def to_range(location)
|
239
|
+
{
|
240
|
+
start: { character: location[:start_column] - 1, line: location[:start_line] - 1 },
|
241
|
+
end: { character: location[:last_column] - 1, line: location[:last_line] - 1 }
|
242
|
+
}
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/standardrb/standard.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2023 Test Double, Inc.
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Lsp
|
14
|
+
# Runtime for Language Server Protocol of RuboCop.
|
15
|
+
# @api private
|
16
|
+
class Runtime
|
17
|
+
attr_writer :safe_autocorrect, :lint_mode, :layout_mode
|
18
|
+
|
19
|
+
def initialize(config_store)
|
20
|
+
@config_store = config_store
|
21
|
+
@logged_paths = []
|
22
|
+
@safe_autocorrect = true
|
23
|
+
@lint_mode = false
|
24
|
+
@layout_mode = false
|
25
|
+
end
|
26
|
+
|
27
|
+
# This abuses the `--stdin` option of rubocop and reads the formatted text
|
28
|
+
# from the `options[:stdin]` that rubocop mutates. This depends on
|
29
|
+
# `parallel: false` as well as the fact that RuboCop doesn't otherwise dup
|
30
|
+
# or reassign that options object. Risky business!
|
31
|
+
#
|
32
|
+
# Reassigning `options[:stdin]` is done here:
|
33
|
+
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/team.rb#L131
|
34
|
+
# Printing `options[:stdin]`
|
35
|
+
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
|
36
|
+
# Setting `parallel: true` would break this here:
|
37
|
+
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
|
38
|
+
def format(path, text, command:)
|
39
|
+
safe_autocorrect = if command
|
40
|
+
command == 'rubocop.formatAutocorrects'
|
41
|
+
else
|
42
|
+
@safe_autocorrect
|
43
|
+
end
|
44
|
+
|
45
|
+
formatting_options = {
|
46
|
+
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: safe_autocorrect
|
47
|
+
}
|
48
|
+
formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
|
49
|
+
|
50
|
+
redirect_stdout { run_rubocop(formatting_options, path) }
|
51
|
+
|
52
|
+
formatting_options[:stdin]
|
53
|
+
end
|
54
|
+
|
55
|
+
def offenses(path, text)
|
56
|
+
diagnostic_options = {
|
57
|
+
stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
|
58
|
+
}
|
59
|
+
diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
|
60
|
+
|
61
|
+
json = redirect_stdout { run_rubocop(diagnostic_options, path) }
|
62
|
+
results = JSON.parse(json, symbolize_names: true)
|
63
|
+
|
64
|
+
if results[:files].empty?
|
65
|
+
unless @logged_paths.include?(path)
|
66
|
+
Logger.log "Ignoring file, per configuration: #{path}"
|
67
|
+
@logged_paths << path
|
68
|
+
end
|
69
|
+
return []
|
70
|
+
end
|
71
|
+
|
72
|
+
results.dig(:files, 0, :offenses)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
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
|
+
|
84
|
+
def redirect_stdout(&block)
|
85
|
+
stdout = StringIO.new
|
86
|
+
|
87
|
+
RuboCop::Server::Helper.redirect(stdout: stdout, &block)
|
88
|
+
|
89
|
+
stdout.string
|
90
|
+
end
|
91
|
+
|
92
|
+
def run_rubocop(options, path)
|
93
|
+
runner = RuboCop::Runner.new(options, @config_store)
|
94
|
+
|
95
|
+
runner.run([path])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'language_server-protocol'
|
4
|
+
require_relative 'logger'
|
5
|
+
require_relative 'routes'
|
6
|
+
require_relative 'runtime'
|
7
|
+
|
8
|
+
#
|
9
|
+
# This code is based on https://github.com/standardrb/standard.
|
10
|
+
#
|
11
|
+
# Copyright (c) 2023 Test Double, Inc.
|
12
|
+
#
|
13
|
+
# The MIT License (MIT)
|
14
|
+
#
|
15
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
16
|
+
#
|
17
|
+
module RuboCop
|
18
|
+
module Lsp
|
19
|
+
# Language Server Protocol of RuboCop.
|
20
|
+
# @api private
|
21
|
+
class Server
|
22
|
+
def initialize(config_store)
|
23
|
+
@reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
|
24
|
+
@writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
|
25
|
+
@runtime = RuboCop::Lsp::Runtime.new(config_store)
|
26
|
+
@routes = Routes.new(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def start
|
30
|
+
@reader.read do |request|
|
31
|
+
if !request.key?(:method)
|
32
|
+
@routes.handle_method_missing(request)
|
33
|
+
elsif (route = @routes.for(request[:method]))
|
34
|
+
route.call(request)
|
35
|
+
else
|
36
|
+
@routes.handle_unsupported_method(request)
|
37
|
+
end
|
38
|
+
rescue StandardError => e
|
39
|
+
Logger.log("Error #{e.class} #{e.message[0..100]}")
|
40
|
+
Logger.log(e.backtrace.inspect)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def write(response)
|
45
|
+
@writer.write(response)
|
46
|
+
end
|
47
|
+
|
48
|
+
def format(path, text, command:)
|
49
|
+
@runtime.format(path, text, command: command)
|
50
|
+
end
|
51
|
+
|
52
|
+
def offenses(path, text)
|
53
|
+
@runtime.offenses(path, text)
|
54
|
+
end
|
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
|
+
|
62
|
+
def stop(&block)
|
63
|
+
at_exit(&block) if block
|
64
|
+
exit
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Lsp
|
5
|
+
# Severity for Language Server Protocol of RuboCop.
|
6
|
+
# @api private
|
7
|
+
class Severity
|
8
|
+
SEVERITIES = {
|
9
|
+
fatal: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
|
10
|
+
error: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
|
11
|
+
warning: LanguageServer::Protocol::Constant::DiagnosticSeverity::WARNING,
|
12
|
+
convention: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
|
13
|
+
refactor: LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT,
|
14
|
+
info: LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def self.find_by(rubocop_severity)
|
18
|
+
if (severity = SEVERITIES[rubocop_severity.to_sym])
|
19
|
+
return severity
|
20
|
+
end
|
21
|
+
|
22
|
+
Logger.log("Unknown severity: #{rubocop_severity}")
|
23
|
+
LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -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/options.rb
CHANGED
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
'root of the project. RuboCop will use this path to determine which ' \
|
17
17
|
'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
|
18
18
|
'like Naming/FileName can be checked.'
|
19
|
-
EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url].freeze
|
19
|
+
EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url lsp].freeze
|
20
20
|
DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
|
21
21
|
|
22
22
|
def initialize
|
@@ -49,12 +49,14 @@ module RuboCop
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
+
# rubocop:disable Metrics/AbcSize
|
52
53
|
def define_options
|
53
54
|
OptionParser.new do |opts|
|
54
55
|
opts.banner = rainbow.wrap('Usage: rubocop [options] [file1, file2, ...]').bright
|
55
56
|
|
56
57
|
add_check_options(opts)
|
57
58
|
add_cache_options(opts)
|
59
|
+
add_lsp_option(opts)
|
58
60
|
add_server_options(opts)
|
59
61
|
add_output_options(opts)
|
60
62
|
add_autocorrection_options(opts)
|
@@ -66,6 +68,7 @@ module RuboCop
|
|
66
68
|
add_profile_options(opts) if RUBY_ENGINE == 'ruby' && !Platform.windows?
|
67
69
|
end
|
68
70
|
end
|
71
|
+
# rubocop:enable Metrics/AbcSize
|
69
72
|
|
70
73
|
def add_check_options(opts) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
71
74
|
section(opts, 'Basic Options') do # rubocop:disable Metrics/BlockLength
|
@@ -205,6 +208,12 @@ module RuboCop
|
|
205
208
|
end
|
206
209
|
end
|
207
210
|
|
211
|
+
def add_lsp_option(opts)
|
212
|
+
section(opts, 'LSP Option') do
|
213
|
+
option(opts, '--lsp')
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
208
217
|
def add_server_options(opts)
|
209
218
|
section(opts, 'Server Options') do
|
210
219
|
option(opts, '--[no-]server')
|
@@ -620,6 +629,7 @@ module RuboCop
|
|
620
629
|
stop_server: 'Stop server process.',
|
621
630
|
server_status: 'Show server status.',
|
622
631
|
no_detach: 'Run the server process in the foreground.',
|
632
|
+
lsp: 'Start a language server listening on STDIN.',
|
623
633
|
raise_cop_error: ['Raise cop-related errors with cause and location.',
|
624
634
|
'This is used to prevent cops from failing silently.',
|
625
635
|
'Default is false.'],
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'digest/sha1'
|
4
|
-
require 'etc'
|
5
4
|
require 'find'
|
6
5
|
require 'zlib'
|
7
6
|
require_relative 'cache_config'
|
@@ -83,7 +82,7 @@ module RuboCop
|
|
83
82
|
config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
|
84
83
|
end
|
85
84
|
|
86
|
-
|
85
|
+
attr_reader :path
|
87
86
|
|
88
87
|
def initialize(file, team, options, config_store, cache_root = nil)
|
89
88
|
cache_root ||= File.join(options[:cache_root], 'rubocop_cache') if options[:cache_root]
|
@@ -202,6 +201,10 @@ module RuboCop
|
|
202
201
|
lib_root = File.join(File.dirname(__FILE__), '..')
|
203
202
|
exe_root = File.join(lib_root, '..', 'exe')
|
204
203
|
|
204
|
+
# Make sure to use an absolute path to prevent errors on Windows
|
205
|
+
# when traversing the relative paths with symlinks.
|
206
|
+
exe_root = File.absolute_path(exe_root)
|
207
|
+
|
205
208
|
# These are all the files we have `require`d plus everything in the
|
206
209
|
# exe directory. A change to any of them could affect the cop output
|
207
210
|
# 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
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
message = 'Infinite loop detected'
|
21
21
|
message += " in #{path}" if path
|
22
22
|
message += " and caused by #{root_cause}" if root_cause
|
23
|
-
super
|
23
|
+
super(message)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -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
@@ -18,10 +18,11 @@ module RuboCop
|
|
18
18
|
def run
|
19
19
|
ensure_server!
|
20
20
|
Cache.status_path.delete if Cache.status_path.file?
|
21
|
+
read_stdin = ARGV.include?('-s') || ARGV.include?('--stdin')
|
21
22
|
send_request(
|
22
23
|
command: 'exec',
|
23
24
|
args: ARGV.dup,
|
24
|
-
body: $stdin.
|
25
|
+
body: read_stdin ? $stdin.read : ''
|
25
26
|
)
|
26
27
|
warn stderr unless stderr.empty?
|
27
28
|
status
|
@@ -31,7 +32,7 @@ module RuboCop
|
|
31
32
|
|
32
33
|
def ensure_server!
|
33
34
|
if incompatible_version?
|
34
|
-
|
35
|
+
warn 'RuboCop version incompatibility found, RuboCop server restarting...'
|
35
36
|
ClientCommand::Stop.new.run
|
36
37
|
elsif check_running_server
|
37
38
|
return
|