ruby-lsp 0.23.11 → 0.23.17

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -1
  4. data/exe/ruby-lsp-launcher +20 -11
  5. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
  6. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
  7. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +82 -116
  8. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +134 -183
  9. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -10
  10. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +97 -217
  11. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +139 -281
  12. data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
  13. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
  14. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +23 -55
  15. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
  16. data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
  18. data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
  19. data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
  20. data/lib/ruby_indexer/test/configuration_test.rb +48 -7
  21. data/lib/ruby_indexer/test/constant_test.rb +34 -34
  22. data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
  23. data/lib/ruby_indexer/test/index_test.rb +146 -135
  24. data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
  25. data/lib/ruby_indexer/test/method_test.rb +149 -123
  26. data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
  27. data/lib/ruby_indexer/test/rbs_indexer_test.rb +68 -73
  28. data/lib/ruby_indexer/test/test_case.rb +9 -3
  29. data/lib/ruby_indexer/test/uri_test.rb +15 -2
  30. data/lib/ruby_lsp/addon.rb +44 -71
  31. data/lib/ruby_lsp/base_server.rb +29 -32
  32. data/lib/ruby_lsp/client_capabilities.rb +10 -12
  33. data/lib/ruby_lsp/document.rb +40 -54
  34. data/lib/ruby_lsp/erb_document.rb +37 -41
  35. data/lib/ruby_lsp/global_state.rb +52 -57
  36. data/lib/ruby_lsp/internal.rb +2 -0
  37. data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
  38. data/lib/ruby_lsp/listeners/completion.rb +67 -73
  39. data/lib/ruby_lsp/listeners/definition.rb +44 -58
  40. data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
  41. data/lib/ruby_lsp/listeners/document_link.rb +50 -70
  42. data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
  43. data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
  44. data/lib/ruby_lsp/listeners/hover.rb +92 -110
  45. data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
  46. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
  47. data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
  48. data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
  49. data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
  50. data/lib/ruby_lsp/listeners/test_style.rb +167 -90
  51. data/lib/ruby_lsp/node_context.rb +12 -39
  52. data/lib/ruby_lsp/rbs_document.rb +9 -7
  53. data/lib/ruby_lsp/requests/code_action_resolve.rb +63 -59
  54. data/lib/ruby_lsp/requests/code_actions.rb +14 -26
  55. data/lib/ruby_lsp/requests/code_lens.rb +20 -19
  56. data/lib/ruby_lsp/requests/completion.rb +7 -20
  57. data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
  58. data/lib/ruby_lsp/requests/definition.rb +7 -17
  59. data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
  60. data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
  61. data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
  62. data/lib/ruby_lsp/requests/document_link.rb +6 -17
  63. data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
  64. data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
  65. data/lib/ruby_lsp/requests/formatting.rb +6 -9
  66. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +85 -0
  67. data/lib/ruby_lsp/requests/hover.rb +10 -20
  68. data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
  69. data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
  70. data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
  71. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
  72. data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
  73. data/lib/ruby_lsp/requests/references.rb +9 -53
  74. data/lib/ruby_lsp/requests/rename.rb +20 -46
  75. data/lib/ruby_lsp/requests/request.rb +8 -19
  76. data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
  77. data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
  78. data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
  79. data/lib/ruby_lsp/requests/signature_help.rb +8 -26
  80. data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
  81. data/lib/ruby_lsp/requests/support/common.rb +15 -55
  82. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
  83. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
  84. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
  85. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
  86. data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
  87. data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
  88. data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
  89. data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
  90. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
  91. data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
  92. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
  93. data/lib/ruby_lsp/response_builders/document_symbol.rb +14 -19
  94. data/lib/ruby_lsp/response_builders/hover.rb +11 -14
  95. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  96. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
  97. data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
  98. data/lib/ruby_lsp/response_builders/test_collection.rb +43 -10
  99. data/lib/ruby_lsp/ruby_document.rb +24 -92
  100. data/lib/ruby_lsp/scope.rb +7 -11
  101. data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
  102. data/lib/ruby_lsp/server.rb +182 -99
  103. data/lib/ruby_lsp/setup_bundler.rb +65 -60
  104. data/lib/ruby_lsp/static_docs.rb +11 -7
  105. data/lib/ruby_lsp/store.rb +29 -47
  106. data/lib/ruby_lsp/test_helper.rb +2 -12
  107. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +191 -0
  108. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
  109. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
  110. data/lib/ruby_lsp/type_inferrer.rb +13 -14
  111. data/lib/ruby_lsp/utils.rb +92 -83
  112. metadata +9 -3
