ruby-lsp 0.23.16 → 0.23.18

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +16 -19
  4. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +0 -3
  5. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +9 -19
  6. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +37 -68
  7. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -9
  8. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +1 -10
  9. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
  10. data/lib/ruby_indexer/test/index_test.rb +7 -0
  11. data/lib/ruby_indexer/test/method_test.rb +7 -7
  12. data/lib/ruby_indexer/test/prefix_tree_test.rb +8 -8
  13. data/lib/ruby_indexer/test/rbs_indexer_test.rb +4 -3
  14. data/lib/ruby_indexer/test/test_case.rb +7 -1
  15. data/lib/ruby_lsp/client_capabilities.rb +6 -1
  16. data/lib/ruby_lsp/document.rb +7 -11
  17. data/lib/ruby_lsp/erb_document.rb +3 -6
  18. data/lib/ruby_lsp/internal.rb +6 -1
  19. data/lib/ruby_lsp/listeners/completion.rb +8 -8
  20. data/lib/ruby_lsp/listeners/definition.rb +7 -7
  21. data/lib/ruby_lsp/listeners/document_link.rb +7 -10
  22. data/lib/ruby_lsp/listeners/hover.rb +18 -14
  23. data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
  24. data/lib/ruby_lsp/listeners/spec_style.rb +11 -11
  25. data/lib/ruby_lsp/listeners/test_discovery.rb +1 -1
  26. data/lib/ruby_lsp/listeners/test_style.rb +10 -5
  27. data/lib/ruby_lsp/rbs_document.rb +3 -6
  28. data/lib/ruby_lsp/requests/code_action_resolve.rb +44 -39
  29. data/lib/ruby_lsp/requests/code_lens.rb +16 -4
  30. data/lib/ruby_lsp/requests/completion.rb +2 -2
  31. data/lib/ruby_lsp/requests/definition.rb +3 -6
  32. data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
  33. data/lib/ruby_lsp/requests/document_link.rb +1 -1
  34. data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
  35. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +0 -2
  36. data/lib/ruby_lsp/requests/hover.rb +2 -5
  37. data/lib/ruby_lsp/requests/inlay_hints.rb +1 -1
  38. data/lib/ruby_lsp/requests/references.rb +1 -16
  39. data/lib/ruby_lsp/requests/rename.rb +1 -4
  40. data/lib/ruby_lsp/requests/request.rb +3 -2
  41. data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
  42. data/lib/ruby_lsp/requests/signature_help.rb +1 -1
  43. data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
  44. data/lib/ruby_lsp/requests/support/common.rb +0 -5
  45. data/lib/ruby_lsp/requests/support/test_item.rb +7 -1
  46. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -4
  47. data/lib/ruby_lsp/response_builders/document_symbol.rb +2 -3
  48. data/lib/ruby_lsp/response_builders/hover.rb +1 -4
  49. data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
  50. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +1 -2
  51. data/lib/ruby_lsp/response_builders/signature_help.rb +1 -2
  52. data/lib/ruby_lsp/response_builders/test_collection.rb +29 -3
  53. data/lib/ruby_lsp/ruby_document.rb +3 -36
  54. data/lib/ruby_lsp/server.rb +76 -22
  55. data/lib/ruby_lsp/store.rb +6 -6
  56. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +47 -10
  57. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +6 -23
  58. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +5 -17
  59. data/lib/ruby_lsp/utils.rb +43 -0
  60. metadata +1 -1
@@ -22,7 +22,7 @@ module RubyIndexer
22
22
  end
23
23
 
24
24
  def test_multiple_items
25
- tree = PrefixTree[String].new
25
+ tree = PrefixTree.new #: PrefixTree[String]
26
26
  ["foo", "bar", "baz"].each { |item| tree.insert(item, item) }
27
27
 
28
28
  assert_equal(["baz", "bar", "foo"], tree.search(""))
@@ -34,7 +34,7 @@ module RubyIndexer
34
34
  end
35
35
 
36
36
  def test_multiple_prefixes
37
- tree = PrefixTree[String].new
37
+ tree = PrefixTree.new #: PrefixTree[String]
38
38
  ["fo", "foo"].each { |item| tree.insert(item, item) }
