ruby-lsp 0.23.11 → 0.23.12

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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +12 -11
  5. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  6. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +52 -77
  7. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +61 -144
  8. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +8 -6
  9. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +73 -182
  10. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +48 -181
  11. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  12. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +12 -14
  13. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +21 -44
  14. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +40 -58
  15. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +9 -16
  16. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +5 -9
  17. data/lib/ruby_indexer/test/configuration_test.rb +32 -2
  18. data/lib/ruby_indexer/test/method_test.rb +2 -2
  19. data/lib/ruby_lsp/addon.rb +32 -67
  20. data/lib/ruby_lsp/base_server.rb +10 -10
  21. data/lib/ruby_lsp/client_capabilities.rb +4 -6
  22. data/lib/ruby_lsp/document.rb +21 -32
  23. data/lib/ruby_lsp/erb_document.rb +17 -27
  24. data/lib/ruby_lsp/global_state.rb +30 -32
  25. data/lib/ruby_lsp/internal.rb +2 -0
  26. data/lib/ruby_lsp/listeners/code_lens.rb +21 -39
  27. data/lib/ruby_lsp/listeners/completion.rb +34 -53
  28. data/lib/ruby_lsp/listeners/definition.rb +35 -49
  29. data/lib/ruby_lsp/listeners/document_highlight.rb +60 -69
  30. data/lib/ruby_lsp/listeners/document_link.rb +9 -19
  31. data/lib/ruby_lsp/listeners/document_symbol.rb +34 -48
  32. data/lib/ruby_lsp/listeners/folding_ranges.rb +31 -38
  33. data/lib/ruby_lsp/listeners/hover.rb +37 -47
  34. data/lib/ruby_lsp/listeners/inlay_hints.rb +3 -10
  35. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +29 -35
  36. data/lib/ruby_lsp/listeners/signature_help.rb +4 -23
  37. data/lib/ruby_lsp/listeners/spec_style.rb +199 -0
  38. data/lib/ruby_lsp/listeners/test_style.rb +136 -30
  39. data/lib/ruby_lsp/node_context.rb +8 -35
  40. data/lib/ruby_lsp/rbs_document.rb +7 -5
  41. data/lib/ruby_lsp/requests/code_action_resolve.rb +10 -10
  42. data/lib/ruby_lsp/requests/code_actions.rb +5 -14
  43. data/lib/ruby_lsp/requests/code_lens.rb +4 -13
  44. data/lib/ruby_lsp/requests/completion.rb +4 -15
  45. data/lib/ruby_lsp/requests/completion_resolve.rb +4 -4
  46. data/lib/ruby_lsp/requests/definition.rb +4 -12
  47. data/lib/ruby_lsp/requests/diagnostics.rb +6 -9
  48. data/lib/ruby_lsp/requests/discover_tests.rb +15 -3
  49. data/lib/ruby_lsp/requests/document_highlight.rb +3 -11
  50. data/lib/ruby_lsp/requests/document_link.rb +4 -13
  51. data/lib/ruby_lsp/requests/document_symbol.rb +4 -7
  52. data/lib/ruby_lsp/requests/folding_ranges.rb +4 -7
  53. data/lib/ruby_lsp/requests/formatting.rb +4 -7
  54. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +87 -0
  55. data/lib/ruby_lsp/requests/hover.rb +6 -16
  56. data/lib/ruby_lsp/requests/inlay_hints.rb +4 -13
  57. data/lib/ruby_lsp/requests/on_type_formatting.rb +17 -24
  58. data/lib/ruby_lsp/requests/prepare_rename.rb +3 -8
  59. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +4 -13
  60. data/lib/ruby_lsp/requests/range_formatting.rb +3 -4
  61. data/lib/ruby_lsp/requests/references.rb +5 -35
  62. data/lib/ruby_lsp/requests/rename.rb +9 -35
  63. data/lib/ruby_lsp/requests/request.rb +5 -17
  64. data/lib/ruby_lsp/requests/selection_ranges.rb +3 -3
  65. data/lib/ruby_lsp/requests/semantic_highlighting.rb +6 -23
  66. data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -5
  67. data/lib/ruby_lsp/requests/signature_help.rb +6 -24
  68. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  69. data/lib/ruby_lsp/requests/support/common.rb +12 -49
  70. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -14
  71. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +7 -10
  72. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +9 -15
  73. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  74. data/lib/ruby_lsp/requests/support/sorbet.rb +1 -7
  75. data/lib/ruby_lsp/requests/support/source_uri.rb +5 -16
  76. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +7 -10
  77. data/lib/ruby_lsp/requests/support/test_item.rb +14 -13
  78. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +4 -5
  79. data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -3
  80. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +4 -4
  81. data/lib/ruby_lsp/response_builders/document_symbol.rb +8 -11
  82. data/lib/ruby_lsp/response_builders/hover.rb +5 -5
  83. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  84. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +18 -40
  85. data/lib/ruby_lsp/response_builders/signature_help.rb +4 -5
  86. data/lib/ruby_lsp/response_builders/test_collection.rb +5 -9
  87. data/lib/ruby_lsp/ruby_document.rb +15 -40
  88. data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +106 -0
  89. data/lib/ruby_lsp/scope.rb +6 -10
  90. data/lib/ruby_lsp/server.rb +125 -74
  91. data/lib/ruby_lsp/setup_bundler.rb +22 -15
  92. data/lib/ruby_lsp/store.rb +12 -28
  93. data/lib/ruby_lsp/test_helper.rb +3 -12
  94. data/lib/ruby_lsp/test_reporter.rb +71 -0
  95. data/lib/ruby_lsp/test_unit_test_runner.rb +96 -0
  96. data/lib/ruby_lsp/type_inferrer.rb +9 -13
  97. data/lib/ruby_lsp/utils.rb +27 -65
  98. metadata +8 -3