@@ -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)
@@ -34,10 +25,8 @@ module RubyLsp
34
25
  code_units_cache: document.code_units_cache,
35
26
  )
36
27
 
37
- @response_builder = T.let(
38
- ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight].new,
39
- ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight],
40
- )
28
+ @response_builder = ResponseBuilders::CollectionResponseBuilder
29
+ .new #: ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight]
41
30
  Listeners::DocumentHighlight.new(
42
31
  @response_builder,
43
32
  node_context.node,
@@ -47,7 +36,8 @@ module RubyLsp
47
36
  )
48
37
  end
49
38
 
50
- sig { override.returns(T::Array[Interface::DocumentHighlight]) }
39
+ # @override
40
+ #: -> Array[Interface::DocumentHighlight]
51
41
  def perform
52
42
  @response_builder.response
53
43
  end
@@ -9,34 +9,23 @@ 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
- @response_builder = T.let(
33
- ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink].new,
34
- ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink],
35
- )
22
+ @response_builder = ResponseBuilders::CollectionResponseBuilder
23
+ .new #: ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink]
36
24
  Listeners::DocumentLink.new(@response_builder, uri, comments, dispatcher)
37
25
  end
38
26
 
39
- sig { override.returns(T::Array[Interface::DocumentLink]) }
27
+ # @override
28
+ #: -> Array[Interface::DocumentLink]
40
29
  def perform
41
30
  @response_builder.response
42
31
  end
@@ -13,21 +13,17 @@ 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
- @response_builder = T.let(ResponseBuilders::DocumentSymbol.new, ResponseBuilders::DocumentSymbol)
26
+ @response_builder = ResponseBuilders::DocumentSymbol.new #: ResponseBuilders::DocumentSymbol
31
27
  Listeners::DocumentSymbol.new(@response_builder, uri, dispatcher)
32
28
 
33
29
  Addon.addons.each do |addon|
@@ -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,31 +8,23 @@ 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
- @response_builder = T.let(
26
- ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange].new,
27
- ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange],
28
- )
29
- @listener = T.let(
30
- Listeners::FoldingRanges.new(@response_builder, comments, dispatcher),
31
- Listeners::FoldingRanges,
32
- )
21
+ @response_builder = ResponseBuilders::CollectionResponseBuilder
22
+ .new #: ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange]
23
+ @listener = Listeners::FoldingRanges.new(@response_builder, comments, dispatcher) #: Listeners::FoldingRanges
33
24
  end
34
25
 
35
- sig { override.returns(T::Array[Interface::FoldingRange]) }
26
+ # @override
27
+ #: -> Array[Interface::FoldingRange]
36
28
  def perform
37
29
  @listener.finalize_response!
38
30
  @response_builder.response
