solargraph 0.59.2 → 0.60.0
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/rspec.yml +4 -1
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +1 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile +3 -0
- data/lib/solargraph/api_map/index.rb +13 -2
- data/lib/solargraph/api_map/store.rb +21 -6
- data/lib/solargraph/api_map.rb +34 -2
- data/lib/solargraph/complex_type/unique_type.rb +4 -0
- data/lib/solargraph/complex_type.rb +4 -0
- data/lib/solargraph/doc_map.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_methods.rb +42 -0
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +29 -5
- data/lib/solargraph/pin/base.rb +31 -3
- data/lib/solargraph/pin/callable.rb +2 -2
- data/lib/solargraph/pin/common.rb +12 -0
- data/lib/solargraph/pin/method.rb +56 -16
- data/lib/solargraph/rbs_map/conversions.rb +96 -145
- data/lib/solargraph/rbs_translator.rb +206 -0
- data/lib/solargraph/shell.rb +130 -63
- data/lib/solargraph/source/chain/call.rb +8 -76
- data/lib/solargraph/source_map/mapper.rb +5 -135
- data/lib/solargraph/source_map.rb +14 -0
- data/lib/solargraph/version.rb +19 -1
- data/lib/solargraph/yard_map/directives/attribute_directive.rb +65 -0
- data/lib/solargraph/yard_map/directives/domain_directive.rb +30 -0
- data/lib/solargraph/yard_map/directives/method_directive.rb +51 -0
- data/lib/solargraph/yard_map/directives/override_directive.rb +30 -0
- data/lib/solargraph/yard_map/directives/parse_directive.rb +53 -0
- data/lib/solargraph/yard_map/directives/visibility_directive.rb +70 -0
- data/lib/solargraph/yard_map/directives.rb +35 -0
- data/lib/solargraph/yard_map/macro.rb +113 -0
- data/lib/solargraph/yard_map/mapper.rb +19 -1
- data/lib/solargraph/yard_map.rb +2 -0
- data/lib/solargraph.rb +1 -0
- data/solargraph.gemspec +1 -0
- metadata +24 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3eff86e8759fbaaa9526cf9cceb70827c701f3b1925d58e1575870989d60e60
|
|
4
|
+
data.tar.gz: a60b5c8e9598afdca808c94fa68e2551d17f970b812ca64c3f00d530d0498fff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 201861185888f275b0c7690887cca60a76d0bb90955c514ba4336e23f2adb9907d305f5e930b08f03c3c388d81bfd40996cd54c0f854035aab5a60703c40f954
|
|
7
|
+
data.tar.gz: b37cc2ed827560a2365b77af0921c0240498dcb287e1a1ba064f0879a748c2d365f0e61cec610233b11521206ab402e83aebbdec5c897a21eb3e9f7313fba602
|
data/.github/workflows/rspec.yml
CHANGED
|
@@ -21,7 +21,10 @@ jobs:
|
|
|
21
21
|
runs-on: ubuntu-latest
|
|
22
22
|
strategy:
|
|
23
23
|
matrix:
|
|
24
|
-
|
|
24
|
+
# @todo Restore 'head' once ruby/setup-ruby publishes it for ubuntu-24.04.
|
|
25
|
+
# It currently 404s ("Unavailable version head for ruby"), failing CI:
|
|
26
|
+
# https://github.com/castwide/solargraph/actions/runs/25863741955/job/76000137015?pr=1187
|
|
27
|
+
ruby-version: ['3.1', '3.2', '3.3', '3.4', '4.0']
|
|
25
28
|
rbs-version: ['3.10.0', '4.0.0', '4.0.1', '4.0.2']
|
|
26
29
|
exclude:
|
|
27
30
|
- ruby-version: '3.1'
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## 0.60.0 - June 15, 2026
|
|
2
|
+
- Add YARD macro support for DSL methods (#1187)
|
|
3
|
+
- YARD macros - More typecheck fixes (#1188)
|
|
4
|
+
- Macro fixes (#1189)
|
|
5
|
+
- Unused macro methods (#1191)
|
|
6
|
+
- Transitive macros (#1203)
|
|
7
|
+
- Allow CTRL-C interruption of profile command + macro debug logs (#1206)
|
|
8
|
+
- Support for Inline RBS (#1173)
|
|
9
|
+
- Make typechecker errors vim quickfix friendly (#1072)
|
|
10
|
+
- Generate RBS (#812)
|
|
11
|
+
|
|
1
12
|
## 0.59.2 - May 22, 2026
|
|
2
13
|
- Convert RBS implicit nil annotations (#1197)
|
|
3
14
|
- Temporary job stubs (#1200)
|
data/Gemfile
CHANGED
|
@@ -4,6 +4,9 @@ source 'https://rubygems.org'
|
|
|
4
4
|
|
|
5
5
|
gemspec name: 'solargraph'
|
|
6
6
|
|
|
7
|
+
# Test fixture gems
|
|
8
|
+
gem 'gem-with-yard-macros', path: 'spec/fixtures/gem-with-yard-macros'
|
|
9
|
+
|
|
7
10
|
# Local gemfile for development tools, etc.
|
|
8
11
|
local_gemfile = File.expand_path('.Gemfile', __dir__)
|
|
9
12
|
instance_eval File.read local_gemfile if File.exist? local_gemfile
|
|
@@ -5,6 +5,12 @@ module Solargraph
|
|
|
5
5
|
class Index
|
|
6
6
|
include Logging
|
|
7
7
|
|
|
8
|
+
# @return [Array<String>]
|
|
9
|
+
attr_reader :macro_method_names
|
|
10
|
+
|
|
11
|
+
# @return [Hash{String => Array<Pin::Method>}]
|
|
12
|
+
attr_reader :macro_method_name_pins
|
|
13
|
+
|
|
8
14
|
# @param pins [Array<Pin::Base>]
|
|
9
15
|
def initialize pins = []
|
|
10
16
|
catalog pins
|
|
@@ -95,16 +101,18 @@ module Solargraph
|
|
|
95
101
|
protected
|
|
96
102
|
|
|
97
103
|
attr_writer :pins, :pin_select_cache, :namespace_hash, :pin_class_hash, :path_pin_hash, :include_references,
|
|
98
|
-
:extend_references, :prepend_references, :superclass_references
|
|
104
|
+
:extend_references, :prepend_references, :superclass_references, :macro_method_names,
|
|
105
|
+
:macro_method_name_pins
|
|
99
106
|
|
|
100
107
|
# @return [self]
|
|
101
108
|
def deep_clone
|
|
102
109
|
Index.allocate.tap do |copy|
|
|
103
110
|
copy.pin_select_cache = {}
|
|
104
111
|
copy.pins = pins.clone
|
|
112
|
+
copy.macro_method_names = macro_method_names
|
|
105
113
|
%i[
|
|
106
114
|
namespace_hash pin_class_hash path_pin_hash include_references extend_references prepend_references
|
|
107
|
-
superclass_references
|
|
115
|
+
superclass_references macro_method_name_pins
|
|
108
116
|
].each do |sym|
|
|
109
117
|
copy.send("#{sym}=", send(sym).clone)
|
|
110
118
|
copy.send(sym)&.transform_values!(&:clone)
|
|
@@ -137,6 +145,9 @@ module Solargraph
|
|
|
137
145
|
map_references Pin::Reference::Prepend, prepend_references
|
|
138
146
|
map_references Pin::Reference::Extend, extend_references
|
|
139
147
|
map_references Pin::Reference::Superclass, superclass_references
|
|
148
|
+
macro_pins = pins_by_class(Pin::Method).select { |pin| pin.macros.any? }
|
|
149
|
+
@macro_method_names = macro_pins.to_set(&:name)
|
|
150
|
+
@macro_method_name_pins = macro_pins.to_set.classify(&:name)
|
|
140
151
|
map_overrides
|
|
141
152
|
pins_by_class(Pin::Reference::TypeAlias).each { |pin| alias_hash[pin.name] = pin.return_type }
|
|
142
153
|
self
|
|
@@ -21,11 +21,11 @@ module Solargraph
|
|
|
21
21
|
# - pinsets[0] = core Ruby pins
|
|
22
22
|
# - pinsets[1] = documentation/gem pins
|
|
23
23
|
# - pinsets[2] = convention pins
|
|
24
|
-
# - pinsets[3] = workspace source pins
|
|
24
|
+
# - pinsets[3] = workspace source pins (aka. "iced_pins")
|
|
25
25
|
# - pinsets[4] = currently open file pins
|
|
26
26
|
# @return [Boolean] True if the index was updated
|
|
27
|
-
def update *pinsets
|
|
28
|
-
return catalog(pinsets) if pinsets.length != @pinsets.length
|
|
27
|
+
def update *pinsets, &block
|
|
28
|
+
return catalog(pinsets, &block) if pinsets.length != @pinsets.length
|
|
29
29
|
|
|
30
30
|
changed = pinsets.find_index.with_index { |pinset, idx| @pinsets[idx] != pinset }
|
|
31
31
|
return false unless changed
|
|
@@ -43,6 +43,9 @@ module Solargraph
|
|
|
43
43
|
@indexes[changed + idx - 1].merge(pins)
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
|
+
# @type [Index]
|
|
47
|
+
@index = @indexes.last.clone
|
|
48
|
+
@index = @index.merge(block.call) if block
|
|
46
49
|
constants.clear
|
|
47
50
|
cached_qualify_superclass.clear
|
|
48
51
|
true
|
|
@@ -174,7 +177,7 @@ module Solargraph
|
|
|
174
177
|
result
|
|
175
178
|
end
|
|
176
179
|
|
|
177
|
-
# @return [Hash{String =>
|
|
180
|
+
# @return [Hash{String => YardMap::Macro}]
|
|
178
181
|
def named_macros
|
|
179
182
|
@named_macros ||= begin
|
|
180
183
|
result = {}
|
|
@@ -276,17 +279,27 @@ module Solargraph
|
|
|
276
279
|
index.alias_hash[name]
|
|
277
280
|
end
|
|
278
281
|
|
|
282
|
+
# @return [Array<String>]
|
|
283
|
+
def macro_method_names
|
|
284
|
+
index.macro_method_names
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# @return [Hash{String => Array<Pin::Method>}]
|
|
288
|
+
def macro_method_name_pins
|
|
289
|
+
index.macro_method_name_pins
|
|
290
|
+
end
|
|
291
|
+
|
|
279
292
|
private
|
|
280
293
|
|
|
281
294
|
# @return [Index]
|
|
282
295
|
def index
|
|
283
|
-
@
|
|
296
|
+
@index ||= Index.new
|
|
284
297
|
end
|
|
285
298
|
|
|
286
299
|
# @param pinsets [Array<Array<Pin::Base>>]
|
|
287
300
|
#
|
|
288
301
|
# @return [true]
|
|
289
|
-
def catalog pinsets
|
|
302
|
+
def catalog pinsets, &block
|
|
290
303
|
@pinsets = pinsets
|
|
291
304
|
# @type [Array<Index>]
|
|
292
305
|
@indexes = []
|
|
@@ -297,6 +310,8 @@ module Solargraph
|
|
|
297
310
|
@indexes.push(@indexes.last&.merge(pins) || Solargraph::ApiMap::Index.new(pins))
|
|
298
311
|
end
|
|
299
312
|
end
|
|
313
|
+
@index = @indexes.last.clone
|
|
314
|
+
@index = @index.merge(block.call) if block
|
|
300
315
|
constants.clear
|
|
301
316
|
cached_qualify_superclass.clear
|
|
302
317
|
true
|
data/lib/solargraph/api_map.rb
CHANGED
|
@@ -107,6 +107,7 @@ module Solargraph
|
|
|
107
107
|
# @return [self]
|
|
108
108
|
def catalog bench
|
|
109
109
|
@source_map_hash = bench.source_map_hash
|
|
110
|
+
# @type [Array<Pin::Base>]
|
|
110
111
|
iced_pins = bench.icebox.flat_map(&:pins)
|
|
111
112
|
live_pins = bench.live_map&.all_pins || []
|
|
112
113
|
conventions_environ.clear
|
|
@@ -123,11 +124,42 @@ module Solargraph
|
|
|
123
124
|
@doc_map = DocMap.new(unresolved_requires, bench.workspace, out: nil) # @todo Implement gem preferences
|
|
124
125
|
@unresolved_requires = @doc_map.unresolved_requires
|
|
125
126
|
end
|
|
126
|
-
|
|
127
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
128
|
+
Solargraph.logger.info 'Cataloging ApiMap started'
|
|
129
|
+
@cache.clear if store.update(@@core_map.pins, @doc_map.pins, conventions_environ.pins, iced_pins, live_pins) { process_macros }
|
|
127
130
|
@missing_docs = [] # @todo Implement missing docs
|
|
131
|
+
Solargraph.logger.info "Cataloging ApiMap finished in #{Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time} seconds"
|
|
128
132
|
self
|
|
129
133
|
end
|
|
130
134
|
|
|
135
|
+
# @return [Array<Pin::Base>]
|
|
136
|
+
def process_macros
|
|
137
|
+
macro_pins = []
|
|
138
|
+
Solargraph.logger.debug { "ApiMap#process_macros: processing macros for #{source_maps.size} source maps" }
|
|
139
|
+
Solargraph.logger.debug { "ApiMap#process_macros: store has #{store.macro_method_name_pins.size} macro method name pins" }
|
|
140
|
+
Solargraph.logger.debug { "ApiMap#process_macros: named macros: #{store.named_macros.keys.join(', ')}" }
|
|
141
|
+
source_maps.each do |source_map|
|
|
142
|
+
method_candidates = source_map.macro_method_candidates(store.macro_method_names)
|
|
143
|
+
Solargraph.logger.debug { "ApiMap#process_macros: processing source map for #{source_map.filename} with #{method_candidates.size} macro method candidates" }
|
|
144
|
+
method_candidates.each do |node|
|
|
145
|
+
closure = source_map.locate_closure_pin(node.location.line, node.location.column)
|
|
146
|
+
chain = Solargraph::Parser::ParserGem::NodeChainer.chain(node)
|
|
147
|
+
if node.children[0].nil? && store.macro_method_name_pins.key?(node.children[1].to_s)
|
|
148
|
+
match = store.macro_method_name_pins[node.children[1].to_s].find do |pin|
|
|
149
|
+
super_and_sub?(pin.namespace, closure.name)
|
|
150
|
+
end
|
|
151
|
+
if match
|
|
152
|
+
match.macros.each do |macro|
|
|
153
|
+
macro_pins.concat macro.generate_pins_from(chain, match, source_map)
|
|
154
|
+
end
|
|
155
|
+
next
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
macro_pins
|
|
161
|
+
end
|
|
162
|
+
|
|
131
163
|
# @return [DocMap]
|
|
132
164
|
def doc_map
|
|
133
165
|
@doc_map ||= DocMap.new([], Workspace.new('.'))
|
|
@@ -154,7 +186,7 @@ module Solargraph
|
|
|
154
186
|
end
|
|
155
187
|
|
|
156
188
|
# @param name [String, nil]
|
|
157
|
-
# @return [
|
|
189
|
+
# @return [Solargraph::YardMap::Macro, nil]
|
|
158
190
|
def named_macro name
|
|
159
191
|
# @sg-ignore Need to add nil check here
|
|
160
192
|
store.named_macros[name]
|
|
@@ -547,6 +547,10 @@ module Solargraph
|
|
|
547
547
|
yield new_type
|
|
548
548
|
end
|
|
549
549
|
|
|
550
|
+
def expand named_types
|
|
551
|
+
named_types[name] || self
|
|
552
|
+
end
|
|
553
|
+
|
|
550
554
|
# Generate a ComplexType that fully qualifies this type's namespaces.
|
|
551
555
|
#
|
|
552
556
|
# @param api_map [ApiMap] The ApiMap that performs qualification
|
|
@@ -298,6 +298,10 @@ module Solargraph
|
|
|
298
298
|
ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
|
|
299
299
|
end
|
|
300
300
|
|
|
301
|
+
def expand named_types
|
|
302
|
+
ComplexType.new(map { |ut| ut.expand(named_types) })
|
|
303
|
+
end
|
|
304
|
+
|
|
301
305
|
# @return [self]
|
|
302
306
|
def force_rooted
|
|
303
307
|
transform do |t|
|
data/lib/solargraph/doc_map.rb
CHANGED
|
@@ -317,6 +317,7 @@ module Solargraph
|
|
|
317
317
|
gemspec = Gem::Specification.find_by_path(path)
|
|
318
318
|
if gemspec.nil?
|
|
319
319
|
gem_name_guess = path.split('/').first
|
|
320
|
+
return nil if gem_name_guess.to_s.empty?
|
|
320
321
|
begin
|
|
321
322
|
# this can happen when the gem is included via a local path in
|
|
322
323
|
# a Gemfile; Gem doesn't try to index the paths in that case.
|
|
@@ -102,6 +102,48 @@ module Solargraph
|
|
|
102
102
|
signature
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
+
# Convert a DSL method call argument with directly inferrable simple params.
|
|
106
|
+
# @param node [Parser::AST::Node]
|
|
107
|
+
# @return [String, Integer, Float, Symbol, Array, Hash, Source::Chain, nil]
|
|
108
|
+
# @sg-ignore "does not match inferred type ::String, ::Parser::AST::Node" - this probably comes from the
|
|
109
|
+
# `.children[0]` call, which is not recognized as returning a literal value.
|
|
110
|
+
def simple_convert node
|
|
111
|
+
return nil unless Parser.is_ast_node?(node)
|
|
112
|
+
|
|
113
|
+
case node.type
|
|
114
|
+
when :const
|
|
115
|
+
unpack_name(node)
|
|
116
|
+
when :str, :dstr, :int, :float, :sym, true, false
|
|
117
|
+
node.children[0]
|
|
118
|
+
when :array
|
|
119
|
+
simple_convert_array(node)
|
|
120
|
+
when :hash
|
|
121
|
+
simple_convert_hash(node)
|
|
122
|
+
else
|
|
123
|
+
Solargraph::Parser.chain(node)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# @param node [Parser::AST::Node]
|
|
128
|
+
# @return [Array]
|
|
129
|
+
def simple_convert_array node
|
|
130
|
+
return [] unless Parser.is_ast_node?(node) && node.type == :array
|
|
131
|
+
node.children.compact.map { |c| simple_convert(c) }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# @param node [Parser::AST::Node]
|
|
135
|
+
# @return [Hash]
|
|
136
|
+
def simple_convert_hash node
|
|
137
|
+
return {} unless Parser.is_ast_node?(node) && node.type == :hash
|
|
138
|
+
result = {}
|
|
139
|
+
# @param pair [Parser::AST::Node]
|
|
140
|
+
node.children.each do |pair|
|
|
141
|
+
next unless Parser.is_ast_node?(pair) && pair.children[0]
|
|
142
|
+
result[pair.children[0].children[0]] = simple_convert(pair.children[1])
|
|
143
|
+
end
|
|
144
|
+
result
|
|
145
|
+
end
|
|
146
|
+
|
|
105
147
|
# @param node [Parser::AST::Node, nil]
|
|
106
148
|
# @return [Hash{Symbol => Chain}]
|
|
107
149
|
def convert_hash node
|
|
@@ -8,22 +8,27 @@ module Solargraph
|
|
|
8
8
|
include ParserGem::NodeMethods
|
|
9
9
|
|
|
10
10
|
def process
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
name = unpack_name(node.children[0])
|
|
12
|
+
comments = comments_for(node)
|
|
13
|
+
|
|
14
|
+
superclass_name = if node.type == :class && node.children[1]&.type == :const
|
|
15
|
+
"#{type_from_node}#{parameters_from_inline_rbs}"
|
|
16
|
+
end
|
|
13
17
|
|
|
14
18
|
loc = get_node_location(node)
|
|
15
19
|
nspin = Solargraph::Pin::Namespace.new(
|
|
16
20
|
type: node.type,
|
|
17
21
|
location: loc,
|
|
18
22
|
closure: region.closure,
|
|
19
|
-
name:
|
|
20
|
-
comments:
|
|
23
|
+
name: name,
|
|
24
|
+
comments: comments,
|
|
21
25
|
visibility: :public,
|
|
22
26
|
gates: region.closure.gates.freeze,
|
|
23
27
|
source: :parser
|
|
24
28
|
)
|
|
25
29
|
pins.push nspin
|
|
26
|
-
|
|
30
|
+
Solargraph.logger.warn "Superclass: #{superclass_name}" if superclass_name&.start_with?('Array')
|
|
31
|
+
if superclass_name
|
|
27
32
|
pins.push Pin::Reference::Superclass.new(
|
|
28
33
|
location: loc,
|
|
29
34
|
closure: pins.last,
|
|
@@ -33,6 +38,25 @@ module Solargraph
|
|
|
33
38
|
end
|
|
34
39
|
process_children region.update(closure: nspin, visibility: :public)
|
|
35
40
|
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# @param comments [String]
|
|
45
|
+
# @return [String, nil]
|
|
46
|
+
def parameters_from_inline_rbs
|
|
47
|
+
source = region.source.code_for(node)
|
|
48
|
+
match = source.match(/[^\n]*?#\s?+\[([^\]]*)/)
|
|
49
|
+
return unless match && match[1]
|
|
50
|
+
|
|
51
|
+
code = match[1].strip
|
|
52
|
+
return if code.empty?
|
|
53
|
+
|
|
54
|
+
"<#{code}>"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def type_from_node
|
|
58
|
+
unpack_name(node.children[1]) if node.children[1]&.type == :const
|
|
59
|
+
end
|
|
36
60
|
end
|
|
37
61
|
end
|
|
38
62
|
end
|
data/lib/solargraph/pin/base.rb
CHANGED
|
@@ -534,11 +534,20 @@ module Solargraph
|
|
|
534
534
|
@directives
|
|
535
535
|
end
|
|
536
536
|
|
|
537
|
-
# @return [::Array<
|
|
537
|
+
# @return [::Array<Solargraph::YardMap::Macro>]
|
|
538
538
|
def macros
|
|
539
539
|
@macros ||= collect_macros
|
|
540
540
|
end
|
|
541
541
|
|
|
542
|
+
def macro_names
|
|
543
|
+
parse_comments unless @macro_names
|
|
544
|
+
@macro_names ||= collect_macro_names
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def macro_names?
|
|
548
|
+
macro_names.any?
|
|
549
|
+
end
|
|
550
|
+
|
|
542
551
|
# Perform a quick check to see if this pin possibly includes YARD
|
|
543
552
|
# directives. This method does not require parsing the comments.
|
|
544
553
|
#
|
|
@@ -569,6 +578,15 @@ module Solargraph
|
|
|
569
578
|
return_type.qualify(api_map, *(closure&.gates || ['']))
|
|
570
579
|
end
|
|
571
580
|
|
|
581
|
+
# @todo Candidate for deprecation (see ApiMap#process_macros)
|
|
582
|
+
def maybe_macros?
|
|
583
|
+
comments.include?('@macro')
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
def macros_names?
|
|
587
|
+
macro_names.any?
|
|
588
|
+
end
|
|
589
|
+
|
|
572
590
|
# Infer the pin's return type via static code analysis.
|
|
573
591
|
#
|
|
574
592
|
# @param api_map [ApiMap]
|
|
@@ -619,6 +637,8 @@ module Solargraph
|
|
|
619
637
|
result = dup
|
|
620
638
|
result.return_type = return_type
|
|
621
639
|
result.proxied = true
|
|
640
|
+
# Macros should have been processed already
|
|
641
|
+
result.macro_names.clear
|
|
622
642
|
result
|
|
623
643
|
end
|
|
624
644
|
|
|
@@ -717,12 +737,14 @@ module Solargraph
|
|
|
717
737
|
if comments.nil? || comments.empty? || comments.strip.end_with?('@overload')
|
|
718
738
|
@docstring = nil
|
|
719
739
|
@directives = []
|
|
740
|
+
@macro_names = []
|
|
720
741
|
else
|
|
721
742
|
# HACK: Pass a dummy code object to the parser for plugins that
|
|
722
743
|
# expect it not to be nil
|
|
723
744
|
parse = Solargraph::Source.parse_docstring(comments)
|
|
724
745
|
@docstring = parse.to_docstring
|
|
725
746
|
@directives = parse.directives
|
|
747
|
+
@macro_names = collect_macro_names
|
|
726
748
|
end
|
|
727
749
|
end
|
|
728
750
|
|
|
@@ -762,11 +784,17 @@ module Solargraph
|
|
|
762
784
|
tag1.types == tag2.types
|
|
763
785
|
end
|
|
764
786
|
|
|
765
|
-
# @return [::Array<
|
|
787
|
+
# @return [::Array<Solargraph::YardMap::Macro>]
|
|
766
788
|
def collect_macros
|
|
767
789
|
return [] unless maybe_directives?
|
|
768
790
|
parse = Solargraph::Source.parse_docstring(comments)
|
|
769
|
-
parse.directives.select { |d| d.tag.tag_name == 'macro' }
|
|
791
|
+
parse.directives.select { |d| d.tag.tag_name == 'macro' }.map do |macro_directive|
|
|
792
|
+
Solargraph::YardMap::Macro.from_directive macro_directive, self
|
|
793
|
+
end
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
def collect_macro_names
|
|
797
|
+
"#{comments}\n".scan(/\s*?@macro +(\S+).*?[\n]/).map { |match| match[0] }
|
|
770
798
|
end
|
|
771
799
|
end
|
|
772
800
|
end
|
|
@@ -161,8 +161,8 @@ module Solargraph
|
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
def typify api_map
|
|
164
|
-
type =
|
|
165
|
-
return type if type.defined?
|
|
164
|
+
type = return_type
|
|
165
|
+
return type.qualify(api_map, *gates) if type.defined?
|
|
166
166
|
if method_name.end_with?('?')
|
|
167
167
|
logger.debug { "Callable#typify(self=#{self}) => Boolean (? suffix)" }
|
|
168
168
|
ComplexType::BOOLEAN
|
|
@@ -72,6 +72,18 @@ module Solargraph
|
|
|
72
72
|
@path ||= name.empty? ? context.namespace : "#{context.namespace}::#{name}"
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
# @yieldparam [Pin::Base]
|
|
76
|
+
# @return [void, Enumerator<Pin::Base>]
|
|
77
|
+
def each_closure &block
|
|
78
|
+
return enum_for(:each_closure) unless block_given?
|
|
79
|
+
|
|
80
|
+
here = closure
|
|
81
|
+
until here.nil?
|
|
82
|
+
yield here
|
|
83
|
+
here = here&.closure
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
75
87
|
protected
|
|
76
88
|
|
|
77
89
|
attr_writer :context
|
|
@@ -143,7 +143,7 @@ module Solargraph
|
|
|
143
143
|
end
|
|
144
144
|
|
|
145
145
|
def return_type
|
|
146
|
-
@return_type ||= ComplexType.new(signatures.map(&:return_type).flat_map(&:items))
|
|
146
|
+
@return_type ||= return_type_from_inline_rbs || ComplexType.new(signatures.map(&:return_type).flat_map(&:items))
|
|
147
147
|
end
|
|
148
148
|
|
|
149
149
|
# @param parameters [::Array<Parameter>]
|
|
@@ -188,18 +188,11 @@ module Solargraph
|
|
|
188
188
|
|
|
189
189
|
# @return [::Array<Signature>]
|
|
190
190
|
def signatures
|
|
191
|
-
@signatures ||=
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
result.concat(overloads.map do |meth|
|
|
197
|
-
generate_signature(meth.parameters, meth.return_type)
|
|
198
|
-
end)
|
|
199
|
-
end
|
|
200
|
-
result.push generate_signature(parameters, @return_type || ComplexType::UNDEFINED) if result.empty?
|
|
201
|
-
result
|
|
202
|
-
end
|
|
191
|
+
@signatures ||= if inline_rbs.empty?
|
|
192
|
+
signatures_from_yard
|
|
193
|
+
else
|
|
194
|
+
signatures_from_inline_rbs
|
|
195
|
+
end
|
|
203
196
|
end
|
|
204
197
|
|
|
205
198
|
# @param return_type [ComplexType]
|
|
@@ -279,7 +272,19 @@ module Solargraph
|
|
|
279
272
|
# @sg-ignore Need to add nil check here
|
|
280
273
|
"Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context.rooted_tags}, return_type=#{return_type.rooted_tags}) - starting"
|
|
281
274
|
end
|
|
282
|
-
decl =
|
|
275
|
+
decl = if macro_names?
|
|
276
|
+
types = macro_names.flat_map do |mac|
|
|
277
|
+
directive = api_map.named_macro(mac)
|
|
278
|
+
next unless directive
|
|
279
|
+
macro = Solargraph::YardMap::Macro.from_directive(directive, self)
|
|
280
|
+
expanded = macro.macro_object.expand([name, *parameter_names])
|
|
281
|
+
docstring = Solargraph::Source.parse_docstring(expanded).to_docstring
|
|
282
|
+
docstring.tags(:return).flat_map(&:types)
|
|
283
|
+
end
|
|
284
|
+
ComplexType.try_parse(*types)
|
|
285
|
+
else
|
|
286
|
+
super
|
|
287
|
+
end
|
|
283
288
|
unless decl.undefined?
|
|
284
289
|
logger.debug do
|
|
285
290
|
"Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context}) => #{decl.rooted_tags.inspect} - decl found"
|
|
@@ -451,7 +456,6 @@ module Solargraph
|
|
|
451
456
|
|
|
452
457
|
attr_writer :block, :signature_help, :documentation, :return_type
|
|
453
458
|
|
|
454
|
-
# @sg-ignore Need to add nil check here
|
|
455
459
|
def dodgy_visibility_source?
|
|
456
460
|
# as of 2025-03-12, the RBS generator used for
|
|
457
461
|
# e.g. activesupport did not understand 'private' markings
|
|
@@ -505,7 +509,8 @@ module Solargraph
|
|
|
505
509
|
#
|
|
506
510
|
# @return [Array<Pin::Signature>]
|
|
507
511
|
def combine_same_type_arity_signatures same_type_arity_signatures
|
|
508
|
-
# @todo Stubbing this method while we debug an infinite loop bug in Ruby 3.x
|
|
512
|
+
# @todo Stubbing this method while we debug an infinite loop bug in Ruby 3.x.
|
|
513
|
+
# The body below is intentionally preserved for when the stub is removed.
|
|
509
514
|
return same_type_arity_signatures
|
|
510
515
|
|
|
511
516
|
# rubocop:disable Lint/UnreachableCode
|
|
@@ -721,6 +726,41 @@ module Solargraph
|
|
|
721
726
|
.join("\n")
|
|
722
727
|
.concat("```\n")
|
|
723
728
|
end
|
|
729
|
+
|
|
730
|
+
# @return [ComplexType, nil]
|
|
731
|
+
def return_type_from_inline_rbs
|
|
732
|
+
return nil if inline_rbs.empty?
|
|
733
|
+
method_type = RBS::Parser.parse_method_type(inline_rbs)
|
|
734
|
+
RbsTranslator.to_complex_type(method_type.type.return_type)
|
|
735
|
+
rescue RBS::ParsingError
|
|
736
|
+
nil
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
# @return [Array<Pin::Signature>]
|
|
740
|
+
def signatures_from_inline_rbs
|
|
741
|
+
method_type = RBS::Parser.parse_method_type(inline_rbs)
|
|
742
|
+
[RbsTranslator.to_signature(method_type, self, parameter_names)]
|
|
743
|
+
rescue RBS::ParsingError
|
|
744
|
+
signatures_from_yard
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
# @return [Array<Pin::Signature>]
|
|
748
|
+
def signatures_from_yard
|
|
749
|
+
top_type = generate_complex_type
|
|
750
|
+
result = []
|
|
751
|
+
result.push generate_signature(parameters, top_type) if top_type.defined?
|
|
752
|
+
result.concat(overloads.map { |meth| generate_signature(meth.parameters, meth.return_type) }) unless overloads.empty?
|
|
753
|
+
result.push generate_signature(parameters, @return_type || ComplexType::UNDEFINED) if result.empty?
|
|
754
|
+
result
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
# @return [String]
|
|
758
|
+
def inline_rbs
|
|
759
|
+
comments.lines
|
|
760
|
+
.select { |line| line.start_with?(': ') }
|
|
761
|
+
.map { |line| line[2..].strip }
|
|
762
|
+
.join("\n")
|
|
763
|
+
end
|
|
724
764
|
end
|
|
725
765
|
end
|
|
726
766
|
end
|