solargraph 0.59.0 → 0.59.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/plugins.yml +1 -1
- data/.github/workflows/typecheck.yml +1 -1
- data/CHANGELOG.md +5 -0
- data/lib/solargraph/complex_type/unique_type.rb +2 -2
- data/lib/solargraph/complex_type.rb +1 -1
- data/lib/solargraph/language_server/host.rb +6 -7
- data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -4
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
- data/lib/solargraph/pin/base.rb +3 -3
- data/lib/solargraph/pin/method.rb +2 -0
- data/lib/solargraph/pin/parameter.rb +3 -1
- data/lib/solargraph/pin/search.rb +5 -5
- data/lib/solargraph/rbs_map/conversions.rb +1 -1
- data/lib/solargraph/source/cursor.rb +11 -2
- data/lib/solargraph/source_map/clip.rb +6 -1
- data/lib/solargraph/type_checker.rb +4 -4
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
- data/lib/solargraph.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9346852d9ba48c677a63c6ac2dd3bf6b7cb536309f28569c256bc8654c19c865
|
|
4
|
+
data.tar.gz: 9fd017aedc2b705156999d93f5bc8f5f6b99cd7cc3716565ef42ab26936336eb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5b8d3c627dec8757b70444e444a66dd024818f3e62e7c8d9ea57a638182de64524cca532c7b8ae9c5944d373cfdb2e0f3a1ede46e1e8b3e4e728d02b2f9db0e0
|
|
7
|
+
data.tar.gz: 41321b8ad277092a434241bc099488c99c721fb7bf593cb3c41f703329ba2d90e2416b5f407ed858db69776d02eb9bb3c93025d094de6f4413fd368f933a7398
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## 0.59.1 - May 18, 2026
|
|
2
|
+
- Fix signatureHelp bug (#1185)
|
|
3
|
+
- Linting fixes for Ruby 3.1 (#1193)
|
|
4
|
+
- Parameters shadow local variables with same name (#1192)
|
|
5
|
+
|
|
1
6
|
## 0.59.0 - May 13, 2026
|
|
2
7
|
- Ensure pathname is required for rbs in shell caching processes (#1183)
|
|
3
8
|
- Pre-release branch 2026-01-12 (#1152)
|
|
@@ -166,7 +166,7 @@ module Solargraph
|
|
|
166
166
|
# @param name [Symbol]
|
|
167
167
|
# @param include_private [Boolean]
|
|
168
168
|
def respond_to_missing? name, include_private = false
|
|
169
|
-
TypeMethods.
|
|
169
|
+
TypeMethods.public_method_defined?(name) || super
|
|
170
170
|
end
|
|
171
171
|
|
|
172
172
|
def to_s
|
|
@@ -648,15 +648,14 @@ module Solargraph
|
|
|
648
648
|
# @param text [String]
|
|
649
649
|
# @param type [Integer] A MessageType constant
|
|
650
650
|
# @param actions [Array<String>] Response options for the client
|
|
651
|
-
# @param block [Proc] The block that processes the response
|
|
652
651
|
# @yieldparam [String] The action received from the client
|
|
653
652
|
# @return [void]
|
|
654
|
-
def show_message_request
|
|
655
|
-
send_request
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
653
|
+
def show_message_request(text, type, actions, &)
|
|
654
|
+
send_request('window/showMessageRequest', {
|
|
655
|
+
type: type,
|
|
656
|
+
message: text,
|
|
657
|
+
actions: actions
|
|
658
|
+
}, &)
|
|
660
659
|
end
|
|
661
660
|
|
|
662
661
|
# Get a list of IDs for server requests that are waiting for responses
|
|
@@ -4,6 +4,7 @@ require 'parser'
|
|
|
4
4
|
require 'ast'
|
|
5
5
|
|
|
6
6
|
# https://github.com/whitequark/parser
|
|
7
|
+
# rubocop:disable Metrics/ModuleLength
|
|
7
8
|
module Solargraph
|
|
8
9
|
module Parser
|
|
9
10
|
module ParserGem
|
|
@@ -246,15 +247,100 @@ module Solargraph
|
|
|
246
247
|
end
|
|
247
248
|
prev = node
|
|
248
249
|
end
|
|
249
|
-
|
|
250
|
+
find_recipient_node_by_text(source, offset)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Text-based fallback for finding a method call recipient when the AST
|
|
254
|
+
# is unavailable (e.g., unparseable source with syntax errors).
|
|
255
|
+
#
|
|
256
|
+
# Scans backward from cursor offset to find '(' and the method name
|
|
257
|
+
# before it, then creates a minimal :send node.
|
|
258
|
+
#
|
|
259
|
+
# @param source [Solargraph::Source]
|
|
260
|
+
# @param offset [Integer]
|
|
261
|
+
# @return [Parser::AST::Node, nil]
|
|
262
|
+
def find_recipient_node_by_text source, offset
|
|
263
|
+
code = source.code
|
|
264
|
+
return nil if offset.nil? || offset <= 0 || offset > code.length
|
|
265
|
+
|
|
266
|
+
# The '(' could be at offset-1 (cursor after '(') or at offset (cursor on '(')
|
|
267
|
+
start_pos = offset - 1
|
|
268
|
+
if start_pos.positive? && code[start_pos] != '(' && code[offset] == '('
|
|
269
|
+
start_pos = offset
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Scan backward to find the matching '(' (handle nested parens)
|
|
273
|
+
depth = 0
|
|
274
|
+
paren_pos = nil
|
|
275
|
+
pos = start_pos
|
|
276
|
+
while pos >= 0
|
|
277
|
+
case code[pos]
|
|
278
|
+
when ')'
|
|
279
|
+
depth += 1
|
|
280
|
+
when '('
|
|
281
|
+
if depth.zero?
|
|
282
|
+
paren_pos = pos
|
|
283
|
+
break
|
|
284
|
+
end
|
|
285
|
+
depth -= 1
|
|
286
|
+
end
|
|
287
|
+
pos -= 1
|
|
288
|
+
end
|
|
289
|
+
return nil if paren_pos.nil?
|
|
290
|
+
|
|
291
|
+
# Skip whitespace before '(' to find method name
|
|
292
|
+
idx = paren_pos - 1
|
|
293
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /\s/
|
|
294
|
+
return nil if idx.negative?
|
|
295
|
+
|
|
296
|
+
# Read method name (including ? and !)
|
|
297
|
+
name_end = idx + 1
|
|
298
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_?!]/
|
|
299
|
+
name_start = idx + 1
|
|
300
|
+
return nil if name_start >= name_end
|
|
301
|
+
method_name = code[name_start...name_end]
|
|
302
|
+
return nil if method_name.empty?
|
|
303
|
+
|
|
304
|
+
# Check for receiver pattern: receiver.method( or receiver::method(
|
|
305
|
+
idx = name_start - 1
|
|
306
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /\s/
|
|
307
|
+
if idx >= 0 && code[idx] == '.'
|
|
308
|
+
idx -= 1
|
|
309
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /\s/
|
|
310
|
+
recv_end = idx + 1
|
|
311
|
+
idx -= 1 while idx >= 0 && code[idx] =~ /[a-zA-Z0-9_@$]/
|
|
312
|
+
recv_start = idx + 1
|
|
313
|
+
if recv_start < recv_end
|
|
314
|
+
recv_name = code[recv_start...recv_end]
|
|
315
|
+
unless recv_name.empty?
|
|
316
|
+
receiver_node = ::Parser::AST::Node.new(:send, [nil, recv_name.to_sym])
|
|
317
|
+
return ::Parser::AST::Node.new(:send, [receiver_node, method_name.to_sym])
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
elsif idx >= 0 && idx.positive? && code[idx - 1] == ':' && code[idx] == ':'
|
|
321
|
+
const_end = idx - 1
|
|
322
|
+
const_start = const_end
|
|
323
|
+
const_start -= 1 while const_start.positive? && code[const_start - 1] =~ /[a-zA-Z0-9_]/
|
|
324
|
+
const_name = code[const_start...const_end]
|
|
325
|
+
unless const_name.empty? || method_name.empty?
|
|
326
|
+
const_node = ::Parser::AST::Node.new(:const, [nil, const_name.to_sym])
|
|
327
|
+
return ::Parser::AST::Node.new(:send, [const_node, method_name.to_sym])
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Simple method call without receiver
|
|
332
|
+
::Parser::AST::Node.new(:send, [nil, method_name.to_sym])
|
|
250
333
|
end
|
|
251
334
|
|
|
252
335
|
# @param cursor [Solargraph::Source::Cursor]
|
|
253
336
|
# @return [Parser::AST::Node, nil]
|
|
254
337
|
def repaired_find_recipient_node cursor
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
338
|
+
c = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
|
|
339
|
+
tree = c.source.tree_at(c.position.line, c.position.column)
|
|
340
|
+
tree.each do |node|
|
|
341
|
+
return node if node.type == :send
|
|
342
|
+
end
|
|
343
|
+
find_recipient_node_by_text(cursor.source, cursor.offset)
|
|
258
344
|
end
|
|
259
345
|
|
|
260
346
|
#
|
|
@@ -505,3 +591,4 @@ module Solargraph
|
|
|
505
591
|
end
|
|
506
592
|
end
|
|
507
593
|
end
|
|
594
|
+
# rubocop:enable Metrics/ModuleLength
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Solargraph
|
|
4
|
-
module Parser
|
|
5
|
-
module ParserGem
|
|
6
|
-
module NodeProcessors
|
|
7
|
-
class NamespaceNode < Parser::NodeProcessor::Base
|
|
8
|
-
include ParserGem::NodeMethods
|
|
9
|
-
|
|
10
|
-
def process
|
|
11
|
-
superclass_name = nil
|
|
12
|
-
superclass_name = unpack_name(node.children[1]) if node.type == :class && node.children[1]&.type == :const
|
|
13
|
-
|
|
14
|
-
loc = get_node_location(node)
|
|
15
|
-
nspin = Solargraph::Pin::Namespace.new(
|
|
16
|
-
type: node.type,
|
|
17
|
-
location: loc,
|
|
18
|
-
closure: region.closure,
|
|
19
|
-
name: unpack_name(node.children[0]),
|
|
20
|
-
comments: comments_for(node),
|
|
21
|
-
visibility: :public,
|
|
22
|
-
gates: region.closure.gates.freeze,
|
|
23
|
-
source: :parser
|
|
24
|
-
)
|
|
25
|
-
pins.push nspin
|
|
26
|
-
unless superclass_name.nil?
|
|
27
|
-
pins.push Pin::Reference::Superclass.new(
|
|
28
|
-
location: loc,
|
|
29
|
-
closure: pins.last,
|
|
30
|
-
name: superclass_name,
|
|
31
|
-
source: :parser
|
|
32
|
-
)
|
|
33
|
-
end
|
|
34
|
-
process_children region.update(closure: nspin, visibility: :public)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Parser
|
|
5
|
+
module ParserGem
|
|
6
|
+
module NodeProcessors
|
|
7
|
+
class NamespaceNode < Parser::NodeProcessor::Base
|
|
8
|
+
include ParserGem::NodeMethods
|
|
9
|
+
|
|
10
|
+
def process
|
|
11
|
+
superclass_name = nil
|
|
12
|
+
superclass_name = unpack_name(node.children[1]) if node.type == :class && node.children[1]&.type == :const
|
|
13
|
+
|
|
14
|
+
loc = get_node_location(node)
|
|
15
|
+
nspin = Solargraph::Pin::Namespace.new(
|
|
16
|
+
type: node.type,
|
|
17
|
+
location: loc,
|
|
18
|
+
closure: region.closure,
|
|
19
|
+
name: unpack_name(node.children[0]),
|
|
20
|
+
comments: comments_for(node),
|
|
21
|
+
visibility: :public,
|
|
22
|
+
gates: region.closure.gates.freeze,
|
|
23
|
+
source: :parser
|
|
24
|
+
)
|
|
25
|
+
pins.push nspin
|
|
26
|
+
unless superclass_name.nil?
|
|
27
|
+
pins.push Pin::Reference::Superclass.new(
|
|
28
|
+
location: loc,
|
|
29
|
+
closure: pins.last,
|
|
30
|
+
name: superclass_name,
|
|
31
|
+
source: :parser
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
process_children region.update(closure: nspin, visibility: :public)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/solargraph/pin/base.rb
CHANGED
|
@@ -293,7 +293,7 @@ module Solargraph
|
|
|
293
293
|
# @param attr [::Symbol]
|
|
294
294
|
# @return [void]
|
|
295
295
|
# @todo strong typechecking should complain when there are no block-related tags
|
|
296
|
-
def assert_same_array_content
|
|
296
|
+
def assert_same_array_content(other, attr, &)
|
|
297
297
|
arr1 = send(attr)
|
|
298
298
|
raise "Expected #{attr} on #{self} to be an Enumerable, got #{arr1.class}" unless arr1.is_a?(::Enumerable)
|
|
299
299
|
# @type arr1 [::Enumerable]
|
|
@@ -302,9 +302,9 @@ module Solargraph
|
|
|
302
302
|
# @type arr2 [::Enumerable]
|
|
303
303
|
|
|
304
304
|
# @type [undefined]
|
|
305
|
-
values1 = arr1.map(&
|
|
305
|
+
values1 = arr1.map(&)
|
|
306
306
|
# @type [undefined]
|
|
307
|
-
values2 = arr2.map(&
|
|
307
|
+
values2 = arr2.map(&)
|
|
308
308
|
# @sg-ignore
|
|
309
309
|
return arr1 if values1 == values2
|
|
310
310
|
Solargraph.assert_or_log(:"combine_with_#{attr}",
|
|
@@ -508,6 +508,7 @@ module Solargraph
|
|
|
508
508
|
# @todo Stubbing this method while we debug an infinite loop bug in Ruby 3.x
|
|
509
509
|
return same_type_arity_signatures
|
|
510
510
|
|
|
511
|
+
# rubocop:disable Lint/UnreachableCode
|
|
511
512
|
# This is an O(n^2) operation, so bail out if n is not small
|
|
512
513
|
return same_type_arity_signatures if same_type_arity_signatures.length > 10
|
|
513
514
|
|
|
@@ -534,6 +535,7 @@ module Solargraph
|
|
|
534
535
|
end
|
|
535
536
|
end
|
|
536
537
|
end
|
|
538
|
+
# rubocop:enable Lint/UnreachableCode
|
|
537
539
|
end
|
|
538
540
|
|
|
539
541
|
# @param name [String]
|
|
@@ -31,7 +31,9 @@ module Solargraph
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def combine_with other, attrs = {}
|
|
34
|
-
# Parameters can be combined with local variables
|
|
34
|
+
# Parameters can only be combined with local variables in the same closure
|
|
35
|
+
return self unless other.closure == closure
|
|
36
|
+
|
|
35
37
|
new_attrs = if other.is_a?(Parameter)
|
|
36
38
|
{
|
|
37
39
|
decl: assert_same(other, :decl),
|
|
@@ -41,11 +41,11 @@ module Solargraph
|
|
|
41
41
|
match = [fuzzy_string_match(pin.path, @query), fuzzy_string_match(pin.name, @query)].max
|
|
42
42
|
Result.new(match, pin) if match > 0.7
|
|
43
43
|
end
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
.compact
|
|
45
|
+
# @param a [self]
|
|
46
|
+
# @param b [self]
|
|
47
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1050
|
|
48
|
+
.sort { |a, b| b.match <=> a.match }
|
|
49
49
|
.map(&:pin)
|
|
50
50
|
end
|
|
51
51
|
|
|
@@ -481,7 +481,7 @@ module Solargraph
|
|
|
481
481
|
visibility = VISIBILITY_OVERRIDE[override_key]
|
|
482
482
|
simple_override_key = [closure.path, scope]
|
|
483
483
|
visibility ||= VISIBILITY_OVERRIDE[simple_override_key]
|
|
484
|
-
if closure.path == 'Kernel' && Kernel.
|
|
484
|
+
if closure.path == 'Kernel' && Kernel.private_method_defined?(decl.name, false)
|
|
485
485
|
visibility ||= :private
|
|
486
486
|
end
|
|
487
487
|
if decl.kind == :singleton_instance
|
|
@@ -115,8 +115,17 @@ module Solargraph
|
|
|
115
115
|
def recipient
|
|
116
116
|
@recipient ||= begin
|
|
117
117
|
node = recipient_node
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
if node.nil?
|
|
119
|
+
nil
|
|
120
|
+
else
|
|
121
|
+
rng = Range.from_node(node)
|
|
122
|
+
if rng
|
|
123
|
+
Cursor.new(source, rng.ending)
|
|
124
|
+
else
|
|
125
|
+
pos = Position.new(position.line, [position.column - 1, 0].max)
|
|
126
|
+
Cursor.new(source, pos)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
120
129
|
end
|
|
121
130
|
end
|
|
122
131
|
alias receiver recipient
|
|
@@ -54,8 +54,13 @@ module Solargraph
|
|
|
54
54
|
# @return [Array<Pin::Method>]
|
|
55
55
|
def signify
|
|
56
56
|
return [] unless cursor.argument?
|
|
57
|
+
return [] if cursor.recipient_node.nil?
|
|
57
58
|
chain = Parser.chain(cursor.recipient_node, cursor.filename)
|
|
58
|
-
|
|
59
|
+
name_pin = context_pin
|
|
60
|
+
if name_pin.nil?
|
|
61
|
+
name_pin = Pin::ProxyType.anonymous(ComplexType.try_parse('::Object'))
|
|
62
|
+
end
|
|
63
|
+
chain.define(api_map, name_pin, locals).select { |pin| pin.is_a?(Pin::Method) }
|
|
59
64
|
end
|
|
60
65
|
|
|
61
66
|
# @return [ComplexType]
|
|
@@ -283,7 +283,7 @@ module Solargraph
|
|
|
283
283
|
|
|
284
284
|
# @return [Array<Pin::BaseVariable>]
|
|
285
285
|
def all_variables
|
|
286
|
-
source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.
|
|
286
|
+
source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.grep(Pin::LocalVariable)
|
|
287
287
|
end
|
|
288
288
|
|
|
289
289
|
# @return [Array<Problem>]
|
|
@@ -773,9 +773,9 @@ module Solargraph
|
|
|
773
773
|
return [] if parameters.any?(&:rest?)
|
|
774
774
|
opt = optional_param_count(parameters)
|
|
775
775
|
return [] if unchecked.length <= req + opt
|
|
776
|
-
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) &&
|
|
777
|
-
|
|
778
|
-
|
|
776
|
+
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && parameters.map(&:decl).intersect?(%i[
|
|
777
|
+
kwarg kwoptarg kwrestarg
|
|
778
|
+
])
|
|
779
779
|
return []
|
|
780
780
|
end
|
|
781
781
|
return [] if arguments.length - req == parameters.select { |p| %i[optarg kwoptarg].include?(p.decl) }.length
|
data/lib/solargraph/version.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Solargraph
|
|
|
32
32
|
# @sg-ignore Need to add nil check here
|
|
33
33
|
final_visibility ||= VISIBILITY_OVERRIDE[[closure.path, final_scope]]
|
|
34
34
|
# @sg-ignore Need to add nil check here
|
|
35
|
-
if closure.path == 'Kernel' && Kernel.
|
|
35
|
+
if closure.path == 'Kernel' && Kernel.private_method_defined?(name.to_sym, false)
|
|
36
36
|
final_visibility ||= :private
|
|
37
37
|
end
|
|
38
38
|
final_visibility ||= visibility
|
data/lib/solargraph.rb
CHANGED
|
@@ -113,13 +113,13 @@ module Solargraph
|
|
|
113
113
|
# @yieldreturn [generic<T>]
|
|
114
114
|
# @sg-ignore dynamic call, but both functions behave the same
|
|
115
115
|
# @return [generic<T>]
|
|
116
|
-
def self.with_clean_env
|
|
116
|
+
def self.with_clean_env(&)
|
|
117
117
|
meth = if Bundler.respond_to?(:with_original_env)
|
|
118
118
|
:with_original_env
|
|
119
119
|
else
|
|
120
120
|
:with_clean_env
|
|
121
121
|
end
|
|
122
|
-
Bundler.send
|
|
122
|
+
Bundler.send(meth, &)
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
125
|
|