@@ -7,28 +7,25 @@ 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
27
- @active_formatter = T.let(global_state.active_formatter, T.nilable(Support::Formatter))
28
- @uri = T.let(document.uri, URI::Generic)
23
+ @active_formatter = global_state.active_formatter #: Support::Formatter?
24
+ @uri = 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,85 @@
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
+ TEST_KEYWORDS = ["test", "spec", "integration_test"]
12
+
13
+ TEST_PREFIX_PATTERN = /^(#{TEST_KEYWORDS.join("_|")}_)/
14
+ TEST_SUFFIX_PATTERN = /(_#{TEST_KEYWORDS.join("|_")})$/
15
+ TEST_PATTERN = /#{TEST_PREFIX_PATTERN}|#{TEST_SUFFIX_PATTERN}/
16
+
17
+ TEST_PREFIX_GLOB = "#{TEST_KEYWORDS.join("_,")}_" #: String
18
+ TEST_SUFFIX_GLOB = "_#{TEST_KEYWORDS.join(",_")}" #: String
19
+
20
+ #: (String path, String workspace_path) -> void
21
+ def initialize(path, workspace_path)
22
+ super()
23
+
24
+ @workspace_path = workspace_path
25
+ @path = path.delete_prefix(workspace_path) #: String
26
+ end
27
+
28
+ # @override
29
+ #: -> Array[String]
30
+ def perform
31
+ find_relevant_paths
32
+ end
33
+
34
+ private
35
+
36
+ #: -> Array[String]
37
+ def find_relevant_paths
38
+ candidate_paths = Dir.glob(File.join("**", relevant_filename_pattern))
39
+ return [] if candidate_paths.empty?
40
+
41
+ find_most_similar_with_jaccard(candidate_paths).map { File.join(@workspace_path, _1) }
42
+ end
43
+
44
+ #: -> String
45
+ def relevant_filename_pattern
46
+ input_basename = File.basename(@path, File.extname(@path))
47
+
48
+ relevant_basename_pattern =
49
+ if input_basename.match?(TEST_PATTERN)
50
+ input_basename.gsub(TEST_PATTERN, "")
51
+ else
52
+ "{{#{TEST_PREFIX_GLOB}}#{input_basename},#{input_basename}{#{TEST_SUFFIX_GLOB}}}"
53
+ end
54
+
55
+ "#{relevant_basename_pattern}#{File.extname(@path)}"
56
+ end
57
+
58
+ # Using the Jaccard algorithm to determine the similarity between the
59
+ # input path and the candidate relevant file paths.
60
+ # Ref: https://en.wikipedia.org/wiki/Jaccard_index
61
+ # The main idea of this algorithm is to take the size of interaction and divide
62
+ # it by the size of union between two sets (in our case the elements in each set
63
+ # would be the parts of the path separated by path divider.)
64
+ #: (Array[String] candidates) -> Array[String]
65
+ def find_most_similar_with_jaccard(candidates)
66
+ dirs = get_dir_parts(@path)
67
+
68
+ _, results = candidates
69
+ .group_by do |other_path|
70
+ other_dirs = get_dir_parts(other_path)
71
+ # Similarity score between the two directories
72
+ (dirs & other_dirs).size.to_f / (dirs | other_dirs).size
73
+ end
74
+ .max_by(&:first)
75
+
76
+ results || []
77
+ end
78
+
79
+ #: (String path) -> Set[String]
80
+ def get_dir_parts(path)
81
+ Set.new(File.dirname(path).split(File::SEPARATOR))
82
+ end
83
+ end
84
+ end
85
+ 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, SorbetLevel sorbet_level) -> void
34
23
  def initialize(document, global_state, position, dispatcher, sorbet_level)
35
24
  super()
36
25
 
@@ -48,8 +37,8 @@ module RubyLsp
48
37
 
49
38
  if should_refine_target?(parent, target)
50
39
  target = determine_target(
51
- T.must(target),
52
- T.must(parent),
40
+ target, #: as !nil
41
+ parent, #: as !nil
53
42
  position,
54
43
  )
55
44
  elsif position_outside_target?(position, target)
@@ -59,9 +48,9 @@ module RubyLsp
59
48
  # Don't need to instantiate any listeners if there's no target
60
49
  return unless target
61
50
 
62
- @target = T.let(target, T.nilable(Prism::Node))
51
+ @target = target #: Prism::Node?
63
52
  uri = document.uri
64
- @response_builder = T.let(ResponseBuilders::Hover.new, ResponseBuilders::Hover)
53
+ @response_builder = ResponseBuilders::Hover.new #: ResponseBuilders::Hover
65
54
  Listeners::Hover.new(@response_builder, global_state, uri, node_context, dispatcher, sorbet_level)
66
55
  Addon.addons.each do |addon|
67
56
  addon.create_hover_listener(@response_builder, node_context, dispatcher)
@@ -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,35 +9,24 @@ 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
 
33
- @response_builder = T.let(
34
- ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint].new,
35
- ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint],
36
- )
23
+ @response_builder = ResponseBuilders::CollectionResponseBuilder
24
+ .new #: ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
37
25
  Listeners::InlayHints.new(@response_builder, hints_configuration, dispatcher)