39
39
 
40
40
  assert_equal(["fo", "foo"], tree.search(""))
@@ -45,7 +45,7 @@ module RubyIndexer
45
45
  end
46
46
 
47
47
  def test_multiple_prefixes_with_shuffled_order
48
- tree = PrefixTree[String].new
48
+ tree = PrefixTree.new #: PrefixTree[String]
49
49
  [
50
50
  "foo/bar/base",
51
51
  "foo/bar/on",
@@ -97,7 +97,7 @@ module RubyIndexer
97
97
  end
98
98
 
99
99
  def test_deletion
100
- tree = PrefixTree[String].new
100
+ tree = PrefixTree.new #: PrefixTree[String]
101
101
  ["foo/bar", "foo/baz"].each { |item| tree.insert(item, item) }
102
102
  assert_equal(["foo/baz", "foo/bar"], tree.search("foo"))
103
103
 
@@ -107,7 +107,7 @@ module RubyIndexer
107
107
  end
108
108
 
109
109
  def test_delete_does_not_impact_other_keys_with_the_same_value
110
- tree = PrefixTree[String].new
110
+ tree = PrefixTree.new #: PrefixTree[String]
111
111
  tree.insert("key1", "value")
112
112
  tree.insert("key2", "value")
113
113
  assert_equal(["value", "value"], tree.search("key"))
@@ -118,7 +118,7 @@ module RubyIndexer
118
118
  end
119
119
 
120
120
  def test_deleted_node_is_removed_from_the_tree
121
- tree = PrefixTree[String].new
121
+ tree = PrefixTree.new #: PrefixTree[String]
122
122
  tree.insert("foo/bar", "foo/bar")
123
123
  assert_equal(["foo/bar"], tree.search("foo"))
124
124
 
@@ -128,7 +128,7 @@ module RubyIndexer
128
128
  end
129
129
 
130
130
  def test_deleting_non_terminal_nodes
131
- tree = PrefixTree[String].new
131
+ tree = PrefixTree.new #: PrefixTree[String]
132
132
  tree.insert("abc", "value1")
133
133
  tree.insert("abcdef", "value2")
134
134
 
@@ -138,7 +138,7 @@ module RubyIndexer
138
138
  end
139
139
 
140
140
  def test_overriding_values
141
- tree = PrefixTree[Integer].new
141
+ tree = PrefixTree.new #: PrefixTree[Integer]
142
142
 
143
143
  tree.insert("foo/bar", 123)
144
144
  assert_equal([123], tree.search("foo/bar"))
@@ -60,7 +60,7 @@ module RubyIndexer
60
60
  entry = entries.find { |entry| entry.owner&.name == "Array" } #: as Entry::Method
61
61
  assert_match(%r{/gems/rbs-.*/core/array.rbs}, entry.file_path)
62
62
  assert_equal("array.rbs", entry.file_name)
63
- assert_equal(Entry::Visibility::PUBLIC, entry.visibility)
63
+ assert_equal(:public, entry.visibility)
64
64
 
65
65
  # Using fixed positions would be fragile, so let's just check some basics.
66
66
  assert_operator(entry.location.start_line, :>, 0)
@@ -373,8 +373,9 @@ module RubyIndexer
373
373
  pathname = Pathname.new("/file.rbs")
374
374
  indexer.process_signature(pathname, declarations)
375
375
  entry = index[method_name] #: as !nil
376
- .first
377
- T.cast(entry, Entry::Method).signatures
376
+ .first #: as Entry::Method
377
+
378
+ entry.signatures
378
379
  end
379
380
  end
380
381
  end
@@ -11,6 +11,13 @@ module RubyIndexer
11
11
  @default_indexed_entries = @index.instance_variable_get(:@entries).dup
12
12
  end
13
13
 
14
+ def teardown
15
+ entries = @index.instance_variable_get(:@entries).values.flatten
16
+ entries.each do |entry|
17
+ assert_includes([:public, :private, :protected], entry.visibility)
18
+ end
19
+ end
20
+
14
21
  private
15
22
 
16
23
  def index(source, uri: URI::Generic.from_path(path: "/fake/path/foo.rb"))
@@ -31,7 +38,6 @@ module RubyIndexer
31
38
  ":#{location.end_line - 1}-#{location.end_column}"
32
39
 
33
40
  assert_equal(expected_location, location_string)
34
-
35
41
  assert_equal(visibility, entry.visibility) if visibility
36
42
  end
37
43
 
@@ -10,7 +10,8 @@ module RubyLsp
10
10
  :supports_request_delegation,
11
11
  :window_show_message_supports_extra_properties,
12
12
  :supports_progress,
13
- :supports_diagnostic_refresh
13
+ :supports_diagnostic_refresh,
14
+ :supports_code_lens_refresh
14
15
 
15
16
  #: -> void
16
17
  def initialize
@@ -34,6 +35,9 @@ module RubyLsp
34
35
 
35
36
  # The editor supports server initiated refresh for diagnostics
36
37
  @supports_diagnostic_refresh = false #: bool
38
+
39
+ # The editor supports server initiated refresh for code lenses
40
+ @supports_code_lens_refresh = false #: bool
37
41
  end
38
42
 
39
43
  #: (Hash[Symbol, untyped] capabilities) -> void
@@ -61,6 +65,7 @@ module RubyLsp
61
65
  @supports_progress = progress if progress
62
66
 
63
67
  @supports_diagnostic_refresh = workspace_capabilities.dig(:diagnostics, :refreshSupport) || false
68
+ @supports_code_lens_refresh = workspace_capabilities.dig(:codeLens, :refreshSupport) || false
64
69
  end
65
70
 
66
71
  #: -> bool
@@ -2,21 +2,12 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RubyLsp
5
+ #: [ParseResultType]
5
6
  class Document
6
- class LanguageId < T::Enum
7
- enums do
8
- Ruby = new("ruby")
9
- ERB = new("erb")
10
- RBS = new("rbs")
11
- end
12
- end
13
-
14
7
  extend T::Sig
15
8
  extend T::Helpers
16
- extend T::Generic
17
9
 
18
10
  class LocationNotFoundError < StandardError; end
19
- ParseResultType = type_member
20
11
 
21
12
  # This maximum number of characters for providing expensive features, like semantic highlighting and diagnostics.
22
13
  # This is the same number used by the TypeScript extension in VS Code
@@ -71,7 +62,7 @@ module RubyLsp
71
62
  self.class == other.class && uri == other.uri && @source == other.source
72
63
  end
73
64
 
74
- sig { abstract.returns(LanguageId) }
65
+ sig { abstract.returns(Symbol) }
75
66
  def language_id; end
76
67
 
77
68
  #: [T] (String request_name) { (Document[ParseResultType] document) -> T } -> T
@@ -94,6 +85,11 @@ module RubyLsp
94
85
  @cache[request_name]
95
86
  end
96
87
 
88
+ #: (String request_name) -> void
89
+ def clear_cache(request_name)
90
+ @cache[request_name] = EMPTY_CACHE
91
+ end
92
+
97
93
  #: (Array[Hash[Symbol, untyped]] edits, version: Integer) -> void
98
94
  def push_edits(edits, version:)
99
95
  edits.each do |edit|
@@ -2,11 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RubyLsp
5
+ #: [ParseResultType = Prism::ParseResult]
5
6
  class ERBDocument < Document
6
- extend T::Generic
7
-
8
- ParseResultType = type_member { { fixed: Prism::ParseResult } }
9
-
10
7
  #: String
11
8
  attr_reader :host_language_source
12
9
 
@@ -46,9 +43,9 @@ module RubyLsp
46
43
  end
47
44
 
48
45
  # @override
49
- #: -> LanguageId
46
+ #: -> Symbol
50
47
  def language_id
51
- LanguageId::ERB
48
+ :erb
52
49
  end
53
50
 
54
51
  #: (Hash[Symbol, untyped] position, ?node_types: Array[singleton(Prism::Node)]) -> NodeContext
@@ -14,7 +14,12 @@ Bundler.ui.level = :silent
14
14
 
15
15
  require "json"
16
16
  require "uri"
17
- require "cgi"
17
+ require "cgi/escape"
18
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.5")
19
+ # Just requiring `cgi/escape` leaves CGI.unescape broken on older rubies
20
+ # Some background on why this is necessary: https://bugs.ruby-lang.org/issues/21258
21
+ require "cgi/util"
22
+ end
18
23
  require "set"
19
24
  require "strscan"
20
25
  require "prism"
@@ -50,7 +50,7 @@ module RubyLsp
50
50
  "__LINE__",
51
51
  ].freeze
