ruby-lsp 0.27.0.beta3 → 0.27.0.beta4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3bc7e833f5619665b205e3346555594540a1150cf4a66514ed1fe6900fc8d0e
4
- data.tar.gz: c7cf77eed53ba29b680221474abffd5356f723dd4bb2bd586b8158c5b3794dba
3
+ metadata.gz: de1859a4f73bdc2007364195d5e2c8aae9f999455a7523ad290263efb0edab30
4
+ data.tar.gz: 63e9388bc11ef954ed197db00c166a900e0f422c346c48af7bc485ab51a630c8
5
5
  SHA512:
6
- metadata.gz: 3b265bbdf75bd46df7acc181a9d77aced50b403b5efa21dc7c22eeda92b5b0319b5d1ac21a279d2c436c5126026c3f643760974c57d26bbbcc32ca69fba5b9bc
7
- data.tar.gz: ee7b8e028a2a38e301ec14c33c2a7c6f292e89f1c850a935b26dce19bc4a10f15915a07c2dea8f8e32839acd3018f7613e698a06d6e908b3334d38cccddd47de
6
+ metadata.gz: cade33d50651fb915408b36b0537cb201c9b61ee0151e2ae6a8a1bee3099054af2a184e93b7790a0d283860159326f31d391c71bda798f00229262c4c58123f2
7
+ data.tar.gz: 01f24b527c33cc3d741fe682d79b70a0881760a9dc6d599101356563cbfce30ce0e719619312f530f42256b6ecb82ac2a40c93d6cde0ad97ef5e2a8087922d3d
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.27.0.beta3
1
+ 0.27.0.beta4
@@ -74,6 +74,8 @@ module RubyLsp
74
74
  )
75
75
  end
76
76
  end
77
+ rescue URI::Error
78
+ # A client can send a document URI with a scheme Ruby's URI parser rejects, so we don't want to fail
77
79
  rescue Store::NonExistingDocumentError
78
80
  # If we receive a request for a file that no longer exists, we don't want to fail
79
81
  end
@@ -256,7 +256,7 @@ module RubyLsp
256
256
  #
257
257
  #: () -> Array[(Rubydex::Declaration | Rubydex::Keyword)]
258
258
  def expression_candidates
259
- @graph.complete_expression(@node_context.nesting, self_receiver: nil)
259
+ @graph.complete_expression(@node_context.nesting, self_receiver: @type_inferrer.self_receiver_name(@node_context))
260
260
  end
261
261
 
262
262
  #: (Interface::Range range, String prefix) -> void
@@ -322,14 +322,14 @@ module RubyLsp
322
322
  end
323
323
 
324
324
  candidates = if namespace_prefix.empty?
325
- @graph.complete_expression([], self_receiver: nil)
325
+ @graph.complete_expression([], self_receiver: @type_inferrer.self_receiver_name(@node_context))
326
326
  else
327
327
  # Rubydex's resolver handles a leading `::` on `namespace_prefix` by resolving from the top-level scope, so
328
328
  # we don't need to special-case top-level references here
329
329
  resolved = @graph.resolve_constant(namespace_prefix, @node_context.nesting)
330
330
  return unless resolved
331
331
 
332
- @graph.complete_namespace_access(resolved.name, self_receiver: nil)
332
+ @graph.complete_namespace_access(resolved.name, self_receiver: @type_inferrer.self_receiver_name(@node_context))
333
333
  end
334
334
 
335
335
  candidates.each do |candidate|
@@ -378,7 +378,7 @@ module RubyLsp
378
378
 
379
379
  guessed_type = type.is_a?(TypeInferrer::GuessedType) && type.name
380
380
 
381
- @graph.complete_method_call(type.name, self_receiver: nil).each do |candidate|
381
+ @graph.complete_method_call(type.name, self_receiver: @type_inferrer.self_receiver_name(@node_context)).each do |candidate|
382
382
  if method_name
383
383
  display_name = candidate.unqualified_name.delete_suffix("()")
384
384
  next unless display_name.start_with?(method_name)
@@ -390,16 +390,13 @@ module RubyLsp
390
390
 
391
391
  # Variable completion (instance, class, and global). The variable kind is selected by the prefix the user typed:
392
392
  # `$…` only matches globals, `@@…` only class variables, and `@…` matches both instance and class variables (since
393
- # `@@foo`.start_with?("@") is true). Globals live at top-level, so they need an empty nesting; instance/class
394
- # variables resolve through the type_inferrer to handle singleton methods and class bodies, where the receiver is
395
- # the singleton class rather than the lexical nesting.
393
+ # `@@foo`.start_with?("@") is true). This uses the same query as expression completion: the lexical nesting drives
394
+ # constants and class variables, while the `self` type (which may differ from the nesting, e.g. inside
395
+ # `def self.foo` or `def Bar.baz`) drives instance variables.
396
396
  #
397
397
  #: (Interface::Range, String) -> void
398
398
  def complete_variable(range, prefix)
399
- type = @type_inferrer.infer_receiver_type(@node_context)
400
- nesting = type ? type.name.split("::") : []
401
-
402
- @graph.complete_expression(nesting, self_receiver: nil).each do |candidate|
399
+ expression_candidates.each do |candidate|
403
400
  next unless candidate.is_a?(Rubydex::Declaration)
404
401
 
405
402
  variable_name = candidate.unqualified_name
@@ -120,6 +120,16 @@ module RubyLsp
120
120
  markdown_title = "```ruby\n#{title}\n```"
121
121
  file_links = []
122
122
  content = +""
123
+
124
+ # Include documentation for method alias targets
125
+ definitions = definitions.flat_map do |definition|
126
+ if definition.is_a?(Rubydex::MethodAliasDefinition) && (target = definition.target)
127
+ [definition, *target.definitions]
128
+ else
129
+ [definition]
130
+ end
131
+ end
132
+
123
133
  defs = max_entries ? definitions.take(max_entries) : definitions
124
134
  defs.each do |definition|
125
135
  # For Markdown links, we need 1 based display locations
@@ -371,6 +371,7 @@ module RubyLsp
371
371
  end
372
372
  end
373
373
 
374
+ load_rubydex_config
374
375
  perform_initial_indexing
375
376
  check_formatter_is_available
376
377
  update_server if @global_state.enabled_feature?(:launcher)
@@ -435,10 +436,15 @@ module RubyLsp
435
436
  if [:ruby, :rbs].include?(language_id)
436
437
  graph = @global_state.graph
437
438
 
438
- benchmark("index_source") do
439
- graph.index_source(text_document[:uri].to_s, document.source, language_id.to_s)
440
- end
439
+ begin_progress("incremental-indexing-progress", "Ruby LSP: indexing files")
440
+
441
+ progress("incremental-indexing-progress", message: "Indexing file...")
442
+ benchmark("index_source") { graph.index_source(text_document[:uri].to_s, document.source, language_id.to_s) }
443
+
444
+ progress("incremental-indexing-progress", message: "Resolving graph...")
441
445
  benchmark("incremental_resolve") { graph.resolve }
446
+
447
+ end_progress("incremental-indexing-progress")
442
448
  end
443
449
  end
444
450
 
@@ -1032,9 +1038,17 @@ module RubyLsp
1032
1038
  acc << path
1033
1039
  end
1034
1040
  end
1041
+
1042
+ begin_progress("incremental-indexing-progress", "Ruby LSP: indexing files")
1043
+
1044
+ progress("incremental-indexing-progress", message: "Indexing files...")
1035
1045
  benchmark("index_all") { graph.index_all(additions_and_changes) }
1046
+
1047
+ progress("incremental-indexing-progress", message: "Resolving graph...")
1036
1048
  benchmark("incremental_resolve") { graph.resolve }
1037
1049
 
1050
+ end_progress("incremental-indexing-progress")
1051
+
1038
1052
  changes.each do |change|
1039
1053
  # File change events include folders, but we're only interested in files
1040
1054
  uri = URI(change[:uri])
@@ -1209,8 +1223,8 @@ module RubyLsp
1209
1223
  end_progress("indexing-progress")
1210
1224
  end
1211
1225
 
