solargraph 0.57.0 → 0.58.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/linting.yml +4 -2
- data/.github/workflows/plugins.yml +61 -27
- data/.github/workflows/rspec.yml +19 -4
- data/.github/workflows/typecheck.yml +2 -2
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +90 -1438
- data/CHANGELOG.md +27 -0
- data/Rakefile +1 -1
- data/bin/solargraph +8 -5
- data/lib/solargraph/api_map/constants.rb +107 -46
- data/lib/solargraph/api_map/index.rb +32 -8
- data/lib/solargraph/api_map/source_to_yard.rb +5 -2
- data/lib/solargraph/api_map/store.rb +22 -12
- data/lib/solargraph/api_map.rb +27 -33
- data/lib/solargraph/complex_type/type_methods.rb +5 -0
- data/lib/solargraph/complex_type/unique_type.rb +12 -5
- data/lib/solargraph/complex_type.rb +19 -2
- data/lib/solargraph/convention/active_support_concern.rb +1 -1
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +1 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -2
- data/lib/solargraph/doc_map.rb +9 -6
- data/lib/solargraph/environ.rb +1 -1
- data/lib/solargraph/equality.rb +1 -0
- data/lib/solargraph/gem_pins.rb +4 -0
- data/lib/solargraph/language_server/host.rb +10 -4
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -2
- data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -1
- data/lib/solargraph/language_server/progress.rb +1 -1
- data/lib/solargraph/language_server/request.rb +3 -1
- data/lib/solargraph/library.rb +3 -3
- data/lib/solargraph/location.rb +1 -0
- data/lib/solargraph/page.rb +0 -1
- data/lib/solargraph/parser/flow_sensitive_typing.rb +1 -1
- data/lib/solargraph/parser/parser_gem/class_methods.rb +2 -12
- data/lib/solargraph/parser/parser_gem/node_methods.rb +1 -14
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +4 -5
- data/lib/solargraph/pin/base.rb +29 -8
- data/lib/solargraph/pin/base_variable.rb +5 -3
- data/lib/solargraph/pin/block.rb +3 -2
- data/lib/solargraph/pin/callable.rb +6 -2
- data/lib/solargraph/pin/closure.rb +3 -7
- data/lib/solargraph/pin/delegated_method.rb +0 -1
- data/lib/solargraph/pin/local_variable.rb +0 -4
- data/lib/solargraph/pin/method.rb +20 -4
- data/lib/solargraph/pin/parameter.rb +6 -2
- data/lib/solargraph/pin/proxy_type.rb +4 -1
- data/lib/solargraph/pin/reference.rb +2 -11
- data/lib/solargraph/pin/search.rb +3 -0
- data/lib/solargraph/pin_cache.rb +5 -5
- data/lib/solargraph/position.rb +1 -0
- data/lib/solargraph/range.rb +4 -0
- data/lib/solargraph/rbs_map/conversions.rb +22 -1
- data/lib/solargraph/rbs_map/core_fills.rb +18 -0
- data/lib/solargraph/rbs_map/core_map.rb +11 -7
- data/lib/solargraph/rbs_map.rb +2 -2
- data/lib/solargraph/shell.rb +82 -1
- data/lib/solargraph/source/chain/call.rb +7 -3
- data/lib/solargraph/source/chain/constant.rb +3 -66
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +1 -1
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain.rb +2 -0
- data/lib/solargraph/source.rb +1 -1
- data/lib/solargraph/source_map/clip.rb +17 -25
- data/lib/solargraph/source_map/mapper.rb +0 -2
- data/lib/solargraph/source_map.rb +8 -3
- data/lib/solargraph/type_checker/rules.rb +23 -9
- data/lib/solargraph/type_checker.rb +133 -71
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +21 -3
- data/lib/solargraph/workspace/require_paths.rb +0 -1
- data/lib/solargraph/workspace.rb +14 -19
- data/lib/solargraph/yard_map/mapper/to_method.rb +2 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/to_method.rb +2 -1
- data/lib/solargraph/yardoc.rb +27 -4
- data/rbs/fills/bundler/0/bundler.rbs +4271 -0
- data/rbs/fills/open3/0/open3.rbs +172 -0
- data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
- data/rbs/fills/rubygems/0/errors.rbs +364 -0
- data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
- data/rbs/fills/rubygems/0/specification.rbs +1753 -0
- data/rbs_collection.yaml +4 -4
- data/sig/shims/ast/0/node.rbs +5 -0
- data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
- data/sig/shims/ast/2.4/ast.rbs +73 -0
- data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
- data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
- data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
- data/solargraph.gemspec +15 -4
- metadata +66 -12
- data/lib/solargraph/parser/node_methods.rb +0 -97
- /data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +0 -0
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
## 0.58.0 - January 1, 2026
|
|
2
|
+
- Faster constant resolution (#1083)
|
|
3
|
+
- [regression] Handle RBS static method aliases (#1094)
|
|
4
|
+
- More type fills and shims (#1005)
|
|
5
|
+
- Fix resolution in blocks in type checker (#890)
|
|
6
|
+
- Annotation fixes for strong typechecking (#1057)
|
|
7
|
+
- Remove dead code (#1077)
|
|
8
|
+
- Fix flakey spec (#1080)
|
|
9
|
+
- Fix bad sexpr generation in op_asgn (#1089)
|
|
10
|
+
- Opt-in for MFA requirement (#730)
|
|
11
|
+
- [regression] Fix resolution issues with namespaces from YARD (#1097)
|
|
12
|
+
- Improve a pin combination case around selfy types (#1024)
|
|
13
|
+
- Rescue reference errors in hosts (#1105)
|
|
14
|
+
- Relax bundler runtime dependency version constraint to support newer versions (#1125)
|
|
15
|
+
- Remove stale Pathname test (#1135)
|
|
16
|
+
- Enable strong type checking in CI (#928)
|
|
17
|
+
- Stale sg-ignore
|
|
18
|
+
- Use rbs 3.9.5 in tests (#1136)
|
|
19
|
+
- Drop broken 'namespaces' method (#1065)
|
|
20
|
+
- Add ActiveRecord example from RBS (#1074)
|
|
21
|
+
- Keep workspace directories as absolute paths (#1076)
|
|
22
|
+
- Handle bad gem_dir from gemspec object (#1079)
|
|
23
|
+
- Test for absolute require paths (#1137)
|
|
24
|
+
- [regression] Fix resolution of ambiguous argument types (#1098)
|
|
25
|
+
- Remove sg-ignore for String#=~ (#1138)
|
|
26
|
+
- Allow levels to be changed for typechecking rules in .solargraph.yml (#1126)
|
|
27
|
+
|
|
1
28
|
## 0.57.0 - September 16, 2025
|
|
2
29
|
- Support ActiveSupport::Concern pattern for class methods (#948)
|
|
3
30
|
- More CI checks (#996)
|
data/Rakefile
CHANGED
|
@@ -9,7 +9,7 @@ task :console do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
desc "Run the type checker"
|
|
12
|
-
task typecheck: [:
|
|
12
|
+
task typecheck: [:typecheck_strong]
|
|
13
13
|
|
|
14
14
|
desc "Run the type checker at typed level - return code issues provable without annotations being correct"
|
|
15
15
|
task :typecheck_typed do
|
data/bin/solargraph
CHANGED
|
@@ -12,15 +12,35 @@ module Solargraph
|
|
|
12
12
|
|
|
13
13
|
# Resolve a name to a fully qualified namespace or constant.
|
|
14
14
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
# `Constants#resolve` finds fully qualified (absolute)
|
|
16
|
+
# namespaces based on relative names and the open gates
|
|
17
|
+
# (namespaces) provided. Names must be runtime-visible (erased)
|
|
18
|
+
# non-literal types, non-duck, non-signature types - e.g.,
|
|
19
|
+
# TrueClass, NilClass, Integer and Hash instead of true, nil,
|
|
20
|
+
# 96, or Hash{String => Symbol}
|
|
21
|
+
#
|
|
22
|
+
# Note: You may want to be using #qualify. Notably, #resolve:
|
|
23
|
+
# - does not handle anything with type parameters
|
|
24
|
+
# - will not gracefully handle nil, self and Boolean
|
|
25
|
+
# - will return a constant name instead of following its assignment
|
|
26
|
+
#
|
|
27
|
+
# @param name [String] Namespace which may relative and not be rooted.
|
|
28
|
+
# @param gates [Array<Array<String>, String>] Namespaces to search while resolving the name
|
|
29
|
+
#
|
|
30
|
+
# @return [String, nil] fully qualified namespace (i.e., is
|
|
31
|
+
# absolute, but will not start with ::)
|
|
18
32
|
def resolve(name, *gates)
|
|
19
33
|
return store.get_path_pins(name[2..]).first&.path if name.start_with?('::')
|
|
20
34
|
|
|
21
35
|
flat = gates.flatten
|
|
22
36
|
flat.push '' if flat.empty?
|
|
23
|
-
cached_resolve[
|
|
37
|
+
if cached_resolve.include? [name, flat]
|
|
38
|
+
cached_result = cached_resolve[[name, flat]]
|
|
39
|
+
# don't recurse
|
|
40
|
+
return nil if cached_result == :in_process
|
|
41
|
+
return cached_result
|
|
42
|
+
end
|
|
43
|
+
resolve_and_cache(name, flat)
|
|
24
44
|
end
|
|
25
45
|
|
|
26
46
|
# Get a fully qualified namespace from a reference pin.
|
|
@@ -28,47 +48,49 @@ module Solargraph
|
|
|
28
48
|
# @param pin [Pin::Reference]
|
|
29
49
|
# @return [String, nil]
|
|
30
50
|
def dereference pin
|
|
31
|
-
|
|
51
|
+
qualify_type(pin.type, *pin.reference_gates)&.tag
|
|
32
52
|
end
|
|
33
53
|
|
|
34
54
|
# Collect a list of all constants defined in the specified gates.
|
|
35
55
|
#
|
|
36
56
|
# @param gates [Array<Array<String>, String>]
|
|
37
|
-
# @return [Array<Pin::
|
|
57
|
+
# @return [Array<Solargraph::Pin::Namespace, Solargraph::Pin::Constant>]
|
|
38
58
|
def collect(*gates)
|
|
39
59
|
flat = gates.flatten
|
|
40
60
|
cached_collect[flat] || collect_and_cache(flat)
|
|
41
61
|
end
|
|
42
62
|
|
|
43
|
-
# Determine fully qualified
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
# the tag.
|
|
63
|
+
# Determine a fully qualified namespace for a given tag
|
|
64
|
+
# referenced from the specified open gates. This method will
|
|
65
|
+
# search in each gate until it finds a match for the name.
|
|
47
66
|
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
# @param tag [String, nil] The namespace to
|
|
52
|
-
# match, complete with generic parameters set to appropriate
|
|
53
|
-
# values if available
|
|
54
|
-
# @param context_tag [String] The fully qualified context in which
|
|
55
|
-
# the tag was referenced; start from here to resolve the name.
|
|
56
|
-
# Should not be prefixed with '::'.
|
|
67
|
+
# @param tag [String, nil] The type to match
|
|
68
|
+
# @param gates [Array<String>]
|
|
57
69
|
# @return [String, nil] fully qualified tag
|
|
58
|
-
def qualify tag,
|
|
59
|
-
return tag if ['Boolean', 'self', nil].include?(tag)
|
|
60
|
-
|
|
70
|
+
def qualify tag, *gates
|
|
61
71
|
type = ComplexType.try_parse(tag)
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
qualify_type(type, *gates)&.tag
|
|
73
|
+
end
|
|
64
74
|
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
# @param type [ComplexType, nil] The type to match
|
|
76
|
+
# @param gates [Array<String>]
|
|
77
|
+
#
|
|
78
|
+
# @return [ComplexType, nil] A new rooted ComplexType
|
|
79
|
+
def qualify_type type, *gates
|
|
80
|
+
return nil if type.nil?
|
|
81
|
+
return type if type.selfy? || type.literal? || type.tag == 'nil' || type.interface? ||
|
|
82
|
+
type.tag == 'Boolean'
|
|
67
83
|
|
|
68
|
-
|
|
84
|
+
gates.push '' unless gates.include?('')
|
|
85
|
+
fqns = resolve(type.rooted_namespace, *gates)
|
|
69
86
|
return unless fqns
|
|
70
|
-
|
|
71
|
-
|
|
87
|
+
pin = store.get_path_pins(fqns).first
|
|
88
|
+
if pin.is_a?(Pin::Constant)
|
|
89
|
+
const = Solargraph::Parser::NodeMethods.unpack_name(pin.assignment)
|
|
90
|
+
return unless const
|
|
91
|
+
fqns = resolve(const, *pin.gates)
|
|
92
|
+
end
|
|
93
|
+
type.recreate(new_name: fqns, make_rooted: true)
|
|
72
94
|
end
|
|
73
95
|
|
|
74
96
|
# @return [void]
|
|
@@ -85,6 +107,7 @@ module Solargraph
|
|
|
85
107
|
# @param gates [Array<String>]
|
|
86
108
|
# @return [String, nil]
|
|
87
109
|
def resolve_and_cache name, gates
|
|
110
|
+
cached_resolve[[name, gates]] = :in_process
|
|
88
111
|
cached_resolve[[name, gates]] = resolve_uncached(name, gates)
|
|
89
112
|
end
|
|
90
113
|
|
|
@@ -92,28 +115,66 @@ module Solargraph
|
|
|
92
115
|
# @param gates [Array<String>]
|
|
93
116
|
# @return [String, nil]
|
|
94
117
|
def resolve_uncached name, gates
|
|
118
|
+
resolved = nil
|
|
119
|
+
base = gates
|
|
95
120
|
parts = name.split('::')
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
121
|
+
first = nil
|
|
122
|
+
parts.each.with_index do |nam, idx|
|
|
123
|
+
resolved, remainder = complex_resolve(nam, base, idx != parts.length - 1)
|
|
124
|
+
first ||= remainder
|
|
125
|
+
if resolved
|
|
126
|
+
base = [resolved]
|
|
127
|
+
else
|
|
128
|
+
return resolve(name, first) unless first.empty?
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
resolved
|
|
102
132
|
end
|
|
103
133
|
|
|
134
|
+
# @todo I'm not sure of a better way to express the return value in YARD.
|
|
135
|
+
# It's a tuple where the first element is a nullable string. Something
|
|
136
|
+
# like `Array(String|nil, Array<String>)` would be more accurate.
|
|
137
|
+
#
|
|
104
138
|
# @param name [String]
|
|
105
139
|
# @param gates [Array<String>]
|
|
140
|
+
# @param internal [Boolean] True if the name is not the last in the namespace
|
|
141
|
+
# @return [Array(Object, Array<String>)]
|
|
142
|
+
def complex_resolve name, gates, internal
|
|
143
|
+
resolved = nil
|
|
144
|
+
gates.each.with_index do |gate, idx|
|
|
145
|
+
resolved = simple_resolve(name, gate, internal)
|
|
146
|
+
return [resolved, gates[(idx + 1)..]] if resolved
|
|
147
|
+
store.get_ancestor_references(gate).each do |ref|
|
|
148
|
+
return ref.name.sub(/^::/, '') if ref.name.end_with?("::#{name}") && ref.name.start_with?('::')
|
|
149
|
+
|
|
150
|
+
mixin = resolve(ref.name, ref.reference_gates)
|
|
151
|
+
next unless mixin
|
|
152
|
+
|
|
153
|
+
resolved = simple_resolve(name, mixin, internal)
|
|
154
|
+
return [resolved, gates[(idx + 1)..]] if resolved
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
[nil, []]
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# @param name [String]
|
|
161
|
+
# @param gate [String]
|
|
162
|
+
# @param internal [Boolean] True if the name is not the last in the namespace
|
|
106
163
|
# @return [String, nil]
|
|
107
|
-
def simple_resolve name,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
164
|
+
def simple_resolve name, gate, internal
|
|
165
|
+
here = "#{gate}::#{name}".sub(/^::/, '').sub(/::$/, '')
|
|
166
|
+
pin = store.get_path_pins(here).first
|
|
167
|
+
if pin.is_a?(Pin::Constant) && internal
|
|
168
|
+
const = Solargraph::Parser::NodeMethods.unpack_name(pin.assignment)
|
|
169
|
+
return unless const
|
|
170
|
+
resolve(const, pin.gates)
|
|
171
|
+
else
|
|
172
|
+
pin&.path
|
|
111
173
|
end
|
|
112
|
-
nil
|
|
113
174
|
end
|
|
114
175
|
|
|
115
176
|
# @param gates [Array<String>]
|
|
116
|
-
# @return [Array<Pin::
|
|
177
|
+
# @return [Array<Solargraph::Pin::Namespace, Solargraph::Pin::Constant>]
|
|
117
178
|
def collect_and_cache gates
|
|
118
179
|
skip = Set.new
|
|
119
180
|
cached_collect[gates] = gates.flat_map do |gate|
|
|
@@ -121,12 +182,12 @@ module Solargraph
|
|
|
121
182
|
end
|
|
122
183
|
end
|
|
123
184
|
|
|
124
|
-
# @return [Hash{Array(
|
|
185
|
+
# @return [Hash{Array(String, Array<String>) => String, :in_process, nil}]
|
|
125
186
|
def cached_resolve
|
|
126
187
|
@cached_resolve ||= {}
|
|
127
188
|
end
|
|
128
189
|
|
|
129
|
-
# @return [Hash{Array<String> => Array<Pin::
|
|
190
|
+
# @return [Hash{Array<String> => Array<Solargraph::Pin::Namespace, Solargraph::Pin::Constant>}]
|
|
130
191
|
def cached_collect
|
|
131
192
|
@cached_collect ||= {}
|
|
132
193
|
end
|
|
@@ -171,7 +232,7 @@ module Solargraph
|
|
|
171
232
|
return fqns if store.namespace_exists?(fqns)
|
|
172
233
|
incs = store.get_includes(roots.join('::'))
|
|
173
234
|
incs.each do |inc|
|
|
174
|
-
foundinc = inner_qualify(name, inc.
|
|
235
|
+
foundinc = inner_qualify(name, inc.type.to_s, skip)
|
|
175
236
|
possibles.push foundinc unless foundinc.nil?
|
|
176
237
|
end
|
|
177
238
|
roots.pop
|
|
@@ -179,7 +240,7 @@ module Solargraph
|
|
|
179
240
|
if possibles.empty?
|
|
180
241
|
incs = store.get_includes('')
|
|
181
242
|
incs.each do |inc|
|
|
182
|
-
foundinc = inner_qualify(name, inc.
|
|
243
|
+
foundinc = inner_qualify(name, inc.type.to_s, skip)
|
|
183
244
|
possibles.push foundinc unless foundinc.nil?
|
|
184
245
|
end
|
|
185
246
|
end
|
|
@@ -191,7 +252,7 @@ module Solargraph
|
|
|
191
252
|
# @param fqns [String]
|
|
192
253
|
# @param visibility [Array<Symbol>]
|
|
193
254
|
# @param skip [Set<String>]
|
|
194
|
-
# @return [Array<Pin::
|
|
255
|
+
# @return [Array<Solargraph::Pin::Namespace, Solargraph::Pin::Constant>]
|
|
195
256
|
def inner_get_constants fqns, visibility, skip
|
|
196
257
|
return [] if fqns.nil? || skip.include?(fqns)
|
|
197
258
|
skip.add fqns
|
|
@@ -15,21 +15,24 @@ module Solargraph
|
|
|
15
15
|
@pins ||= []
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
# @return [Set<String>]
|
|
19
|
-
attr_reader :namespaces
|
|
20
|
-
|
|
21
18
|
# @return [Hash{String => Array<Pin::Namespace>}]
|
|
22
19
|
def namespace_hash
|
|
20
|
+
# @param h [String]
|
|
21
|
+
# @param k [Array<Pin::Namespace>]
|
|
23
22
|
@namespace_hash ||= Hash.new { |h, k| h[k] = [] }
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
# @return [Hash{String => Array<Pin::Base>}]
|
|
27
26
|
def pin_class_hash
|
|
27
|
+
# @param h [String]
|
|
28
|
+
# @param k [Array<Pin::Base>]
|
|
28
29
|
@pin_class_hash ||= Hash.new { |h, k| h[k] = [] }
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
# @return [Hash{String => Array<Pin::Base>}]
|
|
32
33
|
def path_pin_hash
|
|
34
|
+
# @param h [String]
|
|
35
|
+
# @param k [Array<Pin::Base>]
|
|
33
36
|
@path_pin_hash ||= Hash.new { |h, k| h[k] = [] }
|
|
34
37
|
end
|
|
35
38
|
|
|
@@ -45,26 +48,36 @@ module Solargraph
|
|
|
45
48
|
|
|
46
49
|
# @return [Hash{String => Array<String>}]
|
|
47
50
|
def include_references
|
|
51
|
+
# @param h [String]
|
|
52
|
+
# @param k [Array<String>]
|
|
48
53
|
@include_references ||= Hash.new { |h, k| h[k] = [] }
|
|
49
54
|
end
|
|
50
55
|
|
|
51
56
|
# @return [Hash{String => Array<Pin::Reference::Include>}]
|
|
52
57
|
def include_reference_pins
|
|
58
|
+
# @param h [String]
|
|
59
|
+
# @param k [Array<Pin::Reference::Include>]
|
|
53
60
|
@include_reference_pins ||= Hash.new { |h, k| h[k] = [] }
|
|
54
61
|
end
|
|
55
62
|
|
|
56
63
|
# @return [Hash{String => Array<String>}]
|
|
57
64
|
def extend_references
|
|
65
|
+
# @param h [String]
|
|
66
|
+
# @param k [Array<String>]
|
|
58
67
|
@extend_references ||= Hash.new { |h, k| h[k] = [] }
|
|
59
68
|
end
|
|
60
69
|
|
|
61
70
|
# @return [Hash{String => Array<String>}]
|
|
62
71
|
def prepend_references
|
|
72
|
+
# @param h [String]
|
|
73
|
+
# @param k [Array<String>]
|
|
63
74
|
@prepend_references ||= Hash.new { |h, k| h[k] = [] }
|
|
64
75
|
end
|
|
65
76
|
|
|
66
77
|
# @return [Hash{String => Array<String>}]
|
|
67
78
|
def superclass_references
|
|
79
|
+
# @param h [String]
|
|
80
|
+
# @param k [Array<String>]
|
|
68
81
|
@superclass_references ||= Hash.new { |h, k| h[k] = [] }
|
|
69
82
|
end
|
|
70
83
|
|
|
@@ -95,18 +108,25 @@ module Solargraph
|
|
|
95
108
|
end
|
|
96
109
|
|
|
97
110
|
# @param new_pins [Enumerable<Pin::Base>]
|
|
111
|
+
#
|
|
98
112
|
# @return [self]
|
|
99
113
|
def catalog new_pins
|
|
100
114
|
# @type [Hash{Class<generic<T>> => Set<generic<T>>}]
|
|
101
115
|
@pin_select_cache = {}
|
|
102
116
|
pins.concat new_pins
|
|
103
117
|
set = new_pins.to_set
|
|
118
|
+
# @param k [String]
|
|
119
|
+
# @param v [Set<Pin::Base>]
|
|
104
120
|
set.classify(&:class)
|
|
105
|
-
|
|
121
|
+
.map { |k, v| pin_class_hash[k].concat v.to_a }
|
|
122
|
+
# @param k [String]
|
|
123
|
+
# @param v [Set<Pin::Namespace>]
|
|
106
124
|
set.classify(&:namespace)
|
|
107
|
-
|
|
125
|
+
.map { |k, v| namespace_hash[k].concat v.to_a }
|
|
126
|
+
# @param k [String]
|
|
127
|
+
# @param v [Set<Pin::Base>]
|
|
108
128
|
set.classify(&:path)
|
|
109
|
-
|
|
129
|
+
.map { |k, v| path_pin_hash[k].concat v.to_a }
|
|
110
130
|
@namespaces = path_pin_hash.keys.compact.to_set
|
|
111
131
|
map_references Pin::Reference::Include, include_references
|
|
112
132
|
map_references Pin::Reference::Prepend, prepend_references
|
|
@@ -116,10 +136,13 @@ module Solargraph
|
|
|
116
136
|
self
|
|
117
137
|
end
|
|
118
138
|
|
|
119
|
-
# @
|
|
120
|
-
# @param
|
|
139
|
+
# @generic T
|
|
140
|
+
# @param klass [Class<generic<T>>]
|
|
141
|
+
# @param hash [Hash{String => generic<T>}]
|
|
142
|
+
#
|
|
121
143
|
# @return [void]
|
|
122
144
|
def map_references klass, hash
|
|
145
|
+
# @param pin [generic<T>]
|
|
123
146
|
pins_by_class(klass).each do |pin|
|
|
124
147
|
hash[pin.namespace].push pin
|
|
125
148
|
end
|
|
@@ -127,6 +150,7 @@ module Solargraph
|
|
|
127
150
|
|
|
128
151
|
# @return [void]
|
|
129
152
|
def map_overrides
|
|
153
|
+
# @param ovr [Pin::Reference::Override]
|
|
130
154
|
pins_by_class(Pin::Reference::Override).each do |ovr|
|
|
131
155
|
logger.debug { "ApiMap::Index#map_overrides: Looking at override #{ovr} for #{ovr.name}" }
|
|
132
156
|
pins = path_pin_hash[ovr.name]
|
|
@@ -32,11 +32,13 @@ module Solargraph
|
|
|
32
32
|
next
|
|
33
33
|
end
|
|
34
34
|
if pin.type == :class
|
|
35
|
+
# @param obj [YARD::CodeObjects::RootObject]
|
|
35
36
|
code_object_map[pin.path] ||= YARD::CodeObjects::ClassObject.new(root_code_object, pin.path) { |obj|
|
|
36
37
|
next if pin.location.nil? || pin.location.filename.nil?
|
|
37
38
|
obj.add_file(pin.location.filename, pin.location.range.start.line, !pin.comments.empty?)
|
|
38
39
|
}
|
|
39
40
|
else
|
|
41
|
+
# @param obj [YARD::CodeObjects::RootObject]
|
|
40
42
|
code_object_map[pin.path] ||= YARD::CodeObjects::ModuleObject.new(root_code_object, pin.path) { |obj|
|
|
41
43
|
next if pin.location.nil? || pin.location.filename.nil?
|
|
42
44
|
obj.add_file(pin.location.filename, pin.location.range.start.line, !pin.comments.empty?)
|
|
@@ -46,13 +48,13 @@ module Solargraph
|
|
|
46
48
|
store.get_includes(pin.path).each do |ref|
|
|
47
49
|
include_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject)
|
|
48
50
|
unless include_object.nil? || include_object.nil?
|
|
49
|
-
include_object.instance_mixins.push code_object_map[ref.
|
|
51
|
+
include_object.instance_mixins.push code_object_map[ref.type.to_s]
|
|
50
52
|
end
|
|
51
53
|
end
|
|
52
54
|
store.get_extends(pin.path).each do |ref|
|
|
53
55
|
extend_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject)
|
|
54
56
|
next unless extend_object
|
|
55
|
-
code_object = code_object_map[ref.
|
|
57
|
+
code_object = code_object_map[ref.type.to_s]
|
|
56
58
|
next unless code_object
|
|
57
59
|
extend_object.class_mixins.push code_object
|
|
58
60
|
# @todo add spec showing why this next line is necessary
|
|
@@ -65,6 +67,7 @@ module Solargraph
|
|
|
65
67
|
next
|
|
66
68
|
end
|
|
67
69
|
|
|
70
|
+
# @param obj [YARD::CodeObjects::RootObject]
|
|
68
71
|
code_object_map[pin.path] ||= YARD::CodeObjects::MethodObject.new(code_object_at(pin.namespace, YARD::CodeObjects::NamespaceObject), pin.name, pin.scope) { |obj|
|
|
69
72
|
next if pin.location.nil? || pin.location.filename.nil?
|
|
70
73
|
obj.add_file pin.location.filename, pin.location.range.start.line
|
|
@@ -17,7 +17,7 @@ module Solargraph
|
|
|
17
17
|
index.pins
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
# @param pinsets [Array<
|
|
20
|
+
# @param pinsets [Array<Array<Pin::Base>>]
|
|
21
21
|
# - pinsets[0] = core Ruby pins
|
|
22
22
|
# - pinsets[1] = documentation/gem pins
|
|
23
23
|
# - pinsets[2] = convention pins
|
|
@@ -57,9 +57,10 @@ module Solargraph
|
|
|
57
57
|
|
|
58
58
|
# @param fqns [String]
|
|
59
59
|
# @param visibility [Array<Symbol>]
|
|
60
|
-
# @return [Enumerable<Solargraph::Pin::
|
|
60
|
+
# @return [Enumerable<Solargraph::Pin::Namespace, Solargraph::Pin::Constant>]
|
|
61
61
|
def get_constants fqns, visibility = [:public]
|
|
62
62
|
namespace_children(fqns).select { |pin|
|
|
63
|
+
# @sg-ignore flow-sensitive typing not smart enough to handle this case
|
|
63
64
|
!pin.name.empty? && (pin.is_a?(Pin::Namespace) || pin.is_a?(Pin::Constant)) && visibility.include?(pin.visibility)
|
|
64
65
|
}
|
|
65
66
|
end
|
|
@@ -70,6 +71,7 @@ module Solargraph
|
|
|
70
71
|
# @return [Enumerable<Solargraph::Pin::Method>]
|
|
71
72
|
def get_methods fqns, scope: :instance, visibility: [:public]
|
|
72
73
|
all_pins = namespace_children(fqns).select do |pin|
|
|
74
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
73
75
|
pin.is_a?(Pin::Method) && pin.scope == scope && visibility.include?(pin.visibility)
|
|
74
76
|
end
|
|
75
77
|
GemPins.combine_method_pins_by_path(all_pins)
|
|
@@ -97,7 +99,7 @@ module Solargraph
|
|
|
97
99
|
return unless ref
|
|
98
100
|
res = constants.dereference(ref)
|
|
99
101
|
return unless res
|
|
100
|
-
res
|
|
102
|
+
res
|
|
101
103
|
end
|
|
102
104
|
|
|
103
105
|
# @param fqns [String]
|
|
@@ -134,7 +136,8 @@ module Solargraph
|
|
|
134
136
|
end
|
|
135
137
|
|
|
136
138
|
# @param fqns [String]
|
|
137
|
-
#
|
|
139
|
+
#
|
|
140
|
+
# @return [Enumerable<Solargraph::Pin::ClassVariable>]
|
|
138
141
|
def get_class_variables(fqns)
|
|
139
142
|
namespace_children(fqns).select { |pin| pin.is_a?(Pin::ClassVariable)}
|
|
140
143
|
end
|
|
@@ -150,11 +153,6 @@ module Solargraph
|
|
|
150
153
|
fqns_pins(fqns).any?
|
|
151
154
|
end
|
|
152
155
|
|
|
153
|
-
# @return [Set<String>]
|
|
154
|
-
def namespaces
|
|
155
|
-
index.namespaces
|
|
156
|
-
end
|
|
157
|
-
|
|
158
156
|
# @return [Enumerable<Solargraph::Pin::Namespace>]
|
|
159
157
|
def namespace_pins
|
|
160
158
|
pins_by_class(Solargraph::Pin::Namespace)
|
|
@@ -244,7 +242,8 @@ module Solargraph
|
|
|
244
242
|
# Add includes, prepends, and extends
|
|
245
243
|
[get_includes(current), get_prepends(current), get_extends(current)].each do |refs|
|
|
246
244
|
next if refs.nil?
|
|
247
|
-
|
|
245
|
+
# @param ref [String]
|
|
246
|
+
refs.map(&:type).map(&:to_s).each do |ref|
|
|
248
247
|
next if ref.nil? || ref.empty? || visited.include?(ref)
|
|
249
248
|
ancestors << ref
|
|
250
249
|
queue << ref
|
|
@@ -255,6 +254,13 @@ module Solargraph
|
|
|
255
254
|
ancestors.compact.uniq
|
|
256
255
|
end
|
|
257
256
|
|
|
257
|
+
# @param fqns [String]
|
|
258
|
+
#
|
|
259
|
+
# @return [Array<Solargraph::Pin::Reference>]
|
|
260
|
+
def get_ancestor_references(fqns)
|
|
261
|
+
(get_prepends(fqns) + get_includes(fqns) + [get_superclass(fqns)]).compact
|
|
262
|
+
end
|
|
263
|
+
|
|
258
264
|
# @return [Constants]
|
|
259
265
|
def constants
|
|
260
266
|
@constants ||= Constants.new(self)
|
|
@@ -267,8 +273,9 @@ module Solargraph
|
|
|
267
273
|
@indexes.last
|
|
268
274
|
end
|
|
269
275
|
|
|
270
|
-
# @param pinsets [Array<
|
|
271
|
-
#
|
|
276
|
+
# @param pinsets [Array<Array<Pin::Base>>]
|
|
277
|
+
#
|
|
278
|
+
# @return [void]
|
|
272
279
|
def catalog pinsets
|
|
273
280
|
@pinsets = pinsets
|
|
274
281
|
# @type [Array<Index>]
|
|
@@ -287,6 +294,9 @@ module Solargraph
|
|
|
287
294
|
|
|
288
295
|
# @return [Hash{::Array(String, String) => ::Array<Pin::Namespace>}]
|
|
289
296
|
def fqns_pins_map
|
|
297
|
+
# @param h [Hash{::Array(String, String) => ::Array<Pin::Namespace>}]
|
|
298
|
+
# @param base [String]
|
|
299
|
+
# @param name [String]
|
|
290
300
|
@fqns_pins_map ||= Hash.new do |h, (base, name)|
|
|
291
301
|
value = namespace_children(base).select { |pin| pin.name == name && pin.is_a?(Pin::Namespace) }
|
|
292
302
|
h[[base, name]] = value
|