52
52
 
53
- #: (ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem] response_builder, GlobalState global_state, NodeContext node_context, RubyDocument::SorbetLevel sorbet_level, Prism::Dispatcher dispatcher, URI::Generic uri, String? trigger_character) -> void
53
+ #: (ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem] response_builder, GlobalState global_state, NodeContext node_context, SorbetLevel sorbet_level, Prism::Dispatcher dispatcher, URI::Generic uri, String? trigger_character) -> void
54
54
  def initialize( # rubocop:disable Metrics/ParameterLists
55
55
  response_builder,
56
56
  global_state,
@@ -100,7 +100,7 @@ module RubyLsp
100
100
  def on_constant_read_node_enter(node)
101
101
  # The only scenario where Sorbet doesn't provide constant completion is on ignored files. Even if the file has
102
102
  # no sigil, Sorbet will still provide completion for constants
103
- return if @sorbet_level != RubyDocument::SorbetLevel::Ignore
103
+ return unless @sorbet_level.ignore?
104
104
 
105
105
  name = RubyIndexer::Index.constant_name(node)
106
106
  return if name.nil?
@@ -125,7 +125,7 @@ module RubyLsp
125
125
  def on_constant_path_node_enter(node)
126
126
  # The only scenario where Sorbet doesn't provide constant completion is on ignored files. Even if the file has
127
127
  # no sigil, Sorbet will still provide completion for constants
128
- return if @sorbet_level != RubyDocument::SorbetLevel::Ignore
128
+ return unless @sorbet_level.ignore?
129
129
 
130
130
  name = begin
131
131
  node.full_name
@@ -143,7 +143,7 @@ module RubyLsp
143
143
  def on_call_node_enter(node)
144
144
  # The only scenario where Sorbet doesn't provide constant completion is on ignored files. Even if the file has
145
145
  # no sigil, Sorbet will still provide completion for constants
146
- if @sorbet_level == RubyDocument::SorbetLevel::Ignore
146
+ if @sorbet_level.ignore?
147
147
  receiver = node.receiver
148
148
 
149
149
  # When writing `Foo::`, the AST assigns a method call node (because you can use that syntax to invoke
@@ -390,7 +390,7 @@ module RubyLsp
390
390
  def handle_instance_variable_completion(name, location)
391
391
  # Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
392
392
  # to provide all features for them
393
- return if @sorbet_level == RubyDocument::SorbetLevel::Strict
393
+ return if @sorbet_level.strict?
394
394
 
395
395
  type = @type_inferrer.infer_receiver_type(@node_context)
396
396
  return unless type
@@ -475,13 +475,13 @@ module RubyLsp
475
475
  def complete_methods(node, name)
476
476
  # If the node has a receiver, then we don't need to provide local nor keyword completions. Sorbet can provide
477
477
  # local and keyword completion for any file with a Sorbet level of true or higher
478
- if !sorbet_level_true_or_higher?(@sorbet_level) && !node.receiver
478
+ if !@sorbet_level.true_or_higher? && !node.receiver
479
479
  add_local_completions(node, name)
480
480
  add_keyword_completions(node, name)
481
481
  end
482
482
 
483
483
  # Sorbet can provide completion for methods invoked on self on typed true or higher files
484
- return if sorbet_level_true_or_higher?(@sorbet_level) && self_receiver?(node)
484
+ return if @sorbet_level.true_or_higher? && self_receiver?(node)
485
485
 
486
486
  type = @type_inferrer.infer_receiver_type(@node_context)
487
487
  return unless type
@@ -512,7 +512,7 @@ module RubyLsp
512
512
  external_references = @node_context.fully_qualified_name != type.name
513
513
 
514
514
  @index.method_completion_candidates(method_name, type.name).each do |entry|
515
- next if entry.visibility != RubyIndexer::Entry::Visibility::PUBLIC && external_references
515
+ next if entry.visibility != :public && external_references
516
516
 
517
517
  entry_name = entry.name
518
518
  owner_name = entry.owner&.name
@@ -8,7 +8,7 @@ module RubyLsp
8
8
 
9
9
  MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER = 10
10
10
 
11
- #: (ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)] response_builder, GlobalState global_state, Document::LanguageId language_id, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher, RubyDocument::SorbetLevel sorbet_level) -> void
11
+ #: (ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)] response_builder, GlobalState global_state, Symbol language_id, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
12
12
  def initialize(response_builder, global_state, language_id, uri, node_context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
13
13
  @response_builder = response_builder
14
14
  @global_state = global_state
@@ -53,7 +53,7 @@ module RubyLsp
53
53
  #: (Prism::CallNode node) -> void
54
54
  def on_call_node_enter(node)
55
55
  # Sorbet can handle go to definition for methods invoked on self on typed true or higher
56
- return if sorbet_level_true_or_higher?(@sorbet_level) && self_receiver?(node)
56
+ return if @sorbet_level.true_or_higher? && self_receiver?(node)
57
57
 
58
58
  message = node.message
59
59
  return unless message
@@ -62,7 +62,7 @@ module RubyLsp
62
62
 
63
63
  # Until we can properly infer the receiver type in erb files (maybe with ruby-lsp-rails),
64
64
  # treating method calls' type as `nil` will allow users to get some completion support first
65
- if @language_id == Document::LanguageId::ERB && inferrer_receiver_type&.name == "Object"
65
+ if @language_id == :erb && inferrer_receiver_type&.name == "Object"
66
66
  inferrer_receiver_type = nil
67
67
  end
68
68
 
@@ -223,7 +223,7 @@ module RubyLsp
223
223
  #: -> void
224
224
  def handle_super_node_definition
225
225
  # Sorbet can handle super hover on typed true or higher
226
- return if sorbet_level_true_or_higher?(@sorbet_level)
226
+ return if @sorbet_level.true_or_higher?
227
227
 
228
228
  surrounding_method = @node_context.surrounding_method
229
229
  return unless surrounding_method
@@ -276,7 +276,7 @@ module RubyLsp
276
276
  def handle_instance_variable_definition(name)
277
277
  # Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
278
278
  # to provide all features for them
279
- return if @sorbet_level == RubyDocument::SorbetLevel::Strict
279
+ return if @sorbet_level.strict?
280
280
 
281
281
  type = @type_inferrer.infer_receiver_type(@node_context)
282
282
  return unless type
@@ -317,7 +317,7 @@ module RubyLsp
317
317
  methods.each do |target_method|
318
318
  uri = target_method.uri
319
319
  full_path = uri.full_path
320
- next if sorbet_level_true_or_higher?(@sorbet_level) && (!full_path || not_in_dependencies?(full_path))
320
+ next if @sorbet_level.true_or_higher? && (!full_path || not_in_dependencies?(full_path))
321
321
 
322
322
  @response_builder << Interface::LocationLink.new(
323
323
  target_uri: uri.to_s,
@@ -392,7 +392,7 @@ module RubyLsp
392
392
  uri = entry.uri
393
393
  full_path = uri.full_path
394
394
 
395
- if @sorbet_level != RubyDocument::SorbetLevel::Ignore && (!full_path || not_in_dependencies?(full_path))
395
+ if !@sorbet_level.ignore? && (!full_path || not_in_dependencies?(full_path))
396
396
  next
397
397
  end
398
398
 
@@ -105,16 +105,13 @@ module RubyLsp
105
105
  match = comment.location.slice.match(%r{source://.*#\d+$})
106
106
  return unless match
107
107
 
108
- uri = T.cast(
109
- begin
110
- URI(
111
- match[0], #: as !nil
112
- )
113
- rescue URI::Error
114
- nil
115
- end,
116
- T.nilable(URI::Source),
117
- )
108
+ uri = begin
109
+ URI(
110
+ match[0], #: as !nil
111
+ )
112
+ rescue URI::Error
113
+ nil
114
+ end #: as URI::Source?
118
115
  return unless uri
119
116
 
120
117
  gem_version = resolve_version(uri)
@@ -42,7 +42,7 @@ module RubyLsp
42
42
  "https://gitlab.com",
43
43
  ].freeze #: Array[String]
44
44
 
45
- #: (ResponseBuilders::Hover response_builder, GlobalState global_state, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher, RubyDocument::SorbetLevel sorbet_level) -> void
45
+ #: (ResponseBuilders::Hover response_builder, GlobalState global_state, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
46
46
  def initialize(response_builder, global_state, uri, node_context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
47
47
  @response_builder = response_builder
48
48
  @global_state = global_state
@@ -86,6 +86,14 @@ module RubyLsp
86
86
 
87
87
  #: (Prism::StringNode node) -> void
88
88
  def on_string_node_enter(node)
89
+ if @path && File.basename(@path) == GEMFILE_NAME
90
+ call_node = @node_context.call_node
91
+ if call_node && call_node.name == :gem && call_node.arguments&.arguments&.first == node
92
+ generate_gem_hover(call_node)
93
+ return
94
+ end
95
+ end
96
+
89
97
  generate_heredoc_hover(node)
90
98
  end
91
99
 
@@ -96,7 +104,7 @@ module RubyLsp
96
104
 
97
105
  #: (Prism::ConstantReadNode node) -> void
98
106
  def on_constant_read_node_enter(node)
99
- return if @sorbet_level != RubyDocument::SorbetLevel::Ignore
107
+ return unless @sorbet_level.ignore?
100
108
 
101
109
  name = RubyIndexer::Index.constant_name(node)
102
110
  return if name.nil?
@@ -106,14 +114,14 @@ module RubyLsp
106
114
 
107
115
  #: (Prism::ConstantWriteNode node) -> void
108
116
  def on_constant_write_node_enter(node)
109
- return if @sorbet_level != RubyDocument::SorbetLevel::Ignore
117
+ return unless @sorbet_level.ignore?
110
118
 
111
119
  generate_hover(node.name.to_s, node.name_loc)
112
120
  end
113
121
 
114
122
  #: (Prism::ConstantPathNode node) -> void
115
123
  def on_constant_path_node_enter(node)
116
- return if @sorbet_level != RubyDocument::SorbetLevel::Ignore
124
+ return unless @sorbet_level.ignore?
117
125
 
118
126
  name = RubyIndexer::Index.constant_name(node)
119
127
  return if name.nil?
@@ -123,12 +131,7 @@ module RubyLsp
123
131
 
124
132
  #: (Prism::CallNode node) -> void
125
133
  def on_call_node_enter(node)
126
- if @path && File.basename(@path) == GEMFILE_NAME && node.name == :gem
127
- generate_gem_hover(node)
128
- return
129
- end
130
-
131
- return if sorbet_level_true_or_higher?(@sorbet_level) && self_receiver?(node)
134
+ return if @sorbet_level.true_or_higher? && self_receiver?(node)
132
135
 
133
136
  message = node.message
134
137
  return unless message
@@ -283,7 +286,7 @@ module RubyLsp
283
286
  #: -> void
284
287
  def handle_super_node_hover
285
288
  # Sorbet can handle super hover on typed true or higher
286
- return if sorbet_level_true_or_higher?(@sorbet_level)
289
+ return if @sorbet_level.true_or_higher?
287
290
 
288
291
  surrounding_method = @node_context.surrounding_method
289
292
  return unless surrounding_method
@@ -318,7 +321,7 @@ module RubyLsp
318
321
  def handle_instance_variable_hover(name)
319
322
  # Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
320
323
  # to provide all features for them
321
- return if @sorbet_level == RubyDocument::SorbetLevel::Strict
324
+ return if @sorbet_level.strict?
322
325
 
323
326
  type = @type_inferrer.infer_receiver_type(@node_context)
324
327
  return unless type
@@ -366,9 +369,10 @@ module RubyLsp
366
369
  # We should only show hover for private constants if the constant is defined in the same namespace as the
367
370
  # reference
368
371
  first_entry = entries.first #: as !nil
369
- return if first_entry.private? && first_entry.name != "#{@node_context.fully_qualified_name}::#{name}"
372
+ full_name = first_entry.name
373
+ return if first_entry.private? && full_name != "#{@node_context.fully_qualified_name}::#{name}"
370
374
 
371
- categorized_markdown_from_index_entries(name, entries).each do |category, content|
375
+ categorized_markdown_from_index_entries(full_name, entries).each do |category, content|
372
376
  @response_builder.push(content, category: category)
373
377
  end
374
378
  end
@@ -6,7 +6,7 @@ module RubyLsp
6
6
  class SignatureHelp
7
7
  include Requests::Support::Common
8
8
 
9
- #: (ResponseBuilders::SignatureHelp response_builder, GlobalState global_state, NodeContext node_context, Prism::Dispatcher dispatcher, RubyDocument::SorbetLevel sorbet_level) -> void
9
+ #: (ResponseBuilders::SignatureHelp response_builder, GlobalState global_state, NodeContext node_context, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
10
10
  def initialize(response_builder, global_state, node_context, dispatcher, sorbet_level)
11
11
  @sorbet_level = sorbet_level
12
12
  @response_builder = response_builder
@@ -19,7 +19,7 @@ module RubyLsp
19
19
 
20
20
  #: (Prism::CallNode node) -> void
21
21
  def on_call_node_enter(node)
22
- return if sorbet_level_true_or_higher?(@sorbet_level)
22
+ return if @sorbet_level.true_or_higher?
23
23
 
24
24
  message = node.message
25
25
  return unless message
@@ -4,9 +4,7 @@
4
4
  module RubyLsp
5
5
  module Listeners
6
6
  class SpecStyle < TestDiscovery
7
- extend T::Sig
8
-
9
- #: (response_builder: ResponseBuilders::TestCollection, global_state: GlobalState, dispatcher: Prism::Dispatcher, uri: URI::Generic) -> void
7
+ #: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
10
8
  def initialize(response_builder, global_state, dispatcher, uri)
11
9
  super
12
10
 
@@ -22,7 +20,7 @@ module RubyLsp
22
20
  )
23
21
  end
24
22
 
25
- #: (node: Prism::ClassNode) -> void
23
+ #: (Prism::ClassNode) -> void
26
24
  def on_class_node_enter(node)
27
25
  with_test_ancestor_tracking(node) do |_, ancestors|
28
26
  is_spec = ancestors.include?("Minitest::Spec")
@@ -30,14 +28,14 @@ module RubyLsp
30
28
  end
31
29
  end
32
30
 
33
- #: (node: Prism::ClassNode) -> void
31
+ #: (Prism::ClassNode) -> void
34
32
  def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
35
33
  super
36
34
 
37
35
  @spec_class_stack.pop
38
36
  end
39
37
 
40
- #: (node: Prism::CallNode) -> void
38
+ #: (Prism::CallNode) -> void
41
39
  def on_call_node_enter(node)
42
40
  case node.name
43
41
  when :describe
@@ -47,7 +45,7 @@ module RubyLsp
47
45
  end
48
46
  end
49
47
 
50
- #: (node: Prism::CallNode) -> void
48
+ #: (Prism::CallNode) -> void
51
49
  def on_call_node_leave(node)
52
50
  return unless node.name == :describe && !node.receiver
53
51
 
@@ -56,7 +54,7 @@ module RubyLsp
56
54
 
57
55
  private
58
56
 
59
- #: (node: Prism::CallNode) -> void
57
+ #: (Prism::CallNode) -> void
60
58
  def handle_describe(node)
61
59
  return if node.block.nil?
62
60
 
@@ -74,6 +72,7 @@ module RubyLsp
74
72
  framework: :minitest,
75
73
  )
76
74
  @response_builder.add(test_item)
75
+ @response_builder.add_code_lens(test_item)
77
76
  else
78
77
  add_to_parent_test_group(description, node)
79
78
  end
@@ -81,7 +80,7 @@ module RubyLsp
81
80
  @describe_block_nesting << description
82
81
  end
83
82
 
84
- #: (node: Prism::CallNode) -> void
83
+ #: (Prism::CallNode) -> void
85
84
  def handle_example(node)
86
85
  return unless in_spec_context?
87
86
 
@@ -93,7 +92,7 @@ module RubyLsp
93
92
  add_to_parent_test_group(description, node)
94
93
  end
95
94
 
96
- #: (description: String, node: Prism::CallNode) -> void
95
+ #: (String, Prism::CallNode) -> void
97
96
  def add_to_parent_test_group(description, node)
98
97
  parent_test_group = find_parent_test_group
99
98
  return unless parent_test_group
@@ -106,6 +105,7 @@ module RubyLsp
106
105
  framework: :minitest,
107
106
  )
108
107
  parent_test_group.add(test_item)
108
+ @response_builder.add_code_lens(test_item)
109
109
  end
110
110
 
111
111
  #: -> Requests::Support::TestItem?
@@ -129,7 +129,7 @@ module RubyLsp
129
129
  test_group
130
130
  end
131
131
 
132
- #: (node: Prism::CallNode) -> String?
132
+ #: (Prism::CallNode) -> String?
133
133
  def extract_description(node)
134
134
  first_argument = node.arguments&.arguments&.first
135
135
  return unless first_argument
@@ -71,7 +71,7 @@ module RubyLsp
71
71
  slice.gsub(/((?<=::)|^)[a-z]\w*/, DYNAMIC_REFERENCE_MARKER)
72
72
  end
73
73
 
74
- #: (Prism::ClassNode node, ^(String name, Array[String] ancestors) -> void block) -> void
74
+ #: (Prism::ClassNode node) { (String name, Array[String] ancestors) -> void } -> void
75
75
  def with_test_ancestor_tracking(node, &block)
76
76
  @visibility_stack << :public
77
77
  name = constant_name(node.constant_path)
@@ -143,7 +143,7 @@ module RubyLsp
143
143
  "ruby"
144
144
  end #: String
145
145
 
146
- #: (ResponseBuilders::TestCollection response_builder, GlobalState global_state, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
146
+ #: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
147
147
  def initialize(response_builder, global_state, dispatcher, uri)
148
148
  super
149
149
 
@@ -165,13 +165,16 @@ module RubyLsp
165
165
  @framework = :test_unit if ancestors.include?("Test::Unit::TestCase")
166
166
 
167
167
  if @framework == :test_unit || non_declarative_minitest?(ancestors, name)
168
- @response_builder.add(Requests::Support::TestItem.new(
168
+ test_item = Requests::Support::TestItem.new(
169
169
  name,
170
170
  name,
171
171
  @uri,
172
172
  range_from_node(node),
173
173
  framework: @framework,
174
- ))
174
+ )
175
+
176
+ @response_builder.add(test_item)
177
+ @response_builder.add_code_lens(test_item)
175
178
  end
176
179
  end
177
180
  end
@@ -191,13 +194,15 @@ module RubyLsp
191
194
  test_item = @response_builder[current_group_name]
192
195
  return unless test_item
193
196
 
194
- test_item.add(Requests::Support::TestItem.new(
197
+ example_item = Requests::Support::TestItem.new(
195
198
  "#{current_group_name}##{name}",
196
199
  name,
197
200
  @uri,
198
201
  range_from_node(node),
199
202
  framework: @framework,
200
- ))
203
+ )
204
+ test_item.add(example_item)
205
+ @response_builder.add_code_lens(example_item)
201
206
  end
202
207
 
203
208
  #: (Prism::CallNode node) -> void
@@ -2,11 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RubyLsp
5
+ #: [ParseResultType = Array[RBS::AST::Declarations::Base]]
5
6
  class RBSDocument < Document
6
- extend T::Generic
7
-
8
- ParseResultType = type_member { { fixed: T::Array[RBS::AST::Declarations::Base] } }
9
-
10
7
  #: (source: String, version: Integer, uri: URI::Generic, global_state: GlobalState) -> void
11
8
  def initialize(source:, version:, uri:, global_state:)
12
9
  @syntax_error = false #: bool
@@ -36,9 +33,9 @@ module RubyLsp
36
33
  end
37
34
 
38
35
  # @override
39
- #: -> LanguageId
36
+ #: -> Symbol
40
37
  def language_id
41
- LanguageId::RBS
38
+ :rbs
42
39
  end
43
40
  end
44
41
  end