1212
- #: (String id, String title, ?percentage: Integer) -> void
1213
- def begin_progress(id, title, percentage: 0)
1226
+ #: (String id, String title, ?percentage: Integer?, ?message: String?) -> void
1227
+ def begin_progress(id, title, percentage: nil, message: nil)
1214
1228
  return unless @global_state.client_capabilities.supports_progress
1215
1229
 
1216
1230
  send_message(Request.new(
@@ -1219,7 +1233,10 @@ module RubyLsp
1219
1233
  params: Interface::WorkDoneProgressCreateParams.new(token: id),
1220
1234
  ))
1221
1235
 
1222
- send_message(Notification.progress_begin(id, title, percentage: percentage, message: "#{percentage}% completed"))
1236
+ # Omitting the percentage tells the client to show indefinite progress. Only fabricate a "% completed" message
1237
+ # when a caller reports incremental percentages and didn't provide an explicit message
1238
+ message ||= "#{percentage}% completed" if percentage
1239
+ send_message(Notification.progress_begin(id, title, percentage: percentage, message: message))
1223
1240
  end
1224
1241
 
1225
1242
  #: (String, ?message: String?, ?percentage: Integer?) -> void
@@ -1443,5 +1460,15 @@ module RubyLsp
1443
1460
 
1444
1461
  result
1445
1462
  end
1463
+
1464
+ #: () -> void
1465
+ def load_rubydex_config
1466
+ @global_state.graph.load_config
1467
+ rescue Rubydex::ConfigError => e
1468
+ send_message(Notification.window_show_message(
1469
+ "Error loading rubydex config: #{e.message}",
1470
+ type: Constant::MessageType::ERROR,
1471
+ ))
1472
+ end
1446
1473
  end
1447
1474
  end
@@ -445,7 +445,7 @@ module RubyLsp
445
445
  requirement = Gem::Requirement.new(@bundler_version.to_s)
446
446
  return if Gem::Specification.any? { |s| s.name == "bundler" && requirement =~ s.version }
447
447
 
448
- Gem.install("bundler", @bundler_version.to_s)
448
+ Gem.install("bundler", @bundler_version.to_s, env_shebang: true)
449
449
  end
450
450
 
451
451
  #: -> bool
@@ -20,13 +20,67 @@ module RubyLsp
20
20
  when Prism::InstanceVariableReadNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableWriteNode,
21
21
  Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode, Prism::InstanceVariableTargetNode,
22
22
  Prism::SuperNode, Prism::ForwardingSuperNode, Prism::DefNode
23
- self_receiver_handling(node_context)
23
+ infer_self_type(node_context)
24
24
  when Prism::ClassVariableAndWriteNode, Prism::ClassVariableWriteNode, Prism::ClassVariableOperatorWriteNode,
25
25
  Prism::ClassVariableOrWriteNode, Prism::ClassVariableReadNode, Prism::ClassVariableTargetNode
26
26
  infer_receiver_for_class_variables(node_context)
27
27
  end
28
28
  end
29
29
 
30
+ # Infers the type of `self` in the given context. Unlike `infer_receiver_type`, this does not depend on the node
31
+ # being completed — it's derived purely from the lexical nesting and the surrounding method's receiver. This matters
32
+ # because methods and instance variables are attached to the type of `self`, which doesn't always match the lexical
33
+ # scope (e.g. inside `def self.foo` or a class/module body).
34
+ #
35
+ #: (NodeContext node_context) -> Type?
36
+ def infer_self_type(node_context)
37
+ nesting = node_context.nesting
38
+ # If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
39
+ # inherits from Object
40
+ return Type.new("Object") if nesting.empty?
41
+
42
+ surrounding_method = node_context.surrounding_method
43
+
44
+ if surrounding_method
45
+ receiver_name = surrounding_method.receiver
46
+
47
+ case receiver_name
48
+ when "self"
49
+ # `def self.foo` — self is the singleton of the enclosing class/module
50
+ return resolve_singleton_type_from_nesting(nesting)
51
+ when "none"
52
+ # Instance method — self is an instance of the enclosing class/module
53
+ return resolve_type_from_nesting(nesting)
54
+ when nil
55
+ # Dynamic receiver that we cannot handle
56
+ return
57
+ else
58
+ # Explicit constant receiver (e.g. `def Bar.baz`) — self is that constant's singleton class
59
+ resolved = resolve_receiver_singleton_type(receiver_name, nesting)
60
+ return resolved if resolved
61
+
62
+ return resolve_type_from_nesting(nesting)
63
+ end
64
+ end
65
+
66
+ # If we're not inside a method, then we're inside the body of a class or module, which is a singleton
67
+ # context. Resolve through the graph to get the correct fully qualified name
68
+ resolve_singleton_type_from_nesting(nesting)
69
+ end
70
+
71
+ # The type of `self`, which may or may not match the current lexical scope. For example, if we have `def Bar.foo` or
72
+ # if something else mutates the type
73
+ #
74
+ #: (NodeContext) -> String?
75
+ def self_receiver_name(node_context)
76
+ return if node_context.nesting.empty?
77
+
78
+ name = infer_self_type(node_context)&.name
79
+ return unless name
80
+
81
+ name if @graph[name]
82
+ end
83
+
30
84
  private
