solargraph 0.53.2 → 0.53.4
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/CHANGELOG.md +14 -0
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map.rb +27 -21
- data/lib/solargraph/complex_type/unique_type.rb +32 -9
- data/lib/solargraph/gem_pins.rb +1 -1
- data/lib/solargraph/language_server/host.rb +18 -0
- data/lib/solargraph/library.rb +13 -1
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -19
- data/lib/solargraph/pin/base_variable.rb +1 -1
- data/lib/solargraph/pin/block.rb +15 -32
- data/lib/solargraph/pin/method.rb +1 -1
- data/lib/solargraph/rbs_map/conversions.rb +3 -38
- data/lib/solargraph/rbs_map/core_fills.rb +12 -6
- data/lib/solargraph/rbs_map/core_map.rb +2 -13
- data/lib/solargraph/rbs_map.rb +6 -4
- data/lib/solargraph/source_map/clip.rb +3 -2
- data/lib/solargraph/source_map.rb +0 -8
- data/lib/solargraph/type_checker.rb +21 -2
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +5 -2
- metadata +2 -3
- data/lib/solargraph/rbs_map/core_signs.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82af0b18d57296a8eef96680e60f131bad23268e4043d49407d197fc378dd3d2
|
4
|
+
data.tar.gz: 10c5622ac74f0feef06033ed0b851268c876a68581d846b2874fe61a29612acb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1671b54ae2c314d5c566629706b6de94ca5de0902d1d56e7b96853a889d54b0caef084a5c416222f6fe9f4d40387ea3b56d34b6af917a36855ae902f0b8acf0d
|
7
|
+
data.tar.gz: e7b24e7c08164da0a0b60fc8f04281bfceef59e95470d3f3e78193b024d615da2ae62f94712222ffac722623f7de8207f7af29013bdad6787c63716556ecaf43
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.53.4 - March 30, 2025
|
2
|
+
- [regression] Restore 'Unresolved call' typecheck for stdlib objects (#849)
|
3
|
+
- Lazy dynamic rebinding (#851)
|
4
|
+
- Restore fill for Class#allocate (#848)
|
5
|
+
- [regression] Ensure YardMap gems have return type for Class<T>.new (#850)
|
6
|
+
- Create implicit .new pins in namespace method queries (#853)
|
7
|
+
|
8
|
+
## 0.53.3 - March 29, 2025
|
9
|
+
- Remove redundant core fills (#824, #841)
|
10
|
+
- Resolve self type in variable assignments (#839)
|
11
|
+
- Eliminate splat-related false-alarms in strict typechecking (#840)
|
12
|
+
- Dynamic block binding with yieldreceiver (#842)
|
13
|
+
- Resolve generics by descending through context type (#847)
|
14
|
+
|
1
15
|
## 0.53.2 - March 27, 2025
|
2
16
|
- Fix a self-type-related false-positive in strict typechecking (#834)
|
3
17
|
- DocMap fetches gem dependencies (#835)
|
@@ -6,10 +6,13 @@ module Solargraph
|
|
6
6
|
|
7
7
|
# Get the YARD CodeObject at the specified path.
|
8
8
|
#
|
9
|
+
# @generic T
|
9
10
|
# @param path [String]
|
10
|
-
# @
|
11
|
-
|
12
|
-
|
11
|
+
# @param klass [Class<generic<T>>]
|
12
|
+
# @return [generic<T>, nil]
|
13
|
+
def code_object_at path, klass = YARD::CodeObjects::Base
|
14
|
+
obj = code_object_map[path]
|
15
|
+
obj if obj&.is_a?(klass)
|
13
16
|
end
|
14
17
|
|
15
18
|
# @return [Array<String>]
|
@@ -41,11 +44,13 @@ module Solargraph
|
|
41
44
|
end
|
42
45
|
code_object_map[pin.path].docstring = pin.docstring
|
43
46
|
store.get_includes(pin.path).each do |ref|
|
44
|
-
|
47
|
+
include_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject)
|
48
|
+
include_object.instance_mixins.push code_object_map[ref] unless include_object.nil? or include_object.nil?
|
45
49
|
end
|
46
50
|
store.get_extends(pin.path).each do |ref|
|
47
|
-
|
48
|
-
|
51
|
+
extend_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject)
|
52
|
+
extend_object.instance_mixins.push code_object_map[ref] unless extend_object.nil? or extend_object.nil?
|
53
|
+
extend_object.class_mixins.push code_object_map[ref] unless extend_object.nil? or extend_object.nil?
|
49
54
|
end
|
50
55
|
end
|
51
56
|
store.method_pins.each do |pin|
|
@@ -53,13 +58,15 @@ module Solargraph
|
|
53
58
|
code_object_map[pin.path] ||= pin.code_object
|
54
59
|
next
|
55
60
|
end
|
56
|
-
|
61
|
+
|
62
|
+
code_object_map[pin.path] ||= YARD::CodeObjects::MethodObject.new(code_object_at(pin.namespace, YARD::CodeObjects::NamespaceObject), pin.name, pin.scope) { |obj|
|
57
63
|
next if pin.location.nil? || pin.location.filename.nil?
|
58
64
|
obj.add_file pin.location.filename, pin.location.range.start.line
|
59
65
|
}
|
60
|
-
|
61
|
-
|
62
|
-
|
66
|
+
method_object = code_object_at(pin.path, YARD::CodeObjects::MethodObject)
|
67
|
+
method_object.docstring = pin.docstring
|
68
|
+
method_object.visibility = pin.visibility || :public
|
69
|
+
method_object.parameters = pin.parameters.map do |p|
|
63
70
|
[p.name, p.asgn_code]
|
64
71
|
end
|
65
72
|
end
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -68,8 +68,6 @@ module Solargraph
|
|
68
68
|
@store = Store.new(@@core_map.pins + @doc_map.pins + implicit.pins + pins)
|
69
69
|
@unresolved_requires = @doc_map.unresolved_requires
|
70
70
|
@missing_docs = [] # @todo Implement missing docs
|
71
|
-
@rebindable_method_names = nil
|
72
|
-
store.block_pins.each { |blk| blk.rebind(self) }
|
73
71
|
self
|
74
72
|
end
|
75
73
|
|
@@ -154,17 +152,6 @@ module Solargraph
|
|
154
152
|
store.pins
|
155
153
|
end
|
156
154
|
|
157
|
-
# @return [Set<String>]
|
158
|
-
def rebindable_method_names
|
159
|
-
@rebindable_method_names ||= begin
|
160
|
-
result = ['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'].to_set
|
161
|
-
source_maps.each do |map|
|
162
|
-
result.merge map.rebindable_method_names
|
163
|
-
end
|
164
|
-
result
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
155
|
# An array of pins based on Ruby keywords (`if`, `end`, etc.).
|
169
156
|
#
|
170
157
|
# @return [Enumerable<Solargraph::Pin::Keyword>]
|
@@ -324,6 +311,26 @@ module Solargraph
|
|
324
311
|
result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
|
325
312
|
else
|
326
313
|
result.concat inner_get_methods(rooted_tag, scope, visibility, deep, skip)
|
314
|
+
unless %w[Class Class<Class>].include?(rooted_tag)
|
315
|
+
result.map! do |pin|
|
316
|
+
next pin unless pin.path == 'Class#new'
|
317
|
+
init_pin = get_method_stack(rooted_tag, 'initialize').first
|
318
|
+
next pin unless init_pin
|
319
|
+
|
320
|
+
type = ComplexType.try_parse(ComplexType.try_parse(rooted_tag).namespace)
|
321
|
+
Pin::Method.new(
|
322
|
+
name: 'new',
|
323
|
+
scope: :class,
|
324
|
+
location: init_pin.location,
|
325
|
+
parameters: init_pin.parameters,
|
326
|
+
signatures: init_pin.signatures.map { |sig| sig.proxy(type) },
|
327
|
+
return_type: type,
|
328
|
+
comments: init_pin.comments,
|
329
|
+
closure: init_pin.closure
|
330
|
+
# @todo Hack to force TypeChecker#internal_or_core?
|
331
|
+
).tap { |pin| pin.source = :rbs }
|
332
|
+
end
|
333
|
+
end
|
327
334
|
result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
|
328
335
|
result.concat inner_get_methods('Module', scope, visibility, deep, skip)
|
329
336
|
end
|
@@ -737,23 +744,22 @@ module Solargraph
|
|
737
744
|
# @param visibility [Enumerable<Symbol>]
|
738
745
|
# @return [Array<Pin::Base>]
|
739
746
|
def resolve_method_aliases pins, visibility = [:public, :private, :protected]
|
740
|
-
|
741
|
-
pins.each do |pin|
|
747
|
+
pins.map do |pin|
|
742
748
|
resolved = resolve_method_alias(pin)
|
743
|
-
next if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
744
|
-
|
745
|
-
end
|
746
|
-
result
|
749
|
+
next pin if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
750
|
+
resolved
|
751
|
+
end.compact
|
747
752
|
end
|
748
753
|
|
749
754
|
# @param pin [Pin::MethodAlias, Pin::Base]
|
750
755
|
# @return [Pin::Method]
|
751
756
|
def resolve_method_alias pin
|
752
|
-
return pin
|
757
|
+
return pin unless pin.is_a?(Pin::MethodAlias)
|
758
|
+
return nil if @method_alias_stack.include?(pin.path)
|
753
759
|
@method_alias_stack.push pin.path
|
754
760
|
origin = get_method_stack(pin.full_context.tag, pin.original, scope: pin.scope).first
|
755
761
|
@method_alias_stack.pop
|
756
|
-
return
|
762
|
+
return nil if origin.nil?
|
757
763
|
args = {
|
758
764
|
location: pin.location,
|
759
765
|
closure: pin.closure,
|
@@ -8,7 +8,7 @@ module Solargraph
|
|
8
8
|
class UniqueType
|
9
9
|
include TypeMethods
|
10
10
|
|
11
|
-
attr_reader :all_params
|
11
|
+
attr_reader :all_params, :subtypes, :key_types
|
12
12
|
|
13
13
|
# Create a UniqueType with the specified name and an optional substring.
|
14
14
|
# The substring is the parameter section of a parametrized type, e.g.,
|
@@ -105,13 +105,9 @@ module Solargraph
|
|
105
105
|
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
106
106
|
# @return [UniqueType, ComplexType]
|
107
107
|
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
new_binding = false
|
112
|
-
|
113
|
-
type_param = t.subtypes.first&.name
|
114
|
-
next t unless generics_to_resolve.include? type_param
|
108
|
+
if name == ComplexType::GENERIC_TAG_NAME
|
109
|
+
type_param = subtypes.first&.name
|
110
|
+
return self unless generics_to_resolve.include? type_param
|
115
111
|
unless context_type.nil? || !resolved_generic_values[type_param].nil?
|
116
112
|
new_binding = true
|
117
113
|
resolved_generic_values[type_param] = context_type
|
@@ -121,7 +117,34 @@ module Solargraph
|
|
121
117
|
complex_type.resolve_generics_from_context(generics_to_resolve, nil, resolved_generic_values: resolved_generic_values)
|
122
118
|
end
|
123
119
|
end
|
124
|
-
resolved_generic_values[type_param] ||
|
120
|
+
return resolved_generic_values[type_param] || self
|
121
|
+
end
|
122
|
+
|
123
|
+
# @todo typechecking should complain when the method being called has no @yieldparam tag
|
124
|
+
new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:key_types)
|
125
|
+
new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:subtypes)
|
126
|
+
recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
|
127
|
+
end
|
128
|
+
|
129
|
+
# @param generics_to_resolve [Enumerable<String>]
|
130
|
+
# @param context_type [UniqueType]
|
131
|
+
# @param resolved_generic_values [Hash{String => ComplexType}]
|
132
|
+
# @yieldreturn [Array<ComplexType>]
|
133
|
+
# @return [Array<ComplexType>]
|
134
|
+
def resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values)
|
135
|
+
types = yield self
|
136
|
+
types.each_with_index.flat_map do |ct, i|
|
137
|
+
ct.items.flat_map do |ut|
|
138
|
+
context_params = yield context_type if context_type
|
139
|
+
if context_params && context_params[i]
|
140
|
+
type_arg = context_params[i]
|
141
|
+
type_arg.map do |new_unique_context_type|
|
142
|
+
ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type, resolved_generic_values: resolved_generic_values
|
143
|
+
end
|
144
|
+
else
|
145
|
+
ut.resolve_generics_from_context generics_to_resolve, nil, resolved_generic_values: resolved_generic_values
|
146
|
+
end
|
147
|
+
end
|
125
148
|
end
|
126
149
|
end
|
127
150
|
|
data/lib/solargraph/gem_pins.rb
CHANGED
@@ -20,7 +20,7 @@ module Solargraph
|
|
20
20
|
combined = yard_pins.map do |yard|
|
21
21
|
in_yard.add yard.path
|
22
22
|
next yard unless yard.is_a?(Pin::Method)
|
23
|
-
rbs = rbs_map.path_pin(yard.path)
|
23
|
+
rbs = rbs_map.path_pin(yard.path, Pin::Method)
|
24
24
|
next yard unless rbs
|
25
25
|
# @todo Could not include: attribute and anon_splat
|
26
26
|
# @sg-ignore
|
@@ -493,6 +493,24 @@ module Solargraph
|
|
493
493
|
end
|
494
494
|
if params['data']['path']
|
495
495
|
result.concat library.path_pins(params['data']['path'])
|
496
|
+
# @todo This exception is necessary because `Library#path_pins` does
|
497
|
+
# not perform a namespace method query, so the implicit `.new` pin
|
498
|
+
# might not exist.
|
499
|
+
if result.empty? && params['data']['path'] =~ /\.new$/
|
500
|
+
result.concat(library.path_pins(params['data']['path'].sub(/\.new$/, '#initialize')).map do |pin|
|
501
|
+
next pin unless pin.name == 'initialize'
|
502
|
+
|
503
|
+
Pin::Method.new(
|
504
|
+
name: 'new',
|
505
|
+
scope: :class,
|
506
|
+
location: pin.location,
|
507
|
+
parameters: pin.parameters,
|
508
|
+
return_type: ComplexType.try_parse(params['data']['path']),
|
509
|
+
comments: pin.comments,
|
510
|
+
closure: pin.closure
|
511
|
+
)
|
512
|
+
end)
|
513
|
+
end
|
496
514
|
end
|
497
515
|
# Selecting by both location and path can result in duplicate pins
|
498
516
|
result.uniq { |p| [p.path, p.location] }
|
data/lib/solargraph/library.rb
CHANGED
@@ -251,7 +251,19 @@ module Solargraph
|
|
251
251
|
found = source.references(pin.name)
|
252
252
|
found.select! do |loc|
|
253
253
|
referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
|
254
|
-
referenced
|
254
|
+
referenced&.path == pin.path
|
255
|
+
end
|
256
|
+
if pin.path == 'Class#new'
|
257
|
+
caller = cursor.chain.base.infer(api_map, clip.send(:block), clip.locals).first
|
258
|
+
if caller.defined?
|
259
|
+
found.select! do |loc|
|
260
|
+
clip = api_map.clip_at(loc.filename, loc.range.start)
|
261
|
+
other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:block), clip.locals).first
|
262
|
+
caller == other
|
263
|
+
end
|
264
|
+
else
|
265
|
+
found.clear
|
266
|
+
end
|
255
267
|
end
|
256
268
|
# HACK: for language clients that exclude special characters from the start of variable names
|
257
269
|
if strip && match = cursor.word.match(/^[^a-z0-9_]+/i)
|
data/lib/solargraph/page.rb
CHANGED
@@ -7,6 +7,12 @@ require 'cgi'
|
|
7
7
|
|
8
8
|
module Solargraph
|
9
9
|
class Page
|
10
|
+
# @todo This method directive is necessary because OpenStruct.new confuses
|
11
|
+
# the typechecker.
|
12
|
+
# @!method self.new(locals, render_method)
|
13
|
+
# @param locals[Hash]
|
14
|
+
# @param render_method [Proc]
|
15
|
+
# @return [Binder]
|
10
16
|
class Binder < OpenStruct
|
11
17
|
# @param locals [Hash]
|
12
18
|
# @param render_method [Proc]
|
@@ -6,31 +6,18 @@ module Solargraph
|
|
6
6
|
module NodeProcessors
|
7
7
|
class DefNode < Parser::NodeProcessor::Base
|
8
8
|
def process
|
9
|
+
name = node.children[0].to_s
|
10
|
+
scope = region.scope || (region.closure.is_a?(Pin::Singleton) ? :class : :instance)
|
9
11
|
methpin = Solargraph::Pin::Method.new(
|
10
12
|
location: get_node_location(node),
|
11
13
|
closure: region.closure,
|
12
|
-
name:
|
14
|
+
name: name,
|
13
15
|
comments: comments_for(node),
|
14
|
-
scope:
|
15
|
-
visibility: region.visibility,
|
16
|
+
scope: scope,
|
17
|
+
visibility: scope == :instance && name == 'initialize' ? :private : region.visibility,
|
16
18
|
node: node
|
17
19
|
)
|
18
|
-
if
|
19
|
-
pins.push Solargraph::Pin::Method.new(
|
20
|
-
location: methpin.location,
|
21
|
-
closure: methpin.closure,
|
22
|
-
name: 'new',
|
23
|
-
comments: methpin.comments,
|
24
|
-
scope: :class,
|
25
|
-
parameters: methpin.parameters
|
26
|
-
)
|
27
|
-
# @todo Smelly instance variable access.
|
28
|
-
pins.last.instance_variable_set(:@return_type, ComplexType::SELF)
|
29
|
-
pins.push methpin
|
30
|
-
# @todo Smelly instance variable access.
|
31
|
-
methpin.instance_variable_set(:@visibility, :private)
|
32
|
-
methpin.instance_variable_set(:@return_type, ComplexType::VOID)
|
33
|
-
elsif region.visibility == :module_function
|
20
|
+
if region.visibility == :module_function
|
34
21
|
pins.push Solargraph::Pin::Method.new(
|
35
22
|
location: methpin.location,
|
36
23
|
closure: methpin.closure,
|
@@ -51,7 +51,7 @@ module Solargraph
|
|
51
51
|
# Use the return node for inference. The clip might infer from the
|
52
52
|
# first node in a method call instead of the entire call.
|
53
53
|
chain = Parser.chain(node, nil, nil)
|
54
|
-
result = chain.infer(api_map, closure, clip.locals)
|
54
|
+
result = chain.infer(api_map, closure, clip.locals).self_to(closure.context.tag)
|
55
55
|
types.push result unless result.undefined?
|
56
56
|
end
|
57
57
|
end
|
data/lib/solargraph/pin/block.rb
CHANGED
@@ -24,11 +24,11 @@ module Solargraph
|
|
24
24
|
# @param api_map [ApiMap]
|
25
25
|
# @return [void]
|
26
26
|
def rebind api_map
|
27
|
-
@
|
27
|
+
@rebind ||= maybe_rebind(api_map)
|
28
28
|
end
|
29
29
|
|
30
30
|
def binder
|
31
|
-
@
|
31
|
+
@rebind&.defined? ? @rebind : closure.binder
|
32
32
|
end
|
33
33
|
|
34
34
|
# @return [::Array<Parameter>]
|
@@ -44,39 +44,22 @@ module Solargraph
|
|
44
44
|
private
|
45
45
|
|
46
46
|
# @param api_map [ApiMap]
|
47
|
-
# @return [ComplexType
|
48
|
-
def
|
49
|
-
return
|
50
|
-
|
51
|
-
return nil unless api_map.rebindable_method_names.include?(word)
|
47
|
+
# @return [ComplexType]
|
48
|
+
def maybe_rebind api_map
|
49
|
+
return ComplexType::UNDEFINED unless receiver
|
50
|
+
|
52
51
|
chain = Parser.chain(receiver, location.filename)
|
53
52
|
locals = api_map.source_map(location.filename).locals_at(location)
|
54
|
-
links_last_word = chain.links.last.word
|
55
|
-
if %w[instance_eval instance_exec class_eval class_exec module_eval module_exec].include?(links_last_word)
|
56
|
-
return chain.base.infer(api_map, self, locals)
|
57
|
-
end
|
58
|
-
if 'define_method' == links_last_word and chain.define(api_map, self, locals).first&.path == 'Module#define_method' # change class type to instance type
|
59
|
-
if chain.links.size > 1 # Class.define_method
|
60
|
-
ty = chain.base.infer(api_map, self, locals)
|
61
|
-
return Solargraph::ComplexType.parse(ty.namespace)
|
62
|
-
else # define_method without self
|
63
|
-
return Solargraph::ComplexType.parse(closure.binder.namespace)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
# other case without early return, read block yieldreceiver tags
|
67
53
|
receiver_pin = chain.define(api_map, self, locals).first
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
78
|
-
end
|
79
|
-
nil
|
54
|
+
return ComplexType::UNDEFINED unless receiver_pin
|
55
|
+
|
56
|
+
types = receiver_pin.docstring.tag(:yieldreceiver)&.types
|
57
|
+
return ComplexType::UNDEFINED unless types&.any?
|
58
|
+
|
59
|
+
target = chain.base.infer(api_map, receiver_pin, locals)
|
60
|
+
target = full_context unless target.defined?
|
61
|
+
|
62
|
+
ComplexType.try_parse(*types).qualify(api_map, receiver_pin.context.namespace).self_to(target.to_s)
|
80
63
|
end
|
81
64
|
end
|
82
65
|
end
|
@@ -135,7 +135,7 @@ module Solargraph
|
|
135
135
|
result = []
|
136
136
|
result.push generate_signature(parameters, top_type) if top_type.defined?
|
137
137
|
result.concat(overloads.map { |meth| generate_signature(meth.parameters, meth.return_type) }) unless overloads.empty?
|
138
|
-
result.push generate_signature(parameters,
|
138
|
+
result.push generate_signature(parameters, @return_type || ComplexType::UNDEFINED) if result.empty?
|
139
139
|
result
|
140
140
|
end
|
141
141
|
end
|
@@ -39,24 +39,7 @@ module Solargraph
|
|
39
39
|
cursor = pins.length
|
40
40
|
environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
|
41
41
|
added_pins = pins[cursor..-1]
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
# @param added_pins [::Enumerable<Pin>]
|
46
|
-
# @return [void]
|
47
|
-
def add_back_implicit_pins(added_pins)
|
48
|
-
added_pins.each do |pin|
|
49
|
-
pin.source = :rbs
|
50
|
-
next unless pin.is_a?(Pin::Namespace) && pin.type == :class
|
51
|
-
next if pins.any? { |p| p.path == "#{pin.path}.new"}
|
52
|
-
pins.push Solargraph::Pin::Method.new(
|
53
|
-
location: nil,
|
54
|
-
closure: pin,
|
55
|
-
name: 'new',
|
56
|
-
comments: pin.comments,
|
57
|
-
scope: :class
|
58
|
-
)
|
59
|
-
end
|
42
|
+
added_pins.each { |pin| pin.source = :rbs }
|
60
43
|
end
|
61
44
|
|
62
45
|
# @param decl [RBS::AST::Declarations::Base]
|
@@ -303,26 +286,8 @@ module Solargraph
|
|
303
286
|
pin.signatures.concat method_def_to_sigs(decl, pin)
|
304
287
|
pins.push pin
|
305
288
|
if pin.name == 'initialize'
|
306
|
-
|
307
|
-
|
308
|
-
closure: pin.closure,
|
309
|
-
name: 'new',
|
310
|
-
comments: pin.comments,
|
311
|
-
scope: :class,
|
312
|
-
signatures: pin.signatures
|
313
|
-
)
|
314
|
-
pins.last.signatures.replace(
|
315
|
-
pin.signatures.map do |p|
|
316
|
-
Pin::Signature.new(
|
317
|
-
p.generics,
|
318
|
-
p.parameters,
|
319
|
-
ComplexType::SELF
|
320
|
-
)
|
321
|
-
end
|
322
|
-
)
|
323
|
-
# @todo Is this necessary?
|
324
|
-
# pin.instance_variable_set(:@visibility, :private)
|
325
|
-
# pin.instance_variable_set(:@return_type, ComplexType::VOID)
|
289
|
+
pin.instance_variable_set(:@visibility, :private)
|
290
|
+
pin.instance_variable_set(:@return_type, ComplexType::VOID)
|
326
291
|
end
|
327
292
|
end
|
328
293
|
if decl.singleton?
|
@@ -22,11 +22,17 @@ module Solargraph
|
|
22
22
|
closure: Solargraph::Pin::Namespace.new(name: 'Object'), comments: '@return [Class<self>]')
|
23
23
|
]
|
24
24
|
|
25
|
-
|
26
|
-
Override.
|
27
|
-
Override.
|
28
|
-
Override.
|
29
|
-
Override.
|
25
|
+
OVERRIDES = [
|
26
|
+
Override.from_comment('BasicObject#instance_eval', '@yieldreceiver [self]'),
|
27
|
+
Override.from_comment('BasicObject#instance_exec', '@yieldreceiver [self]'),
|
28
|
+
Override.from_comment('Module#define_method', '@yieldreceiver [Object<self>]'),
|
29
|
+
Override.from_comment('Module#class_eval', '@yieldreceiver [Class<self>]'),
|
30
|
+
Override.from_comment('Module#class_exec', '@yieldreceiver [Class<self>]'),
|
31
|
+
Override.from_comment('Module#module_eval', '@yieldreceiver [Module<self>]'),
|
32
|
+
Override.from_comment('Module#module_exec', '@yieldreceiver [Module<self>]'),
|
33
|
+
# RBS does not define Class with a generic, so all calls to
|
34
|
+
# generic() return an 'untyped'. We can do better:
|
35
|
+
Override.method_return('Class#allocate', 'self')
|
30
36
|
]
|
31
37
|
|
32
38
|
# HACK: Add Errno exception classes
|
@@ -38,7 +44,7 @@ module Solargraph
|
|
38
44
|
end
|
39
45
|
ERRNOS = errnos
|
40
46
|
|
41
|
-
ALL = KEYWORDS + MISSING +
|
47
|
+
ALL = KEYWORDS + MISSING + OVERRIDES + ERRNOS
|
42
48
|
end
|
43
49
|
end
|
44
50
|
end
|
@@ -13,27 +13,16 @@ module Solargraph
|
|
13
13
|
pins.replace cache
|
14
14
|
else
|
15
15
|
loader = RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
|
16
|
-
|
16
|
+
RBS::Environment.from_loader(loader).resolve_type_names
|
17
17
|
load_environment_to_pins(loader)
|
18
18
|
pins.concat RbsMap::CoreFills::ALL
|
19
19
|
processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
|
20
|
+
processed.each { |pin| pin.source = :rbs }
|
20
21
|
pins.replace processed
|
21
22
|
|
22
23
|
Cache.save('core.ser', pins)
|
23
24
|
end
|
24
25
|
end
|
25
|
-
|
26
|
-
def method_def_to_sigs decl, pin
|
27
|
-
stubs = CoreSigns.sign(pin.path)
|
28
|
-
return super unless stubs
|
29
|
-
stubs.map do |stub|
|
30
|
-
Pin::Signature.new(
|
31
|
-
[],
|
32
|
-
[],
|
33
|
-
ComplexType.try_parse(stub.return_type)
|
34
|
-
)
|
35
|
-
end
|
36
|
-
end
|
37
26
|
end
|
38
27
|
end
|
39
28
|
end
|
data/lib/solargraph/rbs_map.rb
CHANGED
@@ -7,7 +7,6 @@ module Solargraph
|
|
7
7
|
autoload :Conversions, 'solargraph/rbs_map/conversions'
|
8
8
|
autoload :CoreMap, 'solargraph/rbs_map/core_map'
|
9
9
|
autoload :CoreFills, 'solargraph/rbs_map/core_fills'
|
10
|
-
autoload :CoreSigns, 'solargraph/rbs_map/core_signs'
|
11
10
|
autoload :StdlibMap, 'solargraph/rbs_map/stdlib_map'
|
12
11
|
|
13
12
|
include Conversions
|
@@ -28,10 +27,13 @@ module Solargraph
|
|
28
27
|
load_environment_to_pins(loader)
|
29
28
|
end
|
30
29
|
|
30
|
+
# @generic T
|
31
31
|
# @param path [String]
|
32
|
-
# @
|
33
|
-
|
34
|
-
|
32
|
+
# @param klass [Class<generic<T>>]
|
33
|
+
# @return [generic<T>, nil]
|
34
|
+
def path_pin path, klass = Pin::Base
|
35
|
+
pin = pins.find { |p| p.path == path }
|
36
|
+
pin if pin&.is_a?(klass)
|
35
37
|
end
|
36
38
|
|
37
39
|
# @param path [String]
|
@@ -11,6 +11,7 @@ module Solargraph
|
|
11
11
|
def initialize api_map, cursor
|
12
12
|
@api_map = api_map
|
13
13
|
@cursor = cursor
|
14
|
+
block.rebind(api_map) if block.is_a?(Pin::Block)
|
14
15
|
end
|
15
16
|
|
16
17
|
# @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
|
@@ -50,9 +51,9 @@ module Solargraph
|
|
50
51
|
def infer
|
51
52
|
result = cursor.chain.infer(api_map, block, locals)
|
52
53
|
if result.tag == 'Class'
|
53
|
-
# HACK: Exception to return
|
54
|
+
# HACK: Exception to return BasicObject from Class#new
|
54
55
|
dfn = cursor.chain.define(api_map, block, locals).first
|
55
|
-
return ComplexType.try_parse('
|
56
|
+
return ComplexType.try_parse('BasicObject') if dfn && dfn.path == 'Class#new'
|
56
57
|
end
|
57
58
|
return result unless result.tag == 'self'
|
58
59
|
ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).tag)
|
@@ -40,14 +40,6 @@ module Solargraph
|
|
40
40
|
@pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
|
41
41
|
end
|
42
42
|
|
43
|
-
# @return [Set<String>]
|
44
|
-
def rebindable_method_names
|
45
|
-
@rebindable_method_names ||= pins_by_class(Pin::Method)
|
46
|
-
.select { |pin| pin.comments && pin.comments.include?('@yieldreceiver') }
|
47
|
-
.map(&:name)
|
48
|
-
.to_set
|
49
|
-
end
|
50
|
-
|
51
43
|
# @return [String]
|
52
44
|
def filename
|
53
45
|
source.filename
|
@@ -268,6 +268,7 @@ module Solargraph
|
|
268
268
|
base = base.base
|
269
269
|
end
|
270
270
|
closest = found.typify(api_map) if found
|
271
|
+
# @todo remove the internal_or_core? check at a higher-than-strict level
|
271
272
|
if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
|
272
273
|
unless closest.generic? || ignored_pins.include?(found)
|
273
274
|
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
@@ -299,6 +300,14 @@ module Solargraph
|
|
299
300
|
pin = pins.first
|
300
301
|
ap = if base.links.last.is_a?(Solargraph::Source::Chain::ZSuper)
|
301
302
|
arity_problems_for(pin, fake_args_for(block_pin), location)
|
303
|
+
elsif pin.path == 'Class#new'
|
304
|
+
fqns = if base.links.one?
|
305
|
+
block_pin.namespace
|
306
|
+
else
|
307
|
+
base.base.infer(api_map, block_pin, locals).namespace
|
308
|
+
end
|
309
|
+
init = api_map.get_method_stack(fqns, 'initialize').first
|
310
|
+
init ? arity_problems_for(init, base.links.last.arguments, location) : []
|
302
311
|
else
|
303
312
|
arity_problems_for(pin, base.links.last.arguments, location)
|
304
313
|
end
|
@@ -320,8 +329,14 @@ module Solargraph
|
|
320
329
|
argchain = base.links.last.arguments[idx]
|
321
330
|
if argchain.nil?
|
322
331
|
if par.decl == :arg
|
323
|
-
|
324
|
-
|
332
|
+
last = base.links.last.arguments.last
|
333
|
+
if last && last.node.type == :splat
|
334
|
+
argchain = last
|
335
|
+
next # don't try to apply the type of the splat - unlikely to be specific enough
|
336
|
+
else
|
337
|
+
errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
|
338
|
+
next
|
339
|
+
end
|
325
340
|
else
|
326
341
|
last = base.links.last.arguments.last
|
327
342
|
argchain = last if last && [:kwsplat, :hash].include?(last.node.type)
|
@@ -332,6 +347,10 @@ module Solargraph
|
|
332
347
|
errors.concat kwarg_problems_for sig, argchain, api_map, block_pin, locals, location, pin, params, idx
|
333
348
|
next
|
334
349
|
else
|
350
|
+
last = base.links.last.arguments.last
|
351
|
+
if last && last.node.type == :splat
|
352
|
+
next # don't try to apply the type of the splat - unlikely to be specific enough
|
353
|
+
end
|
335
354
|
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
336
355
|
ptype = ptype.self_to(par.context.namespace)
|
337
356
|
if ptype.nil?
|
data/lib/solargraph/version.rb
CHANGED
@@ -19,17 +19,20 @@ module Solargraph
|
|
19
19
|
gates: [code_object.namespace.to_s]
|
20
20
|
)
|
21
21
|
location = object_location(code_object, spec)
|
22
|
+
name ||= code_object.name.to_s
|
23
|
+
return_type = ComplexType::SELF if name == 'new'
|
22
24
|
comments = code_object.docstring ? code_object.docstring.all.to_s : ''
|
23
25
|
pin = Pin::Method.new(
|
24
26
|
location: location,
|
25
27
|
closure: closure,
|
26
|
-
name: name
|
28
|
+
name: name,
|
27
29
|
comments: comments,
|
28
30
|
scope: scope || code_object.scope,
|
29
31
|
visibility: visibility || code_object.visibility,
|
30
32
|
# @todo Might need to convert overloads to signatures
|
31
33
|
parameters: [],
|
32
|
-
explicit: code_object.is_explicit
|
34
|
+
explicit: code_object.is_explicit?,
|
35
|
+
return_type: return_type
|
33
36
|
)
|
34
37
|
pin.parameters.concat get_parameters(code_object, location, comments, pin)
|
35
38
|
pin
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solargraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.53.
|
4
|
+
version: 0.53.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-03-
|
11
|
+
date: 2025-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backport
|
@@ -558,7 +558,6 @@ files:
|
|
558
558
|
- lib/solargraph/rbs_map/conversions.rb
|
559
559
|
- lib/solargraph/rbs_map/core_fills.rb
|
560
560
|
- lib/solargraph/rbs_map/core_map.rb
|
561
|
-
- lib/solargraph/rbs_map/core_signs.rb
|
562
561
|
- lib/solargraph/rbs_map/stdlib_map.rb
|
563
562
|
- lib/solargraph/server_methods.rb
|
564
563
|
- lib/solargraph/shell.rb
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Solargraph
|
2
|
-
class RbsMap
|
3
|
-
module CoreSigns
|
4
|
-
Override = Pin::Reference::Override
|
5
|
-
|
6
|
-
class Stub
|
7
|
-
attr_reader :parameters
|
8
|
-
|
9
|
-
attr_reader :return_type
|
10
|
-
|
11
|
-
# @param parameters [Array<Hash>]
|
12
|
-
# @param return_type [String]
|
13
|
-
def initialize parameters, return_type
|
14
|
-
@parameters = parameters
|
15
|
-
@return_type = return_type
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
SIGNATURE_MAP = {
|
20
|
-
'Object#class' => [
|
21
|
-
Stub.new(
|
22
|
-
[],
|
23
|
-
'Class<self>'
|
24
|
-
)
|
25
|
-
]
|
26
|
-
}
|
27
|
-
|
28
|
-
# @param path [String]
|
29
|
-
# @return [Array<Stub>]
|
30
|
-
def self.sign path
|
31
|
-
SIGNATURE_MAP[path]
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|