@@ -7,8 +7,6 @@ module RubyLsp
7
7
  # request informs the editor of RuboCop quick fixes that can be applied. These are accessible by hovering over a
8
8
  # specific diagnostic.
9
9
  class CodeActions < Request
10
- extend T::Sig
11
-
12
10
  EXTRACT_TO_VARIABLE_TITLE = "Refactor: Extract Variable"
13
11
  EXTRACT_TO_METHOD_TITLE = "Refactor: Extract Method"
14
12
  TOGGLE_BLOCK_STYLE_TITLE = "Refactor: Toggle block style"
@@ -29,9 +27,7 @@ module RubyLsp
29
27
  )
30
28
 
31
29
  class << self
32
- extend T::Sig
33
-
34
- sig { returns(Interface::CodeActionRegistrationOptions) }
30
+ #: -> Interface::CodeActionRegistrationOptions
35
31
  def provider
36
32
  Interface::CodeActionRegistrationOptions.new(
37
33
  document_selector: nil,
@@ -40,13 +36,7 @@ module RubyLsp
40
36
  end
41
37
  end
42
38
 
43
- sig do
44
- params(
45
- document: T.any(RubyDocument, ERBDocument),
46
- range: T::Hash[Symbol, T.untyped],
47
- context: T::Hash[Symbol, T.untyped],
48
- ).void
49
- end
39
+ #: ((RubyDocument | ERBDocument) document, Hash[Symbol, untyped] range, Hash[Symbol, untyped] context) -> void
50
40
  def initialize(document, range, context)
51
41
  super()
52
42
  @document = document
@@ -55,7 +45,8 @@ module RubyLsp
55
45
  @context = context
56
46
  end
57
47
 
58
- sig { override.returns(T.nilable(T.all(T::Array[Interface::CodeAction], Object))) }
48
+ # @override
49
+ #: -> (Array[Interface::CodeAction] & Object)?
59
50
  def perform
60
51
  diagnostics = @context[:diagnostics]
61
52
 
@@ -88,7 +79,7 @@ module RubyLsp
88
79
 
89
80
  private
90
81
 
91
- sig { returns(T::Array[Interface::CodeAction]) }
82
+ #: -> Array[Interface::CodeAction]
92
83
  def attribute_actions
93
84
  return [] unless @document.is_a?(RubyDocument)
94
85
 
@@ -11,24 +11,14 @@ module RubyLsp
11
11
  # [code lens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
12
12
  # request informs the editor of runnable commands such as testing and debugging.
13
13
  class CodeLens < Request
14
- extend T::Sig
15
-
16
14
  class << self
17
- extend T::Sig
18
-
19
- sig { returns(Interface::CodeLensOptions) }
15
+ #: -> Interface::CodeLensOptions
20
16
  def provider
21
17
  Interface::CodeLensOptions.new(resolve_provider: false)
22
18
  end
23
19
  end
24
20
 
25
- sig do
26
- params(
27
- global_state: GlobalState,
28
- uri: URI::Generic,
29
- dispatcher: Prism::Dispatcher,
30
- ).void
31
- end
21
+ #: (GlobalState global_state, URI::Generic uri, Prism::Dispatcher dispatcher) -> void
32
22
  def initialize(global_state, uri, dispatcher)
33
23
  @response_builder = T.let(
34
24
  ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens].new,
@@ -42,7 +32,8 @@ module RubyLsp
42
32
  end
43
33
  end
44
34
 
45
- sig { override.returns(T::Array[Interface::CodeLens]) }
35
+ # @override
36
+ #: -> Array[Interface::CodeLens]
46
37
  def perform
47
38
  @response_builder.response
48
39
  end
@@ -8,12 +8,8 @@ module RubyLsp
8
8
  # The [completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
9
9
  # suggests possible completions according to what the developer is typing.
10
10
  class Completion < Request
11
- extend T::Sig
12
-
13
11
  class << self
14
- extend T::Sig
15
-
16
- sig { returns(Interface::CompletionOptions) }
12
+ #: -> Interface::CompletionOptions
17
13
  def provider
18
14
  Interface::CompletionOptions.new(
19
15
  resolve_provider: true,
@@ -25,15 +21,7 @@ module RubyLsp
25
21
  end
26
22
  end
27
23
 
28
- sig do
29
- params(
30
- document: T.any(RubyDocument, ERBDocument),
31
- global_state: GlobalState,
32
- params: T::Hash[Symbol, T.untyped],
33
- sorbet_level: RubyDocument::SorbetLevel,
34
- dispatcher: Prism::Dispatcher,
35
- ).void
36
- end
24
+ #: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] params, RubyDocument::SorbetLevel sorbet_level, Prism::Dispatcher dispatcher) -> void
37
25
  def initialize(document, global_state, params, sorbet_level, dispatcher)
38
26
  super()
39
27
  @target = T.let(nil, T.nilable(Prism::Node))
@@ -102,7 +90,8 @@ module RubyLsp
102
90
  end
103
91
  end
104
92
 
105
- sig { override.returns(T::Array[Interface::CompletionItem]) }
93
+ # @override
94
+ #: -> Array[Interface::CompletionItem]
106
95
  def perform
107
96
  return [] unless @target
108
97
 
@@ -14,21 +14,21 @@ module RubyLsp
14
14
  # At most 10 definitions are included, to ensure low latency during request processing and rendering the completion
15
15
  # item.
16
16
  class CompletionResolve < Request
17
- extend T::Sig
18
17
  include Requests::Support::Common
19
18
 
20
19
  # set a limit on the number of documentation entries returned, to avoid rendering performance issues
21
20
  # https://github.com/Shopify/ruby-lsp/pull/1798
22
21
  MAX_DOCUMENTATION_ENTRIES = 10
23
22
 
24
- sig { params(global_state: GlobalState, item: T::Hash[Symbol, T.untyped]).void }
23
+ #: (GlobalState global_state, Hash[Symbol, untyped] item) -> void
25
24
  def initialize(global_state, item)
26
25
  super()
27
26
  @index = T.let(global_state.index, RubyIndexer::Index)
28
27
  @item = item
29
28
  end
30
29
 
31
- sig { override.returns(T::Hash[Symbol, T.untyped]) }
30
+ # @override
31
+ #: -> Hash[Symbol, untyped]
32
32
  def perform
33
33
  return @item if @item.dig(:data, :skip_resolve)
34
34
 
@@ -78,7 +78,7 @@ module RubyLsp
78
78
 
79
79
  private
80
80
 
81
- sig { params(item: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
81
+ #: (Hash[Symbol, untyped] item) -> Hash[Symbol, untyped]
82
82
  def keyword_resolve(item)
83
83
  keyword = item[:label]
84
84
  content = KEYWORD_DOCS[keyword]
@@ -9,18 +9,9 @@ module RubyLsp
9
9
  # request](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition) jumps to the
10
10
  # definition of the symbol under the cursor.
11
11
  class Definition < Request
12
- extend T::Sig
13
12
  extend T::Generic
14
13
 
15
- sig do
16
- params(
17
- document: T.any(RubyDocument, ERBDocument),
18
- global_state: GlobalState,
19
- position: T::Hash[Symbol, T.untyped],
20
- dispatcher: Prism::Dispatcher,
21
- sorbet_level: RubyDocument::SorbetLevel,
22
- ).void
23
- end
14
+ #: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher, RubyDocument::SorbetLevel sorbet_level) -> void
24
15
  def initialize(document, global_state, position, dispatcher, sorbet_level)
25
16
  super()
26
17
  @response_builder = T.let(
@@ -103,7 +94,8 @@ module RubyLsp
103
94
  @target = T.let(target, T.nilable(Prism::Node))
104
95
  end
105
96
 
106
- sig { override.returns(T::Array[T.any(Interface::Location, Interface::LocationLink)]) }
97
+ # @override
98
+ #: -> Array[(Interface::Location | Interface::LocationLink)]
107
99
  def perform
108
100
  @dispatcher.dispatch_once(@target) if @target
109
101
  @response_builder.response
@@ -111,7 +103,7 @@ module RubyLsp
111
103
 
112
104
  private
113
105
 
114
- sig { params(position: T::Hash[Symbol, T.untyped], target: T.nilable(Prism::Node)).returns(T::Boolean) }
106
+ #: (Hash[Symbol, untyped] position, Prism::Node? target) -> bool
115
107
  def position_outside_target?(position, target)
116
108
  case target
117
109
  when Prism::GlobalVariableAndWriteNode,
@@ -7,12 +7,8 @@ module RubyLsp
7
7
  # [diagnostics](https://microsoft.github.io/language-server-protocol/specification#textDocument_publishDiagnostics)
8
8
  # request informs the editor of RuboCop offenses for a given file.
9
9
  class Diagnostics < Request
10
- extend T::Sig
11
-
12
10
  class << self
13
- extend T::Sig
14
-
15
- sig { returns(Interface::DiagnosticRegistrationOptions) }
11
+ #: -> Interface::DiagnosticRegistrationOptions
16
12
  def provider
17
13
  Interface::DiagnosticRegistrationOptions.new(
18
14
  document_selector: nil,
@@ -22,7 +18,7 @@ module RubyLsp
22
18
  end
23
19
  end
24
20
 
25
- sig { params(global_state: GlobalState, document: RubyDocument).void }
21
+ #: (GlobalState global_state, RubyDocument document) -> void
26
22
  def initialize(global_state, document)
27
23
  super()
28
24
  @active_linters = T.let(global_state.active_linters, T::Array[Support::Formatter])
@@ -30,7 +26,8 @@ module RubyLsp
30
26
  @uri = T.let(document.uri, URI::Generic)
31
27
  end
32
28
 
33
- sig { override.returns(T.nilable(T.all(T::Array[Interface::Diagnostic], Object))) }
29
+ # @override
30
+ #: -> (Array[Interface::Diagnostic] & Object)?
34
31
  def perform
35
32
  diagnostics = []
36
33
  diagnostics.concat(syntax_error_diagnostics, syntax_warning_diagnostics)
@@ -50,7 +47,7 @@ module RubyLsp
50
47
 
51
48
  private
52
49
 
53
- sig { returns(T::Array[Interface::Diagnostic]) }
50
+ #: -> Array[Interface::Diagnostic]
54
51
  def syntax_warning_diagnostics
55
52
  @document.parse_result.warnings.map do |warning|
56
53
  location = warning.location
@@ -73,7 +70,7 @@ module RubyLsp
73
70
  end
74
71
  end
75
72
 
76
- sig { returns(T::Array[Interface::Diagnostic]) }
73
+ #: -> Array[Interface::Diagnostic]
77
74
  def syntax_error_diagnostics
78
75
  @document.parse_result.errors.map do |error|
79
76
  location = error.location
@@ -2,16 +2,16 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "ruby_lsp/listeners/test_style"
5
+ require "ruby_lsp/listeners/spec_style"
5
6
 
6
7
  module RubyLsp
7
8
  module Requests
8
9
  # This is a custom request to ask the server to parse a test file and discover all available examples in it. Add-ons
9
10
  # can augment the behavior through listeners, allowing them to handle discovery for different frameworks
10
11
  class DiscoverTests < Request
11
- extend T::Sig
12
12
  include Support::Common
13
13
 
14
- sig { params(global_state: GlobalState, document: RubyDocument, dispatcher: Prism::Dispatcher).void }
14
+ #: (GlobalState global_state, RubyDocument document, Prism::Dispatcher dispatcher) -> void
15
15
  def initialize(global_state, document, dispatcher)
16
16
  super()
17
17
  @global_state = global_state
@@ -21,7 +21,8 @@ module RubyLsp
21
21
  @index = T.let(global_state.index, RubyIndexer::Index)
22
22
  end
23
23
 
24
- sig { override.returns(T::Array[Support::TestItem]) }
24
+ # @override
25
+ #: -> Array[Support::TestItem]
25
26
  def perform
26
27
  uri = @document.uri
27
28
 
@@ -35,6 +36,12 @@ module RubyLsp
35
36
  # in the index first and then discover the tests, all in the same traversal.
36
37
  if @index.entries_for(uri.to_s)
37
38
  Listeners::TestStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
39
+ Listeners::SpecStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
40
+
41
+ Addon.addons.each do |addon|
42
+ addon.create_discover_tests_listener(@response_builder, @dispatcher, @document.uri)
43
+ end
44
+
38
45
  @dispatcher.visit(@document.parse_result.value)
39
46
  else
40
47
  @global_state.synchronize do
@@ -47,6 +54,11 @@ module RubyLsp
47
54
  )
48
55
 
49
56
  Listeners::TestStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
57
+ Listeners::SpecStyle.new(@response_builder, @global_state, @dispatcher, @document.uri)
58
+
59
+ Addon.addons.each do |addon|
60
+ addon.create_discover_tests_listener(@response_builder, @dispatcher, @document.uri)
61
+ end
50
62
 
51
63
  # Dispatch the events both for indexing the test file and discovering the tests. The order here is
52
64
  # important because we need the index to be aware of the existing classes/modules/methods before the test
@@ -13,16 +13,7 @@ module RubyLsp
13
13
  # For writable elements like constants or variables, their read/write occurrences should be highlighted differently.
14
14
  # This is achieved by sending different "kind" attributes to the editor (2 for read and 3 for write).
15
15
  class DocumentHighlight < Request
16
- extend T::Sig
17
-
18
- sig do
19
- params(
20
- global_state: GlobalState,
21
- document: T.any(RubyDocument, ERBDocument),
22
- position: T::Hash[Symbol, T.untyped],
23
- dispatcher: Prism::Dispatcher,
24
- ).void
25
- end
16
+ #: (GlobalState global_state, (RubyDocument | ERBDocument) document, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher) -> void
26
17
  def initialize(global_state, document, position, dispatcher)
27
18
  super()
28
19
  char_position, _ = document.find_index_by_position(position)
@@ -47,7 +38,8 @@ module RubyLsp
47
38
  )
48
39
  end
49
40
 
50
- sig { override.returns(T::Array[Interface::DocumentHighlight]) }
41
+ # @override
42
+ #: -> Array[Interface::DocumentHighlight]
51
43
  def perform
52
44
  @response_builder.response
53
45
  end
@@ -9,24 +9,14 @@ module RubyLsp
9
9
  # makes `# source://PATH_TO_FILE#line` comments in a Ruby/RBI file clickable if the file exists.
10
10
  # When the user clicks the link, it'll open that location.
11
11
  class DocumentLink < Request
12
- extend T::Sig
13
-
14
12
  class << self
15
- extend T::Sig
16
-
17
- sig { returns(Interface::DocumentLinkOptions) }
13
+ #: -> Interface::DocumentLinkOptions
18
14
  def provider
19
15
  Interface::DocumentLinkOptions.new(resolve_provider: false)
20
16
  end
21
17
  end
22
18
 
23
- sig do
24
- params(
25
- uri: URI::Generic,
26
- comments: T::Array[Prism::Comment],
27
- dispatcher: Prism::Dispatcher,
28
- ).void
29
- end
19
+ #: (URI::Generic uri, Array[Prism::Comment] comments, Prism::Dispatcher dispatcher) -> void
30
20
  def initialize(uri, comments, dispatcher)
31
21
  super()
32
22
  @response_builder = T.let(
@@ -36,7 +26,8 @@ module RubyLsp
36
26
  Listeners::DocumentLink.new(@response_builder, uri, comments, dispatcher)
37
27
  end
38
28
 
39
- sig { override.returns(T::Array[Interface::DocumentLink]) }
29
+ # @override
30
+ #: -> Array[Interface::DocumentLink]
40
31
  def perform
41
32
  @response_builder.response
42
33
  end
@@ -13,18 +13,14 @@ module RubyLsp
13
13
  # In VS Code, symbol search known as 'Go To Symbol in Editor' and can be accessed with Ctrl/Cmd-Shift-O,
14
14
  # or by opening the command palette and inserting an `@` symbol.
15
15
  class DocumentSymbol < Request
16
- extend T::Sig
17
-
18
16
  class << self
19
- extend T::Sig
20
-
21
- sig { returns(Interface::DocumentSymbolOptions) }
17
+ #: -> Interface::DocumentSymbolOptions
22
18
  def provider
23
19
  Interface::DocumentSymbolOptions.new
24
20
  end
25
21
  end
26
22
 
27
- sig { params(uri: URI::Generic, dispatcher: Prism::Dispatcher).void }
23
+ #: (URI::Generic uri, Prism::Dispatcher dispatcher) -> void
28
24
  def initialize(uri, dispatcher)
29
25
  super()
30
26
  @response_builder = T.let(ResponseBuilders::DocumentSymbol.new, ResponseBuilders::DocumentSymbol)
@@ -35,7 +31,8 @@ module RubyLsp
35
31
  end
36
32
  end
37
33
 
38
- sig { override.returns(T::Array[Interface::DocumentSymbol]) }
34
+ # @override
35
+ #: -> Array[Interface::DocumentSymbol]
39
36
  def perform
40
37
  @response_builder.response
41
38
  end
@@ -8,18 +8,14 @@ module RubyLsp
8
8
  # The [folding ranges](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)
9
9
  # request informs the editor of the ranges where and how code can be folded.
10
10
  class FoldingRanges < Request
11
- extend T::Sig
12
-
13
11
  class << self
14
- extend T::Sig
15
-
16
- sig { returns(TrueClass) }
12
+ #: -> TrueClass
17
13
  def provider
18
14
  true
19
15
  end
20
16
  end
21
17
 
22
- sig { params(comments: T::Array[Prism::Comment], dispatcher: Prism::Dispatcher).void }
18
+ #: (Array[Prism::Comment] comments, Prism::Dispatcher dispatcher) -> void
23
19
  def initialize(comments, dispatcher)
24
20
  super()
25
21
  @response_builder = T.let(
@@ -32,7 +28,8 @@ module RubyLsp
32
28
  )
33
29
  end
34
30
 
35
- sig { override.returns(T::Array[Interface::FoldingRange]) }
31
+ # @override
32
+ #: -> Array[Interface::FoldingRange]
36
33
  def perform
37
34
  @listener.finalize_response!
38
35
  @response_builder.response
@@ -7,20 +7,16 @@ module RubyLsp
7
7
  # request uses RuboCop to fix auto-correctable offenses in the document. This requires enabling format on save and
8
8
  # registering the ruby-lsp as the Ruby formatter.
9
9
  class Formatting < Request
10
- extend T::Sig
11
-
12
10
  class Error < StandardError; end
13
11
 
14
12
  class << self
15
- extend T::Sig
16
-
17
- sig { returns(TrueClass) }
13
+ #: -> TrueClass
18
14
  def provider
19
15
  true
20
16
  end
21
17
  end
22
18
 
23
- sig { params(global_state: GlobalState, document: RubyDocument).void }
19
+ #: (GlobalState global_state, RubyDocument document) -> void
24
20
  def initialize(global_state, document)
25
21
  super()
26
22
  @document = document
@@ -28,7 +24,8 @@ module RubyLsp
28
24
  @uri = T.let(document.uri, URI::Generic)
29
25
  end
30
26
 
31
- sig { override.returns(T.nilable(T.all(T::Array[Interface::TextEdit], Object))) }
27
+ # @override
28
+ #: -> (Array[Interface::TextEdit] & Object)?
32
29
  def perform
33
30
  return unless @active_formatter
34
31
  return if @document.syntax_error?
@@ -0,0 +1,87 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Requests
6
+ # GoTo Relevant File is a custom [LSP
7
+ # request](https://microsoft.github.io/language-server-protocol/specification#requestMessage)
8
+ # that navigates to the relevant file for the current document.
9
+ # Currently, it supports source code file <> test file navigation.
10
+ class GoToRelevantFile < Request
11
+ extend T::Sig
12
+
13
+ TEST_KEYWORDS = ["test", "spec", "integration_test"]
14
+
15
+ TEST_PREFIX_PATTERN = /^(#{TEST_KEYWORDS.join("_|")}_)/
16
+ TEST_SUFFIX_PATTERN = /(_#{TEST_KEYWORDS.join("|_")})$/
17
+ TEST_PATTERN = /#{TEST_PREFIX_PATTERN}|#{TEST_SUFFIX_PATTERN}/
18
+
19
+ TEST_PREFIX_GLOB = T.let("#{TEST_KEYWORDS.join("_,")}_", String)
20
+ TEST_SUFFIX_GLOB = T.let("_#{TEST_KEYWORDS.join(",_")}", String)
21
+
22
+ #: (String path, String workspace_path) -> void
23
+ def initialize(path, workspace_path)
24
+ super()
25
+
26
+ @workspace_path = workspace_path
27
+ @path = T.let(path.delete_prefix(workspace_path), String)
28
+ end
29
+
30
+ # @override
31
+ #: -> Array[String]
32
+ def perform
33
+ find_relevant_paths
34
+ end
35
+
36
+ private
37
+
38
+ #: -> Array[String]
39
+ def find_relevant_paths
40
+ candidate_paths = Dir.glob(File.join("**", relevant_filename_pattern))
41
+ return [] if candidate_paths.empty?
42
+
43
+ find_most_similar_with_jaccard(candidate_paths).map { File.join(@workspace_path, _1) }
44
+ end
45
+
46
+ #: -> String
47
+ def relevant_filename_pattern
48
+ input_basename = File.basename(@path, File.extname(@path))
49
+
50
+ relevant_basename_pattern =
51
+ if input_basename.match?(TEST_PATTERN)
52
+ input_basename.gsub(TEST_PATTERN, "")
53
+ else
54
+ "{{#{TEST_PREFIX_GLOB}}#{input_basename},#{input_basename}{#{TEST_SUFFIX_GLOB}}}"
55
+ end
56
+
57
+ "#{relevant_basename_pattern}#{File.extname(@path)}"
58
+ end
59
+
60
+ # Using the Jaccard algorithm to determine the similarity between the
61
+ # input path and the candidate relevant file paths.
62
+ # Ref: https://en.wikipedia.org/wiki/Jaccard_index
63
+ # The main idea of this algorithm is to take the size of interaction and divide
64
+ # it by the size of union between two sets (in our case the elements in each set
65
+ # would be the parts of the path separated by path divider.)
66
+ #: (Array[String] candidates) -> Array[String]
67
+ def find_most_similar_with_jaccard(candidates)
68
+ dirs = get_dir_parts(@path)
69
+
70
+ _, results = candidates
71
+ .group_by do |other_path|
72
+ other_dirs = get_dir_parts(other_path)
73
+ # Similarity score between the two directories
74
+ (dirs & other_dirs).size.to_f / (dirs | other_dirs).size
75
+ end
76
+ .max_by(&:first)
77
+
78
+ results || []
79
+ end
80
+
81
+ #: (String path) -> Set[String]
82
+ def get_dir_parts(path)
83
+ Set.new(File.dirname(path).split(File::SEPARATOR))
84
+ end
85
+ end
86
+ end
87
+ end
@@ -8,13 +8,10 @@ module RubyLsp
8
8
  # The [hover request](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
9
9
  # displays the documentation for the symbol currently under the cursor.
10
10
  class Hover < Request
11
- extend T::Sig
12
11
  extend T::Generic
13
12
 
14
13
  class << self
15
- extend T::Sig
16
-
17
- sig { returns(Interface::HoverOptions) }
14
+ #: -> Interface::HoverOptions
18
15
  def provider
19
16
  Interface::HoverOptions.new
20
17
  end
@@ -22,15 +19,7 @@ module RubyLsp
22
19
 
23
20
  ResponseType = type_member { { fixed: T.nilable(Interface::Hover) } }
24
21
 
25
- sig do
26
- params(
27
- document: T.any(RubyDocument, ERBDocument),
28
- global_state: GlobalState,
29
- position: T::Hash[Symbol, T.untyped],
30
- dispatcher: Prism::Dispatcher,
31
- sorbet_level: RubyDocument::SorbetLevel,
32
- ).void
33
- end
22
+ #: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher, RubyDocument::SorbetLevel sorbet_level) -> void
34
23
  def initialize(document, global_state, position, dispatcher, sorbet_level)
35
24
  super()
36
25
 
@@ -70,7 +59,8 @@ module RubyLsp
70
59
  @dispatcher = dispatcher
71
60
  end
72
61
 
73
- sig { override.returns(ResponseType) }
62
+ # @override
63
+ #: -> ResponseType
74
64
  def perform
75
65
  return unless @target
76
66
 
@@ -88,14 +78,14 @@ module RubyLsp
88
78
 
89
79
  private
90
80
 
91
- sig { params(parent: T.nilable(Prism::Node), target: T.nilable(Prism::Node)).returns(T::Boolean) }
81
+ #: (Prism::Node? parent, Prism::Node? target) -> bool
92
82
  def should_refine_target?(parent, target)
93
83
  (Listeners::Hover::ALLOWED_TARGETS.include?(parent.class) &&
94
84
  !Listeners::Hover::ALLOWED_TARGETS.include?(target.class)) ||
95
85
  (parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
96
86
  end
97
87
 
98
- sig { params(position: T::Hash[Symbol, T.untyped], target: T.nilable(Prism::Node)).returns(T::Boolean) }
88
+ #: (Hash[Symbol, untyped] position, Prism::Node? target) -> bool
99
89
  def position_outside_target?(position, target)
100
90
  case target
101
91
  when Prism::GlobalVariableAndWriteNode,
@@ -9,24 +9,14 @@ module RubyLsp
9
9
  # are labels added directly in the code that explicitly show the user something that might
10
10
  # otherwise just be implied.
11
11
  class InlayHints < Request
12
- extend T::Sig
13
-
14
12
  class << self
15
- extend T::Sig
16
-
17
- sig { returns(Interface::InlayHintOptions) }
13
+ #: -> Interface::InlayHintOptions
18
14
  def provider
19
15
  Interface::InlayHintOptions.new(resolve_provider: false)
20
16
  end
21
17
  end
22
18
 
23
- sig do
24
- params(
25
- document: T.any(RubyDocument, ERBDocument),
26
- hints_configuration: RequestConfig,
27
- dispatcher: Prism::Dispatcher,
28
- ).void
29
- end
19
+ #: ((RubyDocument | ERBDocument) document, RequestConfig hints_configuration, Prism::Dispatcher dispatcher) -> void
30
20
  def initialize(document, hints_configuration, dispatcher)
31
21
  super()
32
22
 
@@ -37,7 +27,8 @@ module RubyLsp
37
27
  Listeners::InlayHints.new(@response_builder, hints_configuration, dispatcher)
38
28
  end
39
29
 
40
- sig { override.returns(T::Array[Interface::InlayHint]) }
30
+ # @override
31
+ #: -> Array[Interface::InlayHint]
41
32
  def perform
42
33
  @response_builder.response
43
34
  end