38
26
  end
39
27
 
40
- sig { override.returns(T::Array[Interface::InlayHint]) }
28
+ # @override
29
+ #: -> Array[Interface::InlayHint]
41
30
  def perform
42
31
  @response_builder.response
43
32
  end
@@ -6,12 +6,8 @@ module RubyLsp
6
6
  # The [on type formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting)
7
7
  # request formats code as the user is typing. For example, automatically adding `end` to class definitions.
8
8
  class OnTypeFormatting < Request
9
- extend T::Sig
10
-
11
9
  class << self
12
- extend T::Sig
13
-
14
- sig { returns(Interface::DocumentOnTypeFormattingRegistrationOptions) }
10
+ #: -> Interface::DocumentOnTypeFormattingRegistrationOptions
15
11
  def provider
16
12
  Interface::DocumentOnTypeFormattingRegistrationOptions.new(
17
13
  document_selector: nil,
@@ -21,38 +17,29 @@ module RubyLsp
21
17
  end
22
18
  end
23
19
 
24
- END_REGEXES = T.let(
25
- [
26
- /\b(if|unless|for|while|until)\b($|\s|\()/,
27
- /\b(class|module|def|case)\b($|\s)/,
28
- /.*\s\bdo\b($|\s)/,
29
- ],
30
- T::Array[Regexp],
31
- )
32
-
33
- sig do
34
- params(
35
- document: RubyDocument,
36
- position: T::Hash[Symbol, T.untyped],
37
- trigger_character: String,
38
- client_name: String,
39
- ).void
40
- end
20
+ END_REGEXES = [
21
+ /\b(if|unless|for|while|until)\b($|\s|\()/,
22
+ /\b(class|module|def|case)\b($|\s)/,
23
+ /.*\s\bdo\b($|\s)/,
24
+ ] #: Array[Regexp]
25
+
26
+ #: (RubyDocument document, Hash[Symbol, untyped] position, String trigger_character, String client_name) -> void
41
27
  def initialize(document, position, trigger_character, client_name)
42
28
  super()
43
29
  @document = document
44
- @lines = T.let(@document.source.lines, T::Array[String])
30
+ @lines = @document.source.lines #: Array[String]
45
31
  line = @lines[[position[:line] - 1, 0].max]
46
32
 
47
- @indentation = T.let(line ? find_indentation(line) : 0, Integer)
48
- @previous_line = T.let(line ? line.strip.chomp : "", String)
33
+ @indentation = line ? find_indentation(line) : 0 #: Integer
34
+ @previous_line = line ? line.strip.chomp : "" #: String
49
35
  @position = position
50
- @edits = T.let([], T::Array[Interface::TextEdit])
36
+ @edits = [] #: Array[Interface::TextEdit]
51
37
  @trigger_character = trigger_character
52
38
  @client_name = client_name
53
39
  end
54
40
 
55
- sig { override.returns(T.all(T::Array[Interface::TextEdit], Object)) }
41
+ # @override
42
+ #: -> (Array[Interface::TextEdit] & Object)
56
43
  def perform
57
44
  case @trigger_character
58
45
  when "{"
@@ -60,8 +47,13 @@ module RubyLsp
60
47
  when "|"
61
48
  handle_pipe if @document.syntax_error?
62
49
  when "\n"
63
- if (comment_match = @previous_line.match(/^#(\s*)/))
64
- handle_comment_line(T.must(comment_match[1]))
50
+ # If the previous line is a simple comment, we'll add a comment continuation
51
+ # But if it's a RBS signature starting with `#:`, we'll ignore it
52
+ # so users can immediately continue typing the method definition
53
+ if (comment_match = @previous_line.match(/^#(?!:)(\s*)/))
54
+ handle_comment_line(
55
+ comment_match[1], #: as !nil
56
+ )
65
57
  elsif @document.syntax_error?
66
58
  match = /(<<((-|~)?))(?<quote>['"`]?)(?<delimiter>\w+)\k<quote>/.match(@previous_line)
67
59
  heredoc_delimiter = match && match.named_captures["delimiter"]
@@ -81,12 +73,12 @@ module RubyLsp
81
73
 
82
74
  private
83
75
 
84
- sig { void }
76
+ #: -> void
85
77
  def handle_pipe
86
78
  current_line = @lines[@position[:line]]
87
79
  return unless /((?<=do)|(?<={))\s+\|/.match?(current_line)
88
80
 
89
- line = T.must(current_line)
81
+ line = current_line #: as !nil
90
82
 
91
83
  # If the user inserts the closing pipe manually to the end of the block argument, we need to avoid adding
92
84
  # an additional one and remove the previous one. This also helps to remove the user who accidentally
@@ -112,7 +104,7 @@ module RubyLsp
112
104
  move_cursor_to(@position[:line], @position[:character])
113
105
  end
114
106
 
115
- sig { void }
107
+ #: -> void
116
108
  def handle_curly_brace
117
109
  return unless /".*#\{/.match?(@previous_line)
118
110
 
@@ -120,7 +112,7 @@ module RubyLsp
120
112
  move_cursor_to(@position[:line], @position[:character])
121
113
  end
122
114
 
123
- sig { void }
115
+ #: -> void
124
116
  def handle_statement_end
125
117
  # If a keyword occurs in a line which appears be a comment or a string, we will not try to format it, since
126
118
  # it could be a coincidental match. This approach is not perfect, but it should cover most cases.
@@ -142,7 +134,7 @@ module RubyLsp
142
134
  end
143
135
  end
144
136
 
145
- sig { params(delimiter: String).void }
137
+ #: (String delimiter) -> void
146
138
  def handle_heredoc_end(delimiter)
147
139
  indents = " " * @indentation
148
140
  add_edit_with_text("\n")
@@ -150,12 +142,12 @@ module RubyLsp
150
142
  move_cursor_to(@position[:line], @indentation + 2)
151
143
  end
152
144
 
153
- sig { params(spaces: String).void }
145
+ #: (String spaces) -> void
154
146
  def handle_comment_line(spaces)
155
147
  add_edit_with_text("##{spaces}")
156
148
  end
157
149
 
158
- sig { params(text: String, position: T::Hash[Symbol, T.untyped]).void }
150
+ #: (String text, ?Hash[Symbol, untyped] position) -> void
159
151
  def add_edit_with_text(text, position = @position)
160
152
  pos = Interface::Position.new(
161
153
  line: position[:line],
@@ -168,9 +160,9 @@ module RubyLsp
168
160
  )
169
161
  end
170
162
 
171
- sig { params(line: Integer, character: Integer).void }
163
+ #: (Integer line, Integer character) -> void
172
164
  def move_cursor_to(line, character)
173
- return unless /Visual Studio Code|Cursor/.match?(@client_name)
165
+ return unless /Visual Studio Code|Cursor|VSCodium/.match?(@client_name)
174
166
 
175
167
  position = Interface::Position.new(
176
168
  line: line,
@@ -189,7 +181,7 @@ module RubyLsp
189
181
  )
190
182
  end
191
183
 
192
- sig { params(line: String).returns(Integer) }
184
+ #: (String line) -> Integer
193
185
  def find_indentation(line)
194
186
  count = 0
195
187
 
@@ -202,7 +194,7 @@ module RubyLsp
202
194
  count
203
195
  end
204
196
 
205
- sig { void }
197
+ #: -> void
206
198
  def auto_indent_after_end_keyword
207
199
  current_line = @lines[@position[:line]]
208
200
  return unless current_line && current_line.strip == "end"
@@ -7,22 +7,17 @@ module RubyLsp
7
7
  # [prepare_rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename)
8
8
  # # request checks the validity of a rename operation at a given location.
9
9
  class PrepareRename < Request
10
- extend T::Sig
11
10
  include Support::Common
12
11
 
13
- sig do
14
- params(
15
- document: RubyDocument,
16
- position: T::Hash[Symbol, T.untyped],
17
- ).void
18
- end
12
+ #: (RubyDocument document, Hash[Symbol, untyped] position) -> void
19
13
  def initialize(document, position)
20
14
  super()
21
15
  @document = document
22
- @position = T.let(position, T::Hash[Symbol, Integer])
16
+ @position = position #: Hash[Symbol, Integer]
23
17
  end
24
18
 
25
- sig { override.returns(T.nilable(Interface::Range)) }
19
+ # @override
20
+ #: -> Interface::Range?
26
21
  def perform
27
22
  char_position, _ = @document.find_index_by_position(@position)
28
23
 
@@ -9,26 +9,16 @@ module RubyLsp
9
9
  #
10
10
  # Currently only supports supertypes due to a limitation of the index.
11
11
  class PrepareTypeHierarchy < Request
12
- extend T::Sig
13
-
14
12
  include Support::Common
15
13
 
16
14
  class << self
17
- extend T::Sig
18
-
19
- sig { returns(Interface::TypeHierarchyOptions) }
15
+ #: -> Interface::TypeHierarchyOptions
20
16
  def provider
21
17
  Interface::TypeHierarchyOptions.new
22
18
  end
23
19
  end
24
20
 
25
- sig do
26
- params(
27
- document: T.any(RubyDocument, ERBDocument),
28
- index: RubyIndexer::Index,
29
- position: T::Hash[Symbol, T.untyped],
30
- ).void
31
- end
21
+ #: ((RubyDocument | ERBDocument) document, RubyIndexer::Index index, Hash[Symbol, untyped] position) -> void
32
22
  def initialize(document, index, position)
33
23
  super()
34
24
 
@@ -37,7 +27,8 @@ module RubyLsp
37
27
  @position = position
38
28
  end
39
29
 
40
- sig { override.returns(T.nilable(T::Array[Interface::TypeHierarchyItem])) }
30
+ # @override
31
+ #: -> Array[Interface::TypeHierarchyItem]?
41
32
  def perform
42
33
  context = @document.locate_node(
43
34
  @position,
@@ -58,8 +49,7 @@ module RubyLsp
58
49
 
59
50
  # While the spec allows for multiple entries, VSCode seems to only support one
60
51
  # We'll just return the first one for now
61
- first_entry = T.must(entries.first)
62
-
52
+ first_entry = entries.first #: as !nil
63
53
  range = range_from_location(first_entry.location)
64
54
 
65
55
  [
@@ -6,18 +6,17 @@ module RubyLsp
6
6
  # The [range formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting)
7
7
  # is used to format a selection or to format on paste.
8
8
  class RangeFormatting < Request
9
- extend T::Sig
10
-
11
- sig { params(global_state: GlobalState, document: RubyDocument, params: T::Hash[Symbol, T.untyped]).void }
9
+ #: (GlobalState global_state, RubyDocument document, Hash[Symbol, untyped] params) -> void
12
10
  def initialize(global_state, document, params)
13
11
  super()
14
12
  @document = document
15
- @uri = T.let(document.uri, URI::Generic)
13
+ @uri = document.uri #: URI::Generic
16
14
  @params = params
17
- @active_formatter = T.let(global_state.active_formatter, T.nilable(Support::Formatter))
15
+ @active_formatter = global_state.active_formatter #: Support::Formatter?
18
16
  end
19
17
 
20
- sig { override.returns(T.nilable(T::Array[Interface::TextEdit])) }
18
+ # @override
19
+ #: -> Array[Interface::TextEdit]?
21
20
  def perform
22
21
  return unless @active_formatter
23
22
  return if @document.syntax_error?