31
85
 
32
86
  #: (Prism::CallNode node, NodeContext node_context) -> Type?
@@ -49,7 +103,7 @@ module RubyLsp
49
103
 
50
104
  case receiver
51
105
  when Prism::SelfNode, nil
52
- self_receiver_handling(node_context)
106
+ infer_self_type(node_context)
53
107
  when Prism::StringNode
54
108
  Type.new("String")
55
109
  when Prism::SymbolNode
@@ -129,42 +183,6 @@ module RubyLsp
129
183
  GuessedType.new(declaration.name)
130
184
  end
131
185
 
132
- #: (NodeContext node_context) -> Type?
133
- def self_receiver_handling(node_context)
134
- nesting = node_context.nesting
135
- # If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
136
- # inherits from Object
137
- return Type.new("Object") if nesting.empty?
138
-
139
- surrounding_method = node_context.surrounding_method
140
-
141
- if surrounding_method
142
- receiver_name = surrounding_method.receiver
143
-
144
- case receiver_name
145
- when "self"
146
- # `def self.foo` — self is the singleton of the enclosing class/module
147
- return resolve_singleton_type_from_nesting(nesting)
148
- when "none"
149
- # Instance method — self is an instance of the enclosing class/module
150
- return resolve_type_from_nesting(nesting)
151
- when nil
152
- # Dynamic receiver that we cannot handle
153
- return
154
- else
155
- # Explicit constant receiver (e.g. `def Bar.baz`) — self is that constant's singleton class
156
- resolved = resolve_receiver_singleton_type(receiver_name, nesting)
157
- return resolved if resolved
158
-
159
- return resolve_type_from_nesting(nesting)
160
- end
161
- end
162
-
163
- # If we're not inside a method, then we're inside the body of a class or module, which is a singleton
164
- # context. Resolve through the graph to get the correct fully qualified name
165
- resolve_singleton_type_from_nesting(nesting)
166
- end
167
-
168
186
  # Resolves the fully qualified name of the innermost constant from the nesting and returns it as a type.
169
187
  # For instance methods, the nesting won't have singleton markers, so the result is an instance type.
170
188
  # For `def self.` methods, the nesting includes a singleton marker, which is preserved in the result.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0.beta3
4
+ version: 0.27.0.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
@@ -67,9 +67,9 @@ dependencies:
67
67
  name: rubydex
68
68
  requirement: !ruby/object:Gem::Requirement
69
69
  requirements:
70
- - - "~>"
70
+ - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: 0.2.0
72
+ version: 0.2.7
73
73
  - - "<"
74
74
  - !ruby/object:Gem::Version
75
75
  version: 0.3.0
@@ -77,9 +77,9 @@ dependencies:
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 0.2.0
82
+ version: 0.2.7
83
83
  - - "<"
84
84
  - !ruby/object:Gem::Version
85
85
  version: 0.3.0
@@ -213,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
213
213
  - !ruby/object:Gem::Version
214
214
  version: '0'
215
215
  requirements: []
216
- rubygems_version: 4.0.3
216
+ rubygems_version: 4.0.10
217
217
  specification_version: 4
218
218
  summary: An opinionated language server for Ruby
219
219
  test_files: []