solargraph 0.51.2 → 0.54.2
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 +40 -0
- data/.github/workflows/rspec.yml +1 -3
- data/.github/workflows/typecheck.yml +34 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +127 -5
- data/README.md +13 -16
- data/SPONSORS.md +1 -7
- data/lib/solargraph/api_map/cache.rb +50 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +60 -15
- data/lib/solargraph/api_map.rb +282 -123
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +29 -5
- data/lib/solargraph/complex_type/type_methods.rb +122 -39
- data/lib/solargraph/complex_type/unique_type.rb +310 -76
- data/lib/solargraph/complex_type.rb +166 -44
- data/lib/solargraph/convention.rb +0 -1
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +8 -7
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +187 -0
- data/lib/solargraph/gem_pins.rb +72 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +22 -5
- data/lib/solargraph/language_server/host/message_worker.rb +49 -5
- data/lib/solargraph/language_server/host/sources.rb +8 -65
- data/lib/solargraph/language_server/host.rb +65 -84
- data/lib/solargraph/language_server/message/base.rb +19 -12
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/initialize.rb +19 -2
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document.rb +0 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +135 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/language_server.rb +1 -0
- data/lib/solargraph/library.rb +207 -111
- data/lib/solargraph/location.rb +15 -1
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +4 -0
- data/lib/solargraph/parser/node_methods.rb +47 -7
- data/lib/solargraph/parser/node_processor/base.rb +11 -1
- data/lib/solargraph/parser/node_processor.rb +1 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +62 -43
- data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +8 -6
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +8 -12
- data/lib/solargraph/pin/base.rb +78 -10
- data/lib/solargraph/pin/base_variable.rb +40 -7
- data/lib/solargraph/pin/block.rb +69 -46
- data/lib/solargraph/pin/callable.rb +147 -0
- data/lib/solargraph/pin/closure.rb +23 -3
- data/lib/solargraph/pin/common.rb +6 -6
- data/lib/solargraph/pin/conversions.rb +36 -5
- data/lib/solargraph/pin/delegated_method.rb +6 -2
- data/lib/solargraph/pin/documenting.rb +25 -32
- data/lib/solargraph/pin/instance_variable.rb +6 -2
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +205 -32
- data/lib/solargraph/pin/namespace.rb +20 -7
- data/lib/solargraph/pin/parameter.rb +41 -36
- data/lib/solargraph/pin/proxy_type.rb +1 -1
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +3 -3
- data/lib/solargraph/pin/signature.rb +8 -14
- data/lib/solargraph/pin.rb +4 -2
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +326 -76
- data/lib/solargraph/rbs_map/core_fills.rb +16 -33
- data/lib/solargraph/rbs_map/core_map.rb +3 -13
- data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
- data/lib/solargraph/rbs_map.rb +32 -13
- data/lib/solargraph/shell.rb +95 -72
- data/lib/solargraph/source/chain/array.rb +33 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +152 -69
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +17 -2
- data/lib/solargraph/source/chain/or.rb +2 -2
- data/lib/solargraph/source/chain/z_super.rb +3 -3
- data/lib/solargraph/source/chain.rb +85 -26
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +16 -2
- data/lib/solargraph/source/source_chainer.rb +8 -5
- data/lib/solargraph/source/updater.rb +1 -0
- data/lib/solargraph/source.rb +120 -148
- data/lib/solargraph/source_map/clip.rb +16 -27
- data/lib/solargraph/source_map/data.rb +30 -0
- data/lib/solargraph/source_map/mapper.rb +15 -3
- data/lib/solargraph/source_map.rb +48 -24
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker/rules.rb +6 -1
- data/lib/solargraph/type_checker.rb +150 -39
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +9 -6
- data/lib/solargraph/workspace.rb +30 -3
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
- data/lib/solargraph/yard_map/mapper.rb +1 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +1 -292
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +6 -4
- data/solargraph.gemspec +7 -6
- metadata +71 -82
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/language_server/host/cataloger.rb +0 -56
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -50
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -153
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/rbs_map/core_signs.rb +0 -33
- data/lib/yard-solargraph.rb +0 -33
data/lib/solargraph/api_map.rb
CHANGED
@@ -1,22 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rubygems'
|
4
|
-
require 'set'
|
5
3
|
require 'pathname'
|
6
4
|
require 'yard'
|
7
|
-
require '
|
5
|
+
require 'solargraph/yard_tags'
|
8
6
|
|
9
7
|
module Solargraph
|
10
|
-
# An aggregate provider for information about
|
8
|
+
# An aggregate provider for information about Workspaces, Sources, gems, and
|
11
9
|
# the Ruby core.
|
12
10
|
#
|
13
11
|
class ApiMap
|
14
12
|
autoload :Cache, 'solargraph/api_map/cache'
|
15
13
|
autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
|
16
14
|
autoload :Store, 'solargraph/api_map/store'
|
17
|
-
autoload :BundlerMethods, 'solargraph/api_map/bundler_methods'
|
18
|
-
|
19
|
-
include SourceToYard
|
20
15
|
|
21
16
|
# @return [Array<String>]
|
22
17
|
attr_reader :unresolved_requires
|
@@ -34,6 +29,25 @@ module Solargraph
|
|
34
29
|
index pins
|
35
30
|
end
|
36
31
|
|
32
|
+
#
|
33
|
+
# This is a mutable object, which is cached in the Chain class -
|
34
|
+
# if you add any fields which change the results of calls (not
|
35
|
+
# just caches), please also change `equality_fields` below.
|
36
|
+
#
|
37
|
+
|
38
|
+
def eql?(other)
|
39
|
+
self.class == other.class &&
|
40
|
+
equality_fields == other.equality_fields
|
41
|
+
end
|
42
|
+
|
43
|
+
def ==(other)
|
44
|
+
self.eql?(other)
|
45
|
+
end
|
46
|
+
|
47
|
+
def hash
|
48
|
+
equality_fields.hash
|
49
|
+
end
|
50
|
+
|
37
51
|
# @param pins [Array<Pin::Base>]
|
38
52
|
# @return [self]
|
39
53
|
def index pins
|
@@ -59,34 +73,44 @@ module Solargraph
|
|
59
73
|
# Catalog a bench.
|
60
74
|
#
|
61
75
|
# @param bench [Bench]
|
76
|
+
# @return [self]
|
62
77
|
def catalog bench
|
63
|
-
|
64
|
-
|
78
|
+
old_api_hash = @source_map_hash&.values&.map(&:api_hash)
|
79
|
+
need_to_uncache = (old_api_hash != bench.source_maps.map(&:api_hash))
|
65
80
|
@source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
|
66
|
-
pins = bench.source_maps.
|
67
|
-
|
81
|
+
pins = bench.source_maps.flat_map(&:pins).flatten
|
82
|
+
implicit.clear
|
68
83
|
source_map_hash.each_value do |map|
|
69
84
|
implicit.merge map.environ
|
70
85
|
end
|
71
|
-
external_requires
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
@
|
78
|
-
@
|
79
|
-
|
80
|
-
|
86
|
+
unresolved_requires = (bench.external_requires + implicit.requires + bench.workspace.config.required).to_a.compact.uniq
|
87
|
+
if @unresolved_requires != unresolved_requires || @doc_map&.uncached_gemspecs&.any?
|
88
|
+
@doc_map = DocMap.new(unresolved_requires, [], bench.workspace.rbs_collection_path) # @todo Implement gem preferences
|
89
|
+
@unresolved_requires = unresolved_requires
|
90
|
+
need_to_uncache = true
|
91
|
+
end
|
92
|
+
@store = Store.new(@@core_map.pins + @doc_map.pins + implicit.pins + pins)
|
93
|
+
@cache.clear if need_to_uncache
|
94
|
+
|
95
|
+
@missing_docs = [] # @todo Implement missing docs
|
81
96
|
self
|
82
97
|
end
|
83
98
|
|
84
|
-
def
|
85
|
-
|
99
|
+
# @todo need to model type def statement in chains as a symbol so
|
100
|
+
# that this overload of 'protected' will typecheck @sg-ignore
|
101
|
+
# @sg-ignore
|
102
|
+
protected def equality_fields
|
103
|
+
[self.class, @source_map_hash, implicit, @doc_map, @unresolved_requires, @missing_docs]
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [::Array<Gem::Specification>]
|
107
|
+
def uncached_gemspecs
|
108
|
+
@doc_map&.uncached_gemspecs || []
|
86
109
|
end
|
87
110
|
|
88
|
-
|
89
|
-
|
111
|
+
# @return [Array<Pin::Base>]
|
112
|
+
def core_pins
|
113
|
+
@@core_map.pins
|
90
114
|
end
|
91
115
|
|
92
116
|
# @param name [String]
|
@@ -95,6 +119,7 @@ module Solargraph
|
|
95
119
|
store.named_macros[name]
|
96
120
|
end
|
97
121
|
|
122
|
+
# @return [Set<String>]
|
98
123
|
def required
|
99
124
|
@required ||= Set.new
|
100
125
|
end
|
@@ -120,7 +145,7 @@ module Solargraph
|
|
120
145
|
# @return [SourceMap::Clip]
|
121
146
|
def clip_at filename, position
|
122
147
|
position = Position.normalize(position)
|
123
|
-
|
148
|
+
clip(cursor_at(filename, position))
|
124
149
|
end
|
125
150
|
|
126
151
|
# Create an ApiMap with a workspace in the specified directory.
|
@@ -137,22 +162,33 @@ module Solargraph
|
|
137
162
|
api_map
|
138
163
|
end
|
139
164
|
|
165
|
+
# Create an ApiMap with a workspace in the specified directory and cache
|
166
|
+
# any missing gems.
|
167
|
+
#
|
168
|
+
#
|
169
|
+
# @todo IO::NULL is incorrectly inferred to be a String.
|
170
|
+
# @sg-ignore
|
171
|
+
#
|
172
|
+
# @param directory [String]
|
173
|
+
# @param out [IO] The output stream for messages
|
174
|
+
# @return [ApiMap]
|
175
|
+
def self.load_with_cache directory, out = IO::NULL
|
176
|
+
api_map = load(directory)
|
177
|
+
return api_map if api_map.uncached_gemspecs.empty?
|
178
|
+
|
179
|
+
api_map.uncached_gemspecs.each do |gemspec|
|
180
|
+
out.puts "Caching gem #{gemspec.name} #{gemspec.version}"
|
181
|
+
pins = GemPins.build(gemspec)
|
182
|
+
Solargraph::Cache.save('gems', "#{gemspec.name}-#{gemspec.version}.ser", pins)
|
183
|
+
end
|
184
|
+
load(directory)
|
185
|
+
end
|
186
|
+
|
140
187
|
# @return [Array<Solargraph::Pin::Base>]
|
141
188
|
def pins
|
142
189
|
store.pins
|
143
190
|
end
|
144
191
|
|
145
|
-
def rebindable_method_names
|
146
|
-
@rebindable_method_names ||= begin
|
147
|
-
# result = yard_map.rebindable_method_names
|
148
|
-
result = ['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec', 'define_method'].to_set
|
149
|
-
source_maps.each do |map|
|
150
|
-
result.merge map.rebindable_method_names
|
151
|
-
end
|
152
|
-
result
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
192
|
# An array of pins based on Ruby keywords (`if`, `end`, etc.).
|
157
193
|
#
|
158
194
|
# @return [Enumerable<Solargraph::Pin::Keyword>]
|
@@ -199,22 +235,62 @@ module Solargraph
|
|
199
235
|
result
|
200
236
|
end
|
201
237
|
|
202
|
-
#
|
203
|
-
#
|
238
|
+
# @param namespace [String]
|
239
|
+
# @param context [String]
|
240
|
+
# @return [Array<Pin::Namespace>]
|
241
|
+
def get_namespace_pins namespace, context
|
242
|
+
store.fqns_pins(qualify(namespace, context))
|
243
|
+
end
|
244
|
+
|
245
|
+
# Determine fully qualified tag for a given tag used inside the
|
246
|
+
# definition of another tag ("context"). This method will start
|
247
|
+
# the search in the specified context until it finds a match for
|
248
|
+
# the tag.
|
204
249
|
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
208
|
-
|
209
|
-
|
210
|
-
|
250
|
+
# Does not recurse into qualifying the type parameters, but
|
251
|
+
# returns any which were passed in unchanged.
|
252
|
+
#
|
253
|
+
# @param tag [String, nil] The namespace to
|
254
|
+
# match, complete with generic parameters set to appropriate
|
255
|
+
# values if available
|
256
|
+
# @param context_tag [String] The fully qualified context in which
|
257
|
+
# the tag was referenced; start from here to resolve the name.
|
258
|
+
# Should not be prefixed with '::'.
|
259
|
+
# @return [String, nil] fully qualified tag
|
260
|
+
def qualify tag, context_tag = ''
|
261
|
+
return tag if ['self', nil].include?(tag)
|
262
|
+
|
263
|
+
context_type = ComplexType.parse(context_tag).force_rooted
|
264
|
+
return unless context_type
|
265
|
+
|
266
|
+
type = ComplexType.try_parse(tag)
|
267
|
+
return unless type
|
268
|
+
|
269
|
+
fqns = qualify_namespace(type.rooted_namespace, context_type.namespace)
|
270
|
+
return unless fqns
|
271
|
+
|
272
|
+
fqns + type.substring
|
273
|
+
end
|
274
|
+
|
275
|
+
# Determine fully qualified namespace for a given namespace used
|
276
|
+
# inside the definition of another tag ("context"). This method
|
277
|
+
# will start the search in the specified context until it finds a
|
278
|
+
# match for the namespace.
|
279
|
+
#
|
280
|
+
# @param namespace [String, nil] The namespace to
|
281
|
+
# match
|
282
|
+
# @param context_namespace [String] The context namespace in which the
|
283
|
+
# tag was referenced; start from here to resolve the name
|
284
|
+
# @return [String, nil] fully qualified namespace
|
285
|
+
def qualify_namespace(namespace, context_namespace = '')
|
286
|
+
cached = cache.get_qualified_namespace(namespace, context_namespace)
|
211
287
|
return cached.clone unless cached.nil?
|
212
288
|
result = if namespace.start_with?('::')
|
213
289
|
inner_qualify(namespace[2..-1], '', Set.new)
|
214
290
|
else
|
215
|
-
inner_qualify(namespace,
|
291
|
+
inner_qualify(namespace, context_namespace, Set.new)
|
216
292
|
end
|
217
|
-
cache.set_qualified_namespace(namespace,
|
293
|
+
cache.set_qualified_namespace(namespace, context_namespace, result)
|
218
294
|
result
|
219
295
|
end
|
220
296
|
|
@@ -240,50 +316,82 @@ module Solargraph
|
|
240
316
|
# Get an array of class variable pins for a namespace.
|
241
317
|
#
|
242
318
|
# @param namespace [String] A fully qualified namespace
|
243
|
-
# @return [
|
319
|
+
# @return [Enumerable<Solargraph::Pin::ClassVariable>]
|
244
320
|
def get_class_variable_pins(namespace)
|
245
321
|
prefer_non_nil_variables(store.get_class_variables(namespace))
|
246
322
|
end
|
247
323
|
|
248
|
-
# @return [
|
324
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
249
325
|
def get_symbols
|
250
326
|
store.get_symbols
|
251
327
|
end
|
252
328
|
|
253
|
-
# @return [
|
329
|
+
# @return [Enumerable<Solargraph::Pin::GlobalVariable>]
|
254
330
|
def get_global_variable_pins
|
255
331
|
store.pins_by_class(Pin::GlobalVariable)
|
256
332
|
end
|
257
333
|
|
334
|
+
# @return [Enumerable<Solargraph::Pin::Block>]
|
335
|
+
def get_block_pins
|
336
|
+
store.pins_by_class(Pin::Block)
|
337
|
+
end
|
338
|
+
|
258
339
|
# Get an array of methods available in a particular context.
|
259
340
|
#
|
260
|
-
# @param
|
341
|
+
# @param rooted_tag [String] The fully qualified namespace to search for methods
|
261
342
|
# @param scope [Symbol] :class or :instance
|
262
343
|
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
263
344
|
# @param deep [Boolean] True to include superclasses, mixins, etc.
|
264
345
|
# @return [Array<Solargraph::Pin::Method>]
|
265
|
-
def get_methods
|
266
|
-
|
346
|
+
def get_methods rooted_tag, scope: :instance, visibility: [:public], deep: true
|
347
|
+
rooted_type = ComplexType.try_parse(rooted_tag)
|
348
|
+
fqns = rooted_type.namespace
|
349
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
350
|
+
cached = cache.get_methods(rooted_tag, scope, visibility, deep)
|
267
351
|
return cached.clone unless cached.nil?
|
268
352
|
result = []
|
269
353
|
skip = Set.new
|
270
|
-
if
|
354
|
+
if rooted_tag == ''
|
271
355
|
# @todo Implement domains
|
272
356
|
implicit.domains.each do |domain|
|
273
357
|
type = ComplexType.try_parse(domain)
|
274
358
|
next if type.undefined?
|
275
359
|
result.concat inner_get_methods(type.name, type.scope, visibility, deep, skip)
|
276
360
|
end
|
277
|
-
result.concat inner_get_methods(
|
278
|
-
result.concat inner_get_methods(
|
361
|
+
result.concat inner_get_methods(rooted_tag, :class, visibility, deep, skip)
|
362
|
+
result.concat inner_get_methods(rooted_tag, :instance, visibility, deep, skip)
|
279
363
|
result.concat inner_get_methods('Kernel', :instance, visibility, deep, skip)
|
280
364
|
else
|
281
|
-
result.concat inner_get_methods(
|
365
|
+
result.concat inner_get_methods(rooted_tag, scope, visibility, deep, skip)
|
366
|
+
unless %w[Class Class<Class>].include?(rooted_tag)
|
367
|
+
result.map! do |pin|
|
368
|
+
next pin unless pin.path == 'Class#new'
|
369
|
+
init_pin = get_method_stack(rooted_tag, 'initialize').first
|
370
|
+
next pin unless init_pin
|
371
|
+
|
372
|
+
type = ComplexType.try_parse(ComplexType.try_parse(rooted_tag).namespace)
|
373
|
+
Pin::Method.new(
|
374
|
+
name: 'new',
|
375
|
+
scope: :class,
|
376
|
+
location: init_pin.location,
|
377
|
+
parameters: init_pin.parameters,
|
378
|
+
signatures: init_pin.signatures.map { |sig| sig.proxy(type) },
|
379
|
+
return_type: type,
|
380
|
+
comments: init_pin.comments,
|
381
|
+
closure: init_pin.closure
|
382
|
+
# @todo Hack to force TypeChecker#internal_or_core?
|
383
|
+
).tap { |pin| pin.source = :rbs }
|
384
|
+
end
|
385
|
+
end
|
282
386
|
result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
|
387
|
+
result.concat inner_get_methods('Module', scope, visibility, deep, skip) if scope == :module
|
283
388
|
end
|
284
|
-
|
285
|
-
|
286
|
-
|
389
|
+
result = resolve_method_aliases(result, visibility)
|
390
|
+
if namespace_pin && rooted_tag != rooted_type.name
|
391
|
+
result = result.map { |method_pin| method_pin.resolve_generics(namespace_pin, rooted_type) }
|
392
|
+
end
|
393
|
+
cache.set_methods(rooted_tag, scope, visibility, deep, result)
|
394
|
+
result
|
287
395
|
end
|
288
396
|
|
289
397
|
# Get an array of method pins for a complex type.
|
@@ -320,27 +428,32 @@ module Solargraph
|
|
320
428
|
visibility.push :protected
|
321
429
|
visibility.push :private if internal
|
322
430
|
end
|
323
|
-
result.merge get_methods(type.
|
431
|
+
result.merge get_methods(type.tag, scope: type.scope, visibility: visibility)
|
324
432
|
end
|
325
433
|
end
|
326
434
|
end
|
327
435
|
result.to_a
|
328
436
|
end
|
329
437
|
|
330
|
-
# Get a stack of method pins for a method name in a
|
331
|
-
# of the pins corresponds to
|
332
|
-
# first.
|
438
|
+
# Get a stack of method pins for a method name in a potentially
|
439
|
+
# parameterized namespace. The order of the pins corresponds to
|
440
|
+
# the ancestry chain, with highest precedence first.
|
333
441
|
#
|
334
442
|
# @example
|
335
443
|
# api_map.get_method_stack('Subclass', 'method_name')
|
336
444
|
# #=> [ <Subclass#method_name pin>, <Superclass#method_name pin> ]
|
337
445
|
#
|
338
|
-
# @param
|
339
|
-
# @param name [String]
|
446
|
+
# @param rooted_tag [String] Parameterized namespace, fully qualified
|
447
|
+
# @param name [String] Method name to look up
|
340
448
|
# @param scope [Symbol] :instance or :class
|
341
449
|
# @return [Array<Solargraph::Pin::Method>]
|
342
|
-
def get_method_stack
|
343
|
-
|
450
|
+
def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private, :protected, :public], preserve_generics: false
|
451
|
+
rooted_type = ComplexType.parse(rooted_tag)
|
452
|
+
fqns = rooted_type.namespace
|
453
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
454
|
+
methods = get_methods(rooted_tag, scope: scope, visibility: visibility).select { |p| p.name == name }
|
455
|
+
methods = erase_generics(namespace_pin, rooted_type, methods) unless preserve_generics
|
456
|
+
methods
|
344
457
|
end
|
345
458
|
|
346
459
|
# Get an array of all suggestions that match the specified path.
|
@@ -348,7 +461,7 @@ module Solargraph
|
|
348
461
|
# @deprecated Use #get_path_pins instead.
|
349
462
|
#
|
350
463
|
# @param path [String] The path to find
|
351
|
-
# @return [
|
464
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
352
465
|
def get_path_suggestions path
|
353
466
|
return [] if path.nil?
|
354
467
|
resolve_method_aliases store.get_path_pins(path)
|
@@ -357,7 +470,7 @@ module Solargraph
|
|
357
470
|
# Get an array of pins that match the specified path.
|
358
471
|
#
|
359
472
|
# @param path [String]
|
360
|
-
# @return [
|
473
|
+
# @return [Enumerable<Pin::Base>]
|
361
474
|
def get_path_pins path
|
362
475
|
get_path_suggestions(path)
|
363
476
|
end
|
@@ -370,15 +483,9 @@ module Solargraph
|
|
370
483
|
# @param query [String] The text to match
|
371
484
|
# @return [Array<String>]
|
372
485
|
def search query
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
if (found.empty? || (query.include?('.') || query.include?('#')) || !(k.include?('.') || k.include?('#'))) &&
|
377
|
-
k.downcase.include?(query.downcase)
|
378
|
-
found.push k
|
379
|
-
end
|
380
|
-
end
|
381
|
-
found
|
486
|
+
pins.map(&:path)
|
487
|
+
.compact
|
488
|
+
.select { |path| path.downcase.include?(query.downcase) }
|
382
489
|
end
|
383
490
|
|
384
491
|
# Get YARD documentation for the specified path.
|
@@ -386,13 +493,13 @@ module Solargraph
|
|
386
493
|
# @example
|
387
494
|
# api_map.document('String#split')
|
388
495
|
#
|
496
|
+
# @todo This method is likely superfluous. Calling get_path_pins directly
|
497
|
+
# should be sufficient.
|
498
|
+
#
|
389
499
|
# @param path [String] The path to find
|
390
|
-
# @return [
|
500
|
+
# @return [Enumerable<Pin::Base>]
|
391
501
|
def document path
|
392
|
-
|
393
|
-
docs = []
|
394
|
-
docs.push code_object_at(path) unless code_object_at(path).nil?
|
395
|
-
docs
|
502
|
+
get_path_pins(path)
|
396
503
|
end
|
397
504
|
|
398
505
|
# Get an array of all symbols in the workspace that match the query.
|
@@ -418,6 +525,7 @@ module Solargraph
|
|
418
525
|
# @return [SourceMap::Clip]
|
419
526
|
def clip cursor
|
420
527
|
raise FileNotFoundError, "ApiMap did not catalog #{cursor.filename}" unless source_map_hash.key?(cursor.filename)
|
528
|
+
|
421
529
|
SourceMap::Clip.new(self, cursor)
|
422
530
|
end
|
423
531
|
|
@@ -469,13 +577,15 @@ module Solargraph
|
|
469
577
|
false
|
470
578
|
end
|
471
579
|
|
472
|
-
# Check if the host class includes the specified module
|
580
|
+
# Check if the host class includes the specified module, ignoring
|
581
|
+
# type parameters used.
|
582
|
+
#
|
583
|
+
# @param host_ns [String] The class namesapce (no type parameters)
|
584
|
+
# @param module_ns [String] The module namespace (no type parameters)
|
473
585
|
#
|
474
|
-
# @param host [String] The class
|
475
|
-
# @param mod [String] The module
|
476
586
|
# @return [Boolean]
|
477
|
-
def type_include?(
|
478
|
-
store.get_includes(
|
587
|
+
def type_include?(host_ns, module_ns)
|
588
|
+
store.get_includes(host_ns).map { |inc_tag| ComplexType.parse(inc_tag).name }.include?(module_ns)
|
479
589
|
end
|
480
590
|
|
481
591
|
private
|
@@ -485,14 +595,6 @@ module Solargraph
|
|
485
595
|
# @return [Hash{String => SourceMap}]
|
486
596
|
attr_reader :source_map_hash
|
487
597
|
|
488
|
-
# @param library [String]
|
489
|
-
# @return [RbsMap]
|
490
|
-
def load_rbs_map library
|
491
|
-
# map = RbsMap.load(library)
|
492
|
-
# return map if map.resolved?
|
493
|
-
RbsMap::StdlibMap.load(library)
|
494
|
-
end
|
495
|
-
|
496
598
|
# @return [ApiMap::Store]
|
497
599
|
def store
|
498
600
|
@store ||= Store.new
|
@@ -501,15 +603,20 @@ module Solargraph
|
|
501
603
|
# @return [Solargraph::ApiMap::Cache]
|
502
604
|
attr_reader :cache
|
503
605
|
|
504
|
-
# @param
|
606
|
+
# @param rooted_tag [String] A fully qualified namespace, with
|
607
|
+
# generic parameter values if applicable
|
505
608
|
# @param scope [Symbol] :class or :instance
|
506
609
|
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
507
610
|
# @param deep [Boolean]
|
508
611
|
# @param skip [Set<String>]
|
509
612
|
# @param no_core [Boolean] Skip core classes if true
|
510
613
|
# @return [Array<Pin::Base>]
|
511
|
-
def inner_get_methods
|
512
|
-
|
614
|
+
def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false
|
615
|
+
rooted_type = ComplexType.parse(rooted_tag).force_rooted
|
616
|
+
fqns = rooted_type.namespace
|
617
|
+
fqns_generic_params = rooted_type.all_params
|
618
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
619
|
+
return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module)$/
|
513
620
|
reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
|
514
621
|
return [] if skip.include?(reqstr)
|
515
622
|
skip.add reqstr
|
@@ -520,12 +627,25 @@ module Solargraph
|
|
520
627
|
result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
|
521
628
|
end
|
522
629
|
end
|
523
|
-
|
630
|
+
# Store#get_methods doesn't know about full tags, just
|
631
|
+
# namespaces; resolving the generics in the method pins is this
|
632
|
+
# class' responsibility
|
633
|
+
methods = store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
|
634
|
+
result.concat methods
|
524
635
|
if deep
|
525
636
|
if scope == :instance
|
526
|
-
store.get_includes(fqns).reverse.each do |
|
527
|
-
|
528
|
-
|
637
|
+
store.get_includes(fqns).reverse.each do |include_tag|
|
638
|
+
rooted_include_tag = qualify(include_tag, rooted_tag)
|
639
|
+
# Ensure the types returned by the included methods are
|
640
|
+
# relative to the generics passed to the include. e.g.,
|
641
|
+
# Foo<String> might include Enumerable<String>
|
642
|
+
#
|
643
|
+
# @todo perform the same translation in the other areas
|
644
|
+
# here after adding a spec and handling things correctly
|
645
|
+
# in ApiMap::Store and RbsMap::Conversions
|
646
|
+
resolved_include_type = ComplexType.parse(rooted_include_tag).force_rooted.resolve_generics(namespace_pin, rooted_type)
|
647
|
+
methods = inner_get_methods(resolved_include_type.tag, scope, visibility, deep, skip, true)
|
648
|
+
result.concat methods
|
529
649
|
end
|
530
650
|
fqsc = qualify_superclass(fqns)
|
531
651
|
unless fqsc.nil?
|
@@ -584,11 +704,13 @@ module Solargraph
|
|
584
704
|
|
585
705
|
# @param namespace [String]
|
586
706
|
# @param context [String]
|
587
|
-
# @return [String]
|
707
|
+
# @return [String, nil]
|
588
708
|
def qualify_lower namespace, context
|
589
709
|
qualify namespace, context.split('::')[0..-2].join('::')
|
590
710
|
end
|
591
711
|
|
712
|
+
# @param fqsub [String]
|
713
|
+
# @return [String, nil]
|
592
714
|
def qualify_superclass fqsub
|
593
715
|
sup = store.get_superclass(fqsub)
|
594
716
|
return nil if sup.nil?
|
@@ -598,11 +720,12 @@ module Solargraph
|
|
598
720
|
qualify(sup, parts.join('::'))
|
599
721
|
end
|
600
722
|
|
601
|
-
# @param name [String]
|
602
|
-
# @param root [String]
|
603
|
-
# @param skip [Set<String>]
|
604
|
-
# @return [String, nil]
|
723
|
+
# @param name [String] Namespace to fully qualify
|
724
|
+
# @param root [String] The context to search
|
725
|
+
# @param skip [Set<String>] Contexts already searched
|
726
|
+
# @return [String, nil] Fully qualified ("rooted") namespace
|
605
727
|
def inner_qualify name, root, skip
|
728
|
+
return name if name == ComplexType::GENERIC_TAG_NAME
|
606
729
|
return nil if name.nil?
|
607
730
|
return nil if skip.include?(root)
|
608
731
|
skip.add root
|
@@ -652,8 +775,8 @@ module Solargraph
|
|
652
775
|
|
653
776
|
# Sort an array of pins to put nil or undefined variables last.
|
654
777
|
#
|
655
|
-
# @param pins [
|
656
|
-
# @return [
|
778
|
+
# @param pins [Enumerable<Solargraph::Pin::Base>]
|
779
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
657
780
|
def prefer_non_nil_variables pins
|
658
781
|
result = []
|
659
782
|
nil_pins = []
|
@@ -667,38 +790,74 @@ module Solargraph
|
|
667
790
|
result + nil_pins
|
668
791
|
end
|
669
792
|
|
670
|
-
# @param pins [
|
671
|
-
# @param visibility [
|
793
|
+
# @param pins [Enumerable<Pin::Base>]
|
794
|
+
# @param visibility [Enumerable<Symbol>]
|
672
795
|
# @return [Array<Pin::Base>]
|
673
796
|
def resolve_method_aliases pins, visibility = [:public, :private, :protected]
|
674
|
-
|
675
|
-
pins.each do |pin|
|
797
|
+
pins.map do |pin|
|
676
798
|
resolved = resolve_method_alias(pin)
|
677
|
-
next if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
678
|
-
|
679
|
-
end
|
680
|
-
result
|
799
|
+
next pin if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
800
|
+
resolved
|
801
|
+
end.compact
|
681
802
|
end
|
682
803
|
|
683
804
|
# @param pin [Pin::MethodAlias, Pin::Base]
|
684
805
|
# @return [Pin::Method]
|
685
806
|
def resolve_method_alias pin
|
686
|
-
return pin
|
807
|
+
return pin unless pin.is_a?(Pin::MethodAlias)
|
808
|
+
return nil if @method_alias_stack.include?(pin.path)
|
687
809
|
@method_alias_stack.push pin.path
|
688
|
-
origin = get_method_stack(pin.full_context.
|
810
|
+
origin = get_method_stack(pin.full_context.tag, pin.original, scope: pin.scope).first
|
689
811
|
@method_alias_stack.pop
|
690
|
-
return
|
812
|
+
return nil if origin.nil?
|
691
813
|
args = {
|
692
814
|
location: pin.location,
|
693
815
|
closure: pin.closure,
|
694
816
|
name: pin.name,
|
695
817
|
comments: origin.comments,
|
696
818
|
scope: origin.scope,
|
819
|
+
# context: pin.context,
|
697
820
|
visibility: origin.visibility,
|
698
821
|
signatures: origin.signatures,
|
699
|
-
attribute: origin.attribute
|
822
|
+
attribute: origin.attribute?,
|
823
|
+
generics: origin.generics,
|
824
|
+
return_type: origin.return_type,
|
700
825
|
}
|
701
826
|
Pin::Method.new **args
|
702
827
|
end
|
828
|
+
|
829
|
+
include Logging
|
830
|
+
|
831
|
+
private
|
832
|
+
|
833
|
+
# @param namespace_pin [Pin::Namespace]
|
834
|
+
# @param rooted_type [ComplexType]
|
835
|
+
# @param pins [Enumerable<Pin::Base>]
|
836
|
+
# @return [Array<Pin::Base>]
|
837
|
+
def erase_generics(namespace_pin, rooted_type, pins)
|
838
|
+
return pins unless should_erase_generics_when_done?(namespace_pin, rooted_type)
|
839
|
+
|
840
|
+
logger.debug("Erasing generics on namespace_pin=#{namespace_pin} / rooted_type=#{rooted_type}")
|
841
|
+
pins.map do |method_pin|
|
842
|
+
method_pin.erase_generics(namespace_pin.generics)
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
# @param namespace_pin [Pin::Namespace]
|
847
|
+
# @param rooted_type [ComplexType]
|
848
|
+
def should_erase_generics_when_done?(namespace_pin, rooted_type)
|
849
|
+
has_generics?(namespace_pin) && !can_resolve_generics?(namespace_pin, rooted_type)
|
850
|
+
end
|
851
|
+
|
852
|
+
# @param namespace_pin [Pin::Namespace]
|
853
|
+
def has_generics?(namespace_pin)
|
854
|
+
namespace_pin && !namespace_pin.generics.empty?
|
855
|
+
end
|
856
|
+
|
857
|
+
# @param namespace_pin [Pin::Namespace]
|
858
|
+
# @param rooted_type [ComplexType]
|
859
|
+
def can_resolve_generics?(namespace_pin, rooted_type)
|
860
|
+
has_generics?(namespace_pin) && !rooted_type.all_params.empty?
|
861
|
+
end
|
703
862
|
end
|
704
863
|
end
|
data/lib/solargraph/bench.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'set'
|
4
3
|
|
5
4
|
module Solargraph
|
6
5
|
# A container of source maps and workspace data to be cataloged in an ApiMap.
|
@@ -21,7 +20,9 @@ module Solargraph
|
|
21
20
|
def initialize source_maps: [], workspace: Workspace.new, external_requires: []
|
22
21
|
@source_maps = source_maps.to_set
|
23
22
|
@workspace = workspace
|
24
|
-
@external_requires = external_requires.
|
23
|
+
@external_requires = external_requires.reject { |path| workspace.would_require?(path) }
|
24
|
+
.compact
|
25
|
+
.to_set
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|