solargraph 0.54.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 +127 -0
- data/.github/workflows/plugins.yml +184 -6
- data/.github/workflows/rspec.yml +55 -5
- data/.github/workflows/typecheck.yml +8 -3
- data/.gitignore +7 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +1279 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +171 -0
- data/README.md +20 -6
- data/Rakefile +125 -13
- data/bin/solargraph +8 -5
- data/lib/solargraph/api_map/cache.rb +13 -3
- data/lib/solargraph/api_map/constants.rb +279 -0
- data/lib/solargraph/api_map/index.rb +193 -0
- data/lib/solargraph/api_map/source_to_yard.rb +13 -4
- data/lib/solargraph/api_map/store.rb +207 -132
- data/lib/solargraph/api_map.rb +394 -261
- data/lib/solargraph/bench.rb +18 -1
- data/lib/solargraph/complex_type/type_methods.rb +29 -12
- data/lib/solargraph/complex_type/unique_type.rb +205 -26
- data/lib/solargraph/complex_type.rb +126 -26
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +20 -3
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
- data/lib/solargraph/convention/data_definition.rb +105 -0
- data/lib/solargraph/convention/gemspec.rb +3 -2
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
- data/lib/solargraph/convention/struct_definition.rb +164 -0
- data/lib/solargraph/convention.rb +36 -4
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/doc_map.rb +316 -64
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/equality.rb +34 -0
- data/lib/solargraph/gem_pins.rb +64 -38
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +54 -5
- data/lib/solargraph/language_server/host.rb +36 -18
- data/lib/solargraph/language_server/message/base.rb +20 -12
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- data/lib/solargraph/language_server/message/initialize.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +5 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +23 -2
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +4 -3
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +27 -2
- data/lib/solargraph/language_server/request.rb +4 -1
- data/lib/solargraph/library.rb +83 -73
- data/lib/solargraph/location.rb +45 -1
- data/lib/solargraph/logging.rb +12 -2
- data/lib/solargraph/page.rb +3 -0
- data/lib/solargraph/parser/comment_ripper.rb +20 -7
- data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +26 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +10 -18
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_methods.rb +10 -19
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +26 -20
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +14 -2
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +16 -6
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +64 -32
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
- data/lib/solargraph/parser/region.rb +4 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +3 -5
- data/lib/solargraph/pin/base.rb +417 -42
- data/lib/solargraph/pin/base_variable.rb +21 -12
- data/lib/solargraph/pin/block.rb +9 -26
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +231 -0
- data/lib/solargraph/pin/closure.rb +30 -10
- data/lib/solargraph/pin/common.rb +12 -7
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/conversions.rb +3 -2
- data/lib/solargraph/pin/delegated_method.rb +20 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/instance_variable.rb +2 -2
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +15 -7
- data/lib/solargraph/pin/method.rb +241 -70
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/namespace.rb +21 -13
- data/lib/solargraph/pin/parameter.rb +94 -32
- data/lib/solargraph/pin/proxy_type.rb +17 -7
- data/lib/solargraph/pin/reference/override.rb +24 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +17 -0
- data/lib/solargraph/pin/search.rb +6 -1
- data/lib/solargraph/pin/signature.rb +39 -121
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +8 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +8 -2
- data/lib/solargraph/pin_cache.rb +245 -0
- data/lib/solargraph/position.rb +19 -0
- data/lib/solargraph/range.rb +23 -4
- data/lib/solargraph/rbs_map/conversions.rb +315 -99
- data/lib/solargraph/rbs_map/core_fills.rb +50 -16
- data/lib/solargraph/rbs_map/core_map.rb +41 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +87 -16
- data/lib/solargraph/shell.rb +117 -17
- data/lib/solargraph/source/chain/array.rb +13 -8
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +135 -66
- data/lib/solargraph/source/chain/constant.rb +3 -66
- data/lib/solargraph/source/chain/hash.rb +9 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +7 -2
- data/lib/solargraph/source/chain/link.rb +38 -6
- data/lib/solargraph/source/chain/literal.rb +27 -2
- data/lib/solargraph/source/chain/or.rb +2 -2
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +140 -63
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +4 -4
- data/lib/solargraph/source/source_chainer.rb +3 -3
- data/lib/solargraph/source.rb +110 -89
- data/lib/solargraph/source_map/clip.rb +22 -28
- data/lib/solargraph/source_map/data.rb +34 -0
- data/lib/solargraph/source_map/mapper.rb +11 -7
- data/lib/solargraph/source_map.rb +50 -43
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +35 -8
- data/lib/solargraph/type_checker.rb +331 -189
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +25 -5
- data/lib/solargraph/workspace/require_paths.rb +97 -0
- data/lib/solargraph/workspace.rb +53 -72
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +55 -19
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +11 -7
- data/lib/solargraph/yard_map/mapper.rb +5 -3
- data/lib/solargraph/yard_map/to_method.rb +6 -3
- data/lib/solargraph/yardoc.rb +45 -10
- data/lib/solargraph.rb +35 -1
- 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/fills/tuple/tuple.rbs +149 -0
- data/rbs_collection.yaml +19 -0
- 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/builders/default.rbs +195 -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/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
- data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
- data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
- data/solargraph.gemspec +32 -10
- metadata +237 -37
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/cache.rb +0 -77
- data/lib/solargraph/parser/node_methods.rb +0 -83
data/lib/solargraph/api_map.rb
CHANGED
|
@@ -5,13 +5,15 @@ require 'yard'
|
|
|
5
5
|
require 'solargraph/yard_tags'
|
|
6
6
|
|
|
7
7
|
module Solargraph
|
|
8
|
-
# An aggregate provider for information about
|
|
8
|
+
# An aggregate provider for information about Workspaces, Sources, gems, and
|
|
9
9
|
# the Ruby core.
|
|
10
10
|
#
|
|
11
11
|
class ApiMap
|
|
12
12
|
autoload :Cache, 'solargraph/api_map/cache'
|
|
13
13
|
autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
|
|
14
14
|
autoload :Store, 'solargraph/api_map/store'
|
|
15
|
+
autoload :Index, 'solargraph/api_map/index'
|
|
16
|
+
autoload :Constants, 'solargraph/api_map/constants'
|
|
15
17
|
|
|
16
18
|
# @return [Array<String>]
|
|
17
19
|
attr_reader :unresolved_requires
|
|
@@ -25,7 +27,6 @@ module Solargraph
|
|
|
25
27
|
def initialize pins: []
|
|
26
28
|
@source_map_hash = {}
|
|
27
29
|
@cache = Cache.new
|
|
28
|
-
@method_alias_stack = []
|
|
29
30
|
index pins
|
|
30
31
|
end
|
|
31
32
|
|
|
@@ -35,11 +36,14 @@ module Solargraph
|
|
|
35
36
|
# just caches), please also change `equality_fields` below.
|
|
36
37
|
#
|
|
37
38
|
|
|
39
|
+
# @param other [Object]
|
|
38
40
|
def eql?(other)
|
|
39
41
|
self.class == other.class &&
|
|
42
|
+
# @sg-ignore Flow sensitive typing needs to handle self.class == other.class
|
|
40
43
|
equality_fields == other.equality_fields
|
|
41
44
|
end
|
|
42
45
|
|
|
46
|
+
# @param other [Object]
|
|
43
47
|
def ==(other)
|
|
44
48
|
self.eql?(other)
|
|
45
49
|
end
|
|
@@ -48,25 +52,35 @@ module Solargraph
|
|
|
48
52
|
equality_fields.hash
|
|
49
53
|
end
|
|
50
54
|
|
|
55
|
+
def to_s
|
|
56
|
+
self.class.to_s
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# avoid enormous dump
|
|
60
|
+
def inspect
|
|
61
|
+
to_s
|
|
62
|
+
end
|
|
63
|
+
|
|
51
64
|
# @param pins [Array<Pin::Base>]
|
|
52
65
|
# @return [self]
|
|
53
66
|
def index pins
|
|
54
67
|
# @todo This implementation is incomplete. It should probably create a
|
|
55
68
|
# Bench.
|
|
56
69
|
@source_map_hash = {}
|
|
57
|
-
|
|
70
|
+
conventions_environ.clear
|
|
58
71
|
cache.clear
|
|
59
|
-
|
|
72
|
+
store.update @@core_map.pins, pins
|
|
60
73
|
self
|
|
61
74
|
end
|
|
62
75
|
|
|
63
76
|
# Map a single source.
|
|
64
77
|
#
|
|
65
78
|
# @param source [Source]
|
|
79
|
+
# @param live [Boolean] True for live source map (active editor file)
|
|
66
80
|
# @return [self]
|
|
67
|
-
def map source
|
|
81
|
+
def map source, live: false
|
|
68
82
|
map = Solargraph::SourceMap.map(source)
|
|
69
|
-
catalog Bench.new(source_maps: [map])
|
|
83
|
+
catalog Bench.new(source_maps: [map], live_map: live ? map : nil)
|
|
70
84
|
self
|
|
71
85
|
end
|
|
72
86
|
|
|
@@ -75,29 +89,37 @@ module Solargraph
|
|
|
75
89
|
# @param bench [Bench]
|
|
76
90
|
# @return [self]
|
|
77
91
|
def catalog bench
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
implicit.clear
|
|
92
|
+
@source_map_hash = bench.source_map_hash
|
|
93
|
+
iced_pins = bench.icebox.flat_map(&:pins)
|
|
94
|
+
live_pins = bench.live_map&.all_pins || []
|
|
95
|
+
conventions_environ.clear
|
|
83
96
|
source_map_hash.each_value do |map|
|
|
84
|
-
|
|
97
|
+
conventions_environ.merge map.conventions_environ
|
|
85
98
|
end
|
|
86
|
-
unresolved_requires = (bench.external_requires +
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
99
|
+
unresolved_requires = (bench.external_requires + conventions_environ.requires + bench.workspace.config.required).to_a.compact.uniq
|
|
100
|
+
recreate_docmap = @unresolved_requires != unresolved_requires ||
|
|
101
|
+
@doc_map&.uncached_yard_gemspecs&.any? ||
|
|
102
|
+
@doc_map&.uncached_rbs_collection_gemspecs&.any? ||
|
|
103
|
+
@doc_map&.rbs_collection_path != bench.workspace.rbs_collection_path
|
|
104
|
+
if recreate_docmap
|
|
105
|
+
@doc_map = DocMap.new(unresolved_requires, [], bench.workspace) # @todo Implement gem preferences
|
|
106
|
+
@unresolved_requires = @doc_map.unresolved_requires
|
|
91
107
|
end
|
|
92
|
-
@
|
|
93
|
-
@cache.clear if need_to_uncache
|
|
94
|
-
|
|
108
|
+
@cache.clear if store.update(@@core_map.pins, @doc_map.pins, conventions_environ.pins, iced_pins, live_pins)
|
|
95
109
|
@missing_docs = [] # @todo Implement missing docs
|
|
96
110
|
self
|
|
97
111
|
end
|
|
98
112
|
|
|
113
|
+
# @todo need to model type def statement in chains as a symbol so
|
|
114
|
+
# that this overload of 'protected' will typecheck @sg-ignore
|
|
115
|
+
# @sg-ignore
|
|
99
116
|
protected def equality_fields
|
|
100
|
-
[self.class, @source_map_hash,
|
|
117
|
+
[self.class, @source_map_hash, conventions_environ, @doc_map, @unresolved_requires]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @return [DocMap]
|
|
121
|
+
def doc_map
|
|
122
|
+
@doc_map ||= DocMap.new([], [])
|
|
101
123
|
end
|
|
102
124
|
|
|
103
125
|
# @return [::Array<Gem::Specification>]
|
|
@@ -105,7 +127,17 @@ module Solargraph
|
|
|
105
127
|
@doc_map&.uncached_gemspecs || []
|
|
106
128
|
end
|
|
107
129
|
|
|
108
|
-
# @return [Array<
|
|
130
|
+
# @return [::Array<Gem::Specification>]
|
|
131
|
+
def uncached_rbs_collection_gemspecs
|
|
132
|
+
@doc_map.uncached_rbs_collection_gemspecs
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# @return [::Array<Gem::Specification>]
|
|
136
|
+
def uncached_yard_gemspecs
|
|
137
|
+
@doc_map.uncached_yard_gemspecs
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# @return [Enumerable<Pin::Base>]
|
|
109
141
|
def core_pins
|
|
110
142
|
@@core_map.pins
|
|
111
143
|
end
|
|
@@ -122,8 +154,8 @@ module Solargraph
|
|
|
122
154
|
end
|
|
123
155
|
|
|
124
156
|
# @return [Environ]
|
|
125
|
-
def
|
|
126
|
-
@
|
|
157
|
+
def conventions_environ
|
|
158
|
+
@conventions_environ ||= Environ.new
|
|
127
159
|
end
|
|
128
160
|
|
|
129
161
|
# @param filename [String]
|
|
@@ -148,6 +180,7 @@ module Solargraph
|
|
|
148
180
|
# Create an ApiMap with a workspace in the specified directory.
|
|
149
181
|
#
|
|
150
182
|
# @param directory [String]
|
|
183
|
+
#
|
|
151
184
|
# @return [ApiMap]
|
|
152
185
|
def self.load directory
|
|
153
186
|
api_map = new
|
|
@@ -159,31 +192,46 @@ module Solargraph
|
|
|
159
192
|
api_map
|
|
160
193
|
end
|
|
161
194
|
|
|
195
|
+
# @param out [IO, nil]
|
|
196
|
+
# @return [void]
|
|
197
|
+
def cache_all!(out)
|
|
198
|
+
@doc_map.cache_all!(out)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# @param gemspec [Gem::Specification]
|
|
202
|
+
# @param rebuild [Boolean]
|
|
203
|
+
# @param out [IO, nil]
|
|
204
|
+
# @return [void]
|
|
205
|
+
def cache_gem(gemspec, rebuild: false, out: nil)
|
|
206
|
+
@doc_map.cache(gemspec, rebuild: rebuild, out: out)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
class << self
|
|
210
|
+
include Logging
|
|
211
|
+
end
|
|
212
|
+
|
|
162
213
|
# Create an ApiMap with a workspace in the specified directory and cache
|
|
163
214
|
# any missing gems.
|
|
164
215
|
#
|
|
165
216
|
#
|
|
166
|
-
# @todo IO::NULL is incorrectly inferred to be a String.
|
|
167
|
-
# @sg-ignore
|
|
168
|
-
#
|
|
169
217
|
# @param directory [String]
|
|
170
218
|
# @param out [IO] The output stream for messages
|
|
219
|
+
#
|
|
171
220
|
# @return [ApiMap]
|
|
172
|
-
def self.load_with_cache directory, out
|
|
221
|
+
def self.load_with_cache directory, out
|
|
173
222
|
api_map = load(directory)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
out.puts "Caching gem #{gemspec.name} #{gemspec.version}"
|
|
178
|
-
pins = GemPins.build(gemspec)
|
|
179
|
-
Solargraph::Cache.save('gems', "#{gemspec.name}-#{gemspec.version}.ser", pins)
|
|
223
|
+
if api_map.uncached_gemspecs.empty?
|
|
224
|
+
logger.info { "All gems cached for #{directory}" }
|
|
225
|
+
return api_map
|
|
180
226
|
end
|
|
227
|
+
|
|
228
|
+
api_map.cache_all!(out)
|
|
181
229
|
load(directory)
|
|
182
230
|
end
|
|
183
231
|
|
|
184
232
|
# @return [Array<Solargraph::Pin::Base>]
|
|
185
233
|
def pins
|
|
186
|
-
store.pins
|
|
234
|
+
store.pins.clone.freeze
|
|
187
235
|
end
|
|
188
236
|
|
|
189
237
|
# An array of pins based on Ruby keywords (`if`, `end`, etc.).
|
|
@@ -193,13 +241,6 @@ module Solargraph
|
|
|
193
241
|
store.pins_by_class(Pin::Keyword)
|
|
194
242
|
end
|
|
195
243
|
|
|
196
|
-
# An array of namespace names defined in the ApiMap.
|
|
197
|
-
#
|
|
198
|
-
# @return [Set<String>]
|
|
199
|
-
def namespaces
|
|
200
|
-
store.namespaces
|
|
201
|
-
end
|
|
202
|
-
|
|
203
244
|
# True if the namespace exists.
|
|
204
245
|
#
|
|
205
246
|
# @param name [String] The namespace to match
|
|
@@ -214,22 +255,16 @@ module Solargraph
|
|
|
214
255
|
#
|
|
215
256
|
# @param namespace [String] The namespace
|
|
216
257
|
# @param contexts [Array<String>] The contexts
|
|
217
|
-
# @return [Array<Solargraph::Pin::
|
|
258
|
+
# @return [Array<Solargraph::Pin::Constant, Solargraph::Pin::Namespace>]
|
|
218
259
|
def get_constants namespace, *contexts
|
|
219
260
|
namespace ||= ''
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
visibility = [:public]
|
|
228
|
-
visibility.push :private if fqns == context
|
|
229
|
-
result.concat inner_get_constants(fqns, visibility, skip)
|
|
230
|
-
end
|
|
231
|
-
cache.set_constants(namespace, contexts, result)
|
|
232
|
-
result
|
|
261
|
+
gates = contexts.clone
|
|
262
|
+
gates.push '' if contexts.empty? && namespace.empty?
|
|
263
|
+
gates.push namespace unless namespace.empty?
|
|
264
|
+
store.constants
|
|
265
|
+
.collect(gates)
|
|
266
|
+
.select { |pin| namespace.empty? || contexts.empty? || pin.namespace == namespace }
|
|
267
|
+
.select { |pin| pin.visibility == :public || pin.namespace == namespace }
|
|
233
268
|
end
|
|
234
269
|
|
|
235
270
|
# @param namespace [String]
|
|
@@ -250,43 +285,41 @@ module Solargraph
|
|
|
250
285
|
# @param tag [String, nil] The namespace to
|
|
251
286
|
# match, complete with generic parameters set to appropriate
|
|
252
287
|
# values if available
|
|
253
|
-
# @param
|
|
254
|
-
# referenced; start from here to resolve the name
|
|
288
|
+
# @param gates [Array<String>] The fully qualified context in which
|
|
289
|
+
# the tag was referenced; start from here to resolve the name.
|
|
290
|
+
# Should not be prefixed with '::'.
|
|
255
291
|
# @return [String, nil] fully qualified tag
|
|
256
|
-
def qualify tag,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
return unless context_type
|
|
292
|
+
def qualify tag, *gates
|
|
293
|
+
store.constants.qualify(tag, *gates)
|
|
294
|
+
end
|
|
260
295
|
|
|
261
|
-
|
|
262
|
-
|
|
296
|
+
# @see Store::Constants#resolve
|
|
297
|
+
#
|
|
298
|
+
# @param name [String]
|
|
299
|
+
# @param gates [Array<String, Array<String>>]
|
|
300
|
+
# @return [String, nil]
|
|
301
|
+
def resolve name, *gates
|
|
302
|
+
store.constants.resolve(name, *gates)
|
|
303
|
+
end
|
|
263
304
|
|
|
264
|
-
|
|
265
|
-
|
|
305
|
+
# Get a fully qualified namespace from a reference pin.
|
|
306
|
+
#
|
|
307
|
+
# @param pin [Pin::Reference]
|
|
308
|
+
# @return [String, nil]
|
|
309
|
+
def dereference(pin)
|
|
310
|
+
store.constants.dereference(pin)
|
|
311
|
+
end
|
|
266
312
|
|
|
267
|
-
|
|
313
|
+
# @param fqns [String]
|
|
314
|
+
# @return [Array<Pin::Reference::Extend>]
|
|
315
|
+
def get_extends(fqns)
|
|
316
|
+
store.get_extends(fqns)
|
|
268
317
|
end
|
|
269
318
|
|
|
270
|
-
#
|
|
271
|
-
#
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
#
|
|
275
|
-
# @param namespace [String, nil] The namespace to
|
|
276
|
-
# match
|
|
277
|
-
# @param context_namespace [String] The context namespace in which the
|
|
278
|
-
# tag was referenced; start from here to resolve the name
|
|
279
|
-
# @return [String, nil] fully qualified namespace
|
|
280
|
-
def qualify_namespace(namespace, context_namespace = '')
|
|
281
|
-
cached = cache.get_qualified_namespace(namespace, context_namespace)
|
|
282
|
-
return cached.clone unless cached.nil?
|
|
283
|
-
result = if namespace.start_with?('::')
|
|
284
|
-
inner_qualify(namespace[2..-1], '', Set.new)
|
|
285
|
-
else
|
|
286
|
-
inner_qualify(namespace, context_namespace, Set.new)
|
|
287
|
-
end
|
|
288
|
-
cache.set_qualified_namespace(namespace, context_namespace, result)
|
|
289
|
-
result
|
|
319
|
+
# @param fqns [String]
|
|
320
|
+
# @return [Array<Pin::Reference::Include>]
|
|
321
|
+
def get_includes(fqns)
|
|
322
|
+
store.get_includes(fqns)
|
|
290
323
|
end
|
|
291
324
|
|
|
292
325
|
# Get an array of instance variable pins defined in specified namespace
|
|
@@ -299,15 +332,20 @@ module Solargraph
|
|
|
299
332
|
result = []
|
|
300
333
|
used = [namespace]
|
|
301
334
|
result.concat store.get_instance_variables(namespace, scope)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
result.concat store.get_instance_variables(
|
|
306
|
-
sc = qualify_lower(store.get_superclass(sc), sc)
|
|
335
|
+
sc_fqns = namespace
|
|
336
|
+
while (sc = store.get_superclass(sc_fqns))
|
|
337
|
+
sc_fqns = store.constants.dereference(sc)
|
|
338
|
+
result.concat store.get_instance_variables(sc_fqns, scope)
|
|
307
339
|
end
|
|
308
340
|
result
|
|
309
341
|
end
|
|
310
342
|
|
|
343
|
+
# @sg-ignore Missing @return tag for Solargraph::ApiMap#visible_pins
|
|
344
|
+
# @see Solargraph::Parser::FlowSensitiveTyping#visible_pins
|
|
345
|
+
def visible_pins(*args, **kwargs, &blk)
|
|
346
|
+
Solargraph::Parser::FlowSensitiveTyping.visible_pins(*args, **kwargs, &blk)
|
|
347
|
+
end
|
|
348
|
+
|
|
311
349
|
# Get an array of class variable pins for a namespace.
|
|
312
350
|
#
|
|
313
351
|
# @param namespace [String] A fully qualified namespace
|
|
@@ -326,6 +364,11 @@ module Solargraph
|
|
|
326
364
|
store.pins_by_class(Pin::GlobalVariable)
|
|
327
365
|
end
|
|
328
366
|
|
|
367
|
+
# @return [Enumerable<Solargraph::Pin::Block>]
|
|
368
|
+
def get_block_pins
|
|
369
|
+
store.pins_by_class(Pin::Block)
|
|
370
|
+
end
|
|
371
|
+
|
|
329
372
|
# Get an array of methods available in a particular context.
|
|
330
373
|
#
|
|
331
374
|
# @param rooted_tag [String] The fully qualified namespace to search for methods
|
|
@@ -334,13 +377,22 @@ module Solargraph
|
|
|
334
377
|
# @param deep [Boolean] True to include superclasses, mixins, etc.
|
|
335
378
|
# @return [Array<Solargraph::Pin::Method>]
|
|
336
379
|
def get_methods rooted_tag, scope: :instance, visibility: [:public], deep: true
|
|
380
|
+
if rooted_tag.start_with? 'Array('
|
|
381
|
+
# Array() are really tuples - use our fill, as the RBS repo
|
|
382
|
+
# does not give us definitions for it
|
|
383
|
+
rooted_tag = "Solargraph::Fills::Tuple(#{rooted_tag[6..-2]})"
|
|
384
|
+
end
|
|
385
|
+
rooted_type = ComplexType.try_parse(rooted_tag)
|
|
386
|
+
fqns = rooted_type.namespace
|
|
387
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
337
388
|
cached = cache.get_methods(rooted_tag, scope, visibility, deep)
|
|
338
389
|
return cached.clone unless cached.nil?
|
|
390
|
+
# @type [Array<Solargraph::Pin::Method>]
|
|
339
391
|
result = []
|
|
340
392
|
skip = Set.new
|
|
341
393
|
if rooted_tag == ''
|
|
342
394
|
# @todo Implement domains
|
|
343
|
-
|
|
395
|
+
conventions_environ.domains.each do |domain|
|
|
344
396
|
type = ComplexType.try_parse(domain)
|
|
345
397
|
next if type.undefined?
|
|
346
398
|
result.concat inner_get_methods(type.name, type.scope, visibility, deep, skip)
|
|
@@ -356,26 +408,47 @@ module Solargraph
|
|
|
356
408
|
init_pin = get_method_stack(rooted_tag, 'initialize').first
|
|
357
409
|
next pin unless init_pin
|
|
358
410
|
|
|
359
|
-
type = ComplexType
|
|
360
|
-
Pin::Method.new(
|
|
411
|
+
type = ComplexType::SELF
|
|
412
|
+
new_pin = Pin::Method.new(
|
|
361
413
|
name: 'new',
|
|
362
414
|
scope: :class,
|
|
363
415
|
location: init_pin.location,
|
|
364
|
-
parameters: init_pin.parameters,
|
|
365
|
-
signatures: init_pin.signatures.map { |sig| sig.proxy(type) },
|
|
366
416
|
return_type: type,
|
|
367
417
|
comments: init_pin.comments,
|
|
368
|
-
closure: init_pin.closure
|
|
369
|
-
|
|
370
|
-
|
|
418
|
+
closure: init_pin.closure,
|
|
419
|
+
source: init_pin.source,
|
|
420
|
+
type_location: init_pin.type_location,
|
|
421
|
+
)
|
|
422
|
+
new_pin.parameters = init_pin.parameters.map do |init_param|
|
|
423
|
+
param = init_param.clone
|
|
424
|
+
param.closure = new_pin
|
|
425
|
+
param.reset_generated!
|
|
426
|
+
param
|
|
427
|
+
end.freeze
|
|
428
|
+
new_pin.signatures = init_pin.signatures.map do |init_sig|
|
|
429
|
+
sig = init_sig.proxy(type)
|
|
430
|
+
sig.parameters = init_sig.parameters.map do |param|
|
|
431
|
+
param = param.clone
|
|
432
|
+
param.closure = new_pin
|
|
433
|
+
param.reset_generated!
|
|
434
|
+
param
|
|
435
|
+
end.freeze
|
|
436
|
+
sig.closure = new_pin
|
|
437
|
+
sig.reset_generated!
|
|
438
|
+
sig
|
|
439
|
+
end.freeze
|
|
440
|
+
new_pin
|
|
371
441
|
end
|
|
372
442
|
end
|
|
373
443
|
result.concat inner_get_methods('Kernel', :instance, [:public], deep, skip) if visibility.include?(:private)
|
|
374
444
|
result.concat inner_get_methods('Module', scope, visibility, deep, skip) if scope == :module
|
|
375
445
|
end
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
446
|
+
result = resolve_method_aliases(result, visibility)
|
|
447
|
+
if namespace_pin && rooted_tag != rooted_type.name
|
|
448
|
+
result = result.map { |method_pin| method_pin.resolve_generics(namespace_pin, rooted_type) }
|
|
449
|
+
end
|
|
450
|
+
cache.set_methods(rooted_tag, scope, visibility, deep, result)
|
|
451
|
+
result
|
|
379
452
|
end
|
|
380
453
|
|
|
381
454
|
# Get an array of method pins for a complex type.
|
|
@@ -403,7 +476,7 @@ module Solargraph
|
|
|
403
476
|
result = Set.new
|
|
404
477
|
complex_type.each do |type|
|
|
405
478
|
if type.duck_type?
|
|
406
|
-
result.add Pin::DuckMethod.new(name: type.to_s[1..-1])
|
|
479
|
+
result.add Pin::DuckMethod.new(name: type.to_s[1..-1], source: :api_map)
|
|
407
480
|
result.merge get_methods('Object')
|
|
408
481
|
else
|
|
409
482
|
unless type.nil? || type.name == 'void'
|
|
@@ -430,9 +503,27 @@ module Solargraph
|
|
|
430
503
|
# @param rooted_tag [String] Parameterized namespace, fully qualified
|
|
431
504
|
# @param name [String] Method name to look up
|
|
432
505
|
# @param scope [Symbol] :instance or :class
|
|
506
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
|
507
|
+
# @param preserve_generics [Boolean] True to preserve any
|
|
508
|
+
# unresolved generic parameters, false to erase them
|
|
433
509
|
# @return [Array<Solargraph::Pin::Method>]
|
|
434
|
-
def get_method_stack rooted_tag, name, scope: :instance
|
|
435
|
-
|
|
510
|
+
def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private, :protected, :public], preserve_generics: false
|
|
511
|
+
rooted_type = ComplexType.parse(rooted_tag)
|
|
512
|
+
fqns = rooted_type.namespace
|
|
513
|
+
namespace_pin = store.get_path_pins(fqns).first
|
|
514
|
+
methods = if namespace_pin.is_a?(Pin::Constant)
|
|
515
|
+
type = namespace_pin.infer(self)
|
|
516
|
+
if type.defined?
|
|
517
|
+
namespace_pin = store.get_path_pins(type.namespace).first
|
|
518
|
+
get_methods(type.namespace, scope: scope, visibility: visibility).select { |p| p.name == name }
|
|
519
|
+
else
|
|
520
|
+
[]
|
|
521
|
+
end
|
|
522
|
+
else
|
|
523
|
+
get_methods(rooted_tag, scope: scope, visibility: visibility).select { |p| p.name == name }
|
|
524
|
+
end
|
|
525
|
+
methods = erase_generics(namespace_pin, rooted_type, methods) unless preserve_generics
|
|
526
|
+
methods
|
|
436
527
|
end
|
|
437
528
|
|
|
438
529
|
# Get an array of all suggestions that match the specified path.
|
|
@@ -440,7 +531,7 @@ module Solargraph
|
|
|
440
531
|
# @deprecated Use #get_path_pins instead.
|
|
441
532
|
#
|
|
442
533
|
# @param path [String] The path to find
|
|
443
|
-
# @return [
|
|
534
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
444
535
|
def get_path_suggestions path
|
|
445
536
|
return [] if path.nil?
|
|
446
537
|
resolve_method_aliases store.get_path_pins(path)
|
|
@@ -449,7 +540,7 @@ module Solargraph
|
|
|
449
540
|
# Get an array of pins that match the specified path.
|
|
450
541
|
#
|
|
451
542
|
# @param path [String]
|
|
452
|
-
# @return [
|
|
543
|
+
# @return [Array<Pin::Base>]
|
|
453
544
|
def get_path_pins path
|
|
454
545
|
get_path_suggestions(path)
|
|
455
546
|
end
|
|
@@ -467,13 +558,8 @@ module Solargraph
|
|
|
467
558
|
.select { |path| path.downcase.include?(query.downcase) }
|
|
468
559
|
end
|
|
469
560
|
|
|
470
|
-
#
|
|
471
|
-
#
|
|
472
|
-
# @example
|
|
473
|
-
# api_map.document('String#split')
|
|
474
|
-
#
|
|
475
|
-
# @todo This method is likely superfluous. Calling get_path_pins directly
|
|
476
|
-
# should be sufficient.
|
|
561
|
+
# @deprecated This method is likely superfluous. Calling #get_path_pins
|
|
562
|
+
# directly should be sufficient.
|
|
477
563
|
#
|
|
478
564
|
# @param path [String] The path to find
|
|
479
565
|
# @return [Enumerable<Pin::Base>]
|
|
@@ -545,13 +631,22 @@ module Solargraph
|
|
|
545
631
|
# @param sub [String] The subclass
|
|
546
632
|
# @return [Boolean]
|
|
547
633
|
def super_and_sub?(sup, sub)
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
634
|
+
sup = ComplexType.try_parse(sup)
|
|
635
|
+
sub = ComplexType.try_parse(sub)
|
|
636
|
+
# @todo If two literals are different values of the same type, it would
|
|
637
|
+
# make more sense for super_and_sub? to return true, but there are a
|
|
638
|
+
# few callers that currently expect this to be false.
|
|
639
|
+
return false if sup.literal? && sub.literal? && sup.to_s != sub.to_s
|
|
640
|
+
sup = sup.simplify_literals.to_s
|
|
641
|
+
sub = sub.simplify_literals.to_s
|
|
642
|
+
return true if sup == sub
|
|
643
|
+
sc_fqns = sub
|
|
644
|
+
while (sc = store.get_superclass(sc_fqns))
|
|
645
|
+
sc_new = store.constants.dereference(sc)
|
|
646
|
+
# Cyclical inheritance is invalid
|
|
647
|
+
return false if sc_new == sc_fqns
|
|
648
|
+
sc_fqns = sc_new
|
|
649
|
+
return true if sc_fqns == sup
|
|
555
650
|
end
|
|
556
651
|
false
|
|
557
652
|
end
|
|
@@ -564,7 +659,56 @@ module Solargraph
|
|
|
564
659
|
#
|
|
565
660
|
# @return [Boolean]
|
|
566
661
|
def type_include?(host_ns, module_ns)
|
|
567
|
-
store.get_includes(host_ns).map { |inc_tag|
|
|
662
|
+
store.get_includes(host_ns).map { |inc_tag| inc_tag.type.name }.include?(module_ns)
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
# @param pins [Enumerable<Pin::Base>]
|
|
666
|
+
# @param visibility [Enumerable<Symbol>]
|
|
667
|
+
# @return [Array<Pin::Base>]
|
|
668
|
+
def resolve_method_aliases pins, visibility = [:public, :private, :protected]
|
|
669
|
+
with_resolved_aliases = pins.map do |pin|
|
|
670
|
+
next pin unless pin.is_a?(Pin::MethodAlias)
|
|
671
|
+
resolved = resolve_method_alias(pin)
|
|
672
|
+
next nil if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility)
|
|
673
|
+
resolved
|
|
674
|
+
end.compact
|
|
675
|
+
logger.debug { "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}" }
|
|
676
|
+
GemPins.combine_method_pins_by_path(with_resolved_aliases)
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
# @param fq_reference_tag [String] A fully qualified whose method should be pulled in
|
|
680
|
+
# @param namespace_pin [Pin::Base] Namespace pin for the rooted_type
|
|
681
|
+
# parameter - used to pull generics information
|
|
682
|
+
# @param type [ComplexType] The type which is having its
|
|
683
|
+
# methods supplemented from fq_reference_tag
|
|
684
|
+
# @param scope [Symbol] :class or :instance
|
|
685
|
+
# @param visibility [Array<Symbol>] :public, :protected, and/or :private
|
|
686
|
+
# @param deep [Boolean]
|
|
687
|
+
# @param skip [Set<String>]
|
|
688
|
+
# @param no_core [Boolean] Skip core classes if true
|
|
689
|
+
# @return [Array<Pin::Base>]
|
|
690
|
+
def inner_get_methods_from_reference(fq_reference_tag, namespace_pin, type, scope, visibility, deep, skip, no_core)
|
|
691
|
+
logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) starting" }
|
|
692
|
+
|
|
693
|
+
# Ensure the types returned by the methods in the referenced
|
|
694
|
+
# type are relative to the generic values passed in the
|
|
695
|
+
# reference. e.g., Foo<String> might include Enumerable<String>
|
|
696
|
+
#
|
|
697
|
+
# @todo perform the same translation in the other areas
|
|
698
|
+
# here after adding a spec and handling things correctly
|
|
699
|
+
# in ApiMap::Store and RbsMap::Conversions for each
|
|
700
|
+
resolved_reference_type = ComplexType.parse(fq_reference_tag).force_rooted.resolve_generics(namespace_pin, type)
|
|
701
|
+
# @todo Can inner_get_methods be cached? Lots of lookups of base types going on.
|
|
702
|
+
methods = inner_get_methods(resolved_reference_type.tag, scope, visibility, deep, skip, no_core)
|
|
703
|
+
if namespace_pin && !resolved_reference_type.all_params.empty?
|
|
704
|
+
reference_pin = store.get_path_pins(resolved_reference_type.name).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
705
|
+
# logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) - resolving generics with #{reference_pin.generics}, #{resolved_reference_type.rooted_tags}" }
|
|
706
|
+
methods = methods.map do |method_pin|
|
|
707
|
+
method_pin.resolve_generics(reference_pin, resolved_reference_type)
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
# logger.debug { "ApiMap#add_methods_from_reference(type=#{type}) - resolved_reference_type: #{resolved_reference_type} for type=#{type}: #{methods.map(&:name)}" }
|
|
711
|
+
methods
|
|
568
712
|
end
|
|
569
713
|
|
|
570
714
|
private
|
|
@@ -591,60 +735,55 @@ module Solargraph
|
|
|
591
735
|
# @param no_core [Boolean] Skip core classes if true
|
|
592
736
|
# @return [Array<Pin::Base>]
|
|
593
737
|
def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false
|
|
594
|
-
rooted_type = ComplexType.parse(rooted_tag)
|
|
738
|
+
rooted_type = ComplexType.parse(rooted_tag).force_rooted
|
|
595
739
|
fqns = rooted_type.namespace
|
|
596
740
|
fqns_generic_params = rooted_type.all_params
|
|
741
|
+
namespace_pin = store.get_path_pins(fqns).select { |p| p.is_a?(Pin::Namespace) }.first
|
|
597
742
|
return [] if no_core && fqns =~ /^(Object|BasicObject|Class|Module)$/
|
|
598
743
|
reqstr = "#{fqns}|#{scope}|#{visibility.sort}|#{deep}"
|
|
599
744
|
return [] if skip.include?(reqstr)
|
|
600
745
|
skip.add reqstr
|
|
601
746
|
result = []
|
|
747
|
+
environ = Convention.for_object(self, rooted_tag, scope, visibility, deep, skip, no_core)
|
|
748
|
+
# ensure we start out with any immediate methods in this
|
|
749
|
+
# namespace so we roughly match the same ordering of get_methods
|
|
750
|
+
# and obey the 'deep' instruction
|
|
751
|
+
direct_convention_methods, convention_methods_by_reference = environ.pins.partition { |p| p.namespace == rooted_tag }
|
|
752
|
+
result.concat direct_convention_methods
|
|
753
|
+
|
|
602
754
|
if deep && scope == :instance
|
|
603
755
|
store.get_prepends(fqns).reverse.each do |im|
|
|
604
|
-
fqim =
|
|
756
|
+
fqim = store.constants.dereference(im)
|
|
605
757
|
result.concat inner_get_methods(fqim, scope, visibility, deep, skip, true) unless fqim.nil?
|
|
606
758
|
end
|
|
607
759
|
end
|
|
608
760
|
# Store#get_methods doesn't know about full tags, just
|
|
609
761
|
# namespaces; resolving the generics in the method pins is this
|
|
610
762
|
# class' responsibility
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
methods = if namespace_pin && rooted_tag != fqns
|
|
614
|
-
methods = raw_methods.map do |method_pin|
|
|
615
|
-
method_pin.resolve_generics(namespace_pin, rooted_type)
|
|
616
|
-
end
|
|
617
|
-
else
|
|
618
|
-
raw_methods
|
|
619
|
-
end
|
|
763
|
+
methods = store.get_methods(fqns, scope: scope, visibility: visibility).sort{ |a, b| a.name <=> b.name }
|
|
764
|
+
logger.info { "ApiMap#inner_get_methods(rooted_tag=#{rooted_tag.inspect}, scope=#{scope.inspect}, visibility=#{visibility.inspect}, deep=#{deep.inspect}, skip=#{skip.inspect}, fqns=#{fqns}) - added from store: #{methods}" }
|
|
620
765
|
result.concat methods
|
|
621
766
|
if deep
|
|
767
|
+
result.concat convention_methods_by_reference
|
|
768
|
+
|
|
622
769
|
if scope == :instance
|
|
623
|
-
store.get_includes(fqns).reverse.each do |
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
# relative to the generics passed to the include. e.g.,
|
|
627
|
-
# Foo<String> might include Enumerable<String>
|
|
628
|
-
#
|
|
629
|
-
# @todo perform the same translation in the other areas
|
|
630
|
-
# here after adding a spec and handling things correctly
|
|
631
|
-
# in ApiMap::Store and RbsMap::Conversions
|
|
632
|
-
resolved_include_type = ComplexType.parse(rooted_include_tag).resolve_generics(namespace_pin, rooted_type)
|
|
633
|
-
methods = inner_get_methods(resolved_include_type.tag, scope, visibility, deep, skip, true)
|
|
634
|
-
result.concat methods
|
|
770
|
+
store.get_includes(fqns).reverse.each do |ref|
|
|
771
|
+
in_tag = dereference(ref)
|
|
772
|
+
result.concat inner_get_methods_from_reference(in_tag, namespace_pin, rooted_type, scope, visibility, deep, skip, true)
|
|
635
773
|
end
|
|
636
|
-
|
|
637
|
-
unless
|
|
638
|
-
result.concat
|
|
774
|
+
rooted_sc_tag = qualify_superclass(rooted_tag)
|
|
775
|
+
unless rooted_sc_tag.nil?
|
|
776
|
+
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, no_core)
|
|
639
777
|
end
|
|
640
778
|
else
|
|
779
|
+
logger.info { "ApiMap#inner_get_methods(#{fqns}, #{scope}, #{visibility}, #{deep}, #{skip}) - looking for get_extends() from #{fqns}" }
|
|
641
780
|
store.get_extends(fqns).reverse.each do |em|
|
|
642
|
-
fqem =
|
|
781
|
+
fqem = dereference(em)
|
|
643
782
|
result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil?
|
|
644
783
|
end
|
|
645
|
-
|
|
646
|
-
unless
|
|
647
|
-
result.concat
|
|
784
|
+
rooted_sc_tag = qualify_superclass(rooted_tag)
|
|
785
|
+
unless rooted_sc_tag.nil?
|
|
786
|
+
result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, true)
|
|
648
787
|
end
|
|
649
788
|
unless no_core || fqns.empty?
|
|
650
789
|
type = get_namespace_type(fqns)
|
|
@@ -660,91 +799,15 @@ module Solargraph
|
|
|
660
799
|
result
|
|
661
800
|
end
|
|
662
801
|
|
|
663
|
-
# @param fqns [String]
|
|
664
|
-
# @param visibility [Array<Symbol>]
|
|
665
|
-
# @param skip [Set<String>]
|
|
666
|
-
# @return [Array<Pin::Base>]
|
|
667
|
-
def inner_get_constants fqns, visibility, skip
|
|
668
|
-
return [] if fqns.nil? || skip.include?(fqns)
|
|
669
|
-
skip.add fqns
|
|
670
|
-
result = []
|
|
671
|
-
store.get_prepends(fqns).each do |is|
|
|
672
|
-
result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
|
|
673
|
-
end
|
|
674
|
-
result.concat store.get_constants(fqns, visibility)
|
|
675
|
-
.sort { |a, b| a.name <=> b.name }
|
|
676
|
-
store.get_includes(fqns).each do |is|
|
|
677
|
-
result.concat inner_get_constants(qualify(is, fqns), [:public], skip)
|
|
678
|
-
end
|
|
679
|
-
fqsc = qualify_superclass(fqns)
|
|
680
|
-
unless %w[Object BasicObject].include?(fqsc)
|
|
681
|
-
result.concat inner_get_constants(fqsc, [:public], skip)
|
|
682
|
-
end
|
|
683
|
-
result
|
|
684
|
-
end
|
|
685
|
-
|
|
686
802
|
# @return [Hash]
|
|
687
803
|
def path_macros
|
|
688
804
|
@path_macros ||= {}
|
|
689
805
|
end
|
|
690
806
|
|
|
691
|
-
# @param
|
|
692
|
-
# @param context [String]
|
|
693
|
-
# @return [String]
|
|
694
|
-
def qualify_lower namespace, context
|
|
695
|
-
qualify namespace, context.split('::')[0..-2].join('::')
|
|
696
|
-
end
|
|
697
|
-
|
|
698
|
-
# @param fqsub [String]
|
|
807
|
+
# @param fq_sub_tag [String]
|
|
699
808
|
# @return [String, nil]
|
|
700
|
-
def qualify_superclass
|
|
701
|
-
|
|
702
|
-
return nil if sup.nil?
|
|
703
|
-
parts = fqsub.split('::')
|
|
704
|
-
last = parts.pop
|
|
705
|
-
parts.pop if last == sup
|
|
706
|
-
qualify(sup, parts.join('::'))
|
|
707
|
-
end
|
|
708
|
-
|
|
709
|
-
# @param name [String] Namespace to fully qualify
|
|
710
|
-
# @param root [String] The context to search
|
|
711
|
-
# @param skip [Set<String>] Contexts already searched
|
|
712
|
-
# @return [String, nil] Fully qualified ("rooted") namespace
|
|
713
|
-
def inner_qualify name, root, skip
|
|
714
|
-
return name if name == ComplexType::GENERIC_TAG_NAME
|
|
715
|
-
return nil if name.nil?
|
|
716
|
-
return nil if skip.include?(root)
|
|
717
|
-
skip.add root
|
|
718
|
-
possibles = []
|
|
719
|
-
if name == ''
|
|
720
|
-
if root == ''
|
|
721
|
-
return ''
|
|
722
|
-
else
|
|
723
|
-
return inner_qualify(root, '', skip)
|
|
724
|
-
end
|
|
725
|
-
else
|
|
726
|
-
return name if root == '' && store.namespace_exists?(name)
|
|
727
|
-
roots = root.to_s.split('::')
|
|
728
|
-
while roots.length > 0
|
|
729
|
-
fqns = roots.join('::') + '::' + name
|
|
730
|
-
return fqns if store.namespace_exists?(fqns)
|
|
731
|
-
incs = store.get_includes(roots.join('::'))
|
|
732
|
-
incs.each do |inc|
|
|
733
|
-
foundinc = inner_qualify(name, inc, skip)
|
|
734
|
-
possibles.push foundinc unless foundinc.nil?
|
|
735
|
-
end
|
|
736
|
-
roots.pop
|
|
737
|
-
end
|
|
738
|
-
if possibles.empty?
|
|
739
|
-
incs = store.get_includes('')
|
|
740
|
-
incs.each do |inc|
|
|
741
|
-
foundinc = inner_qualify(name, inc, skip)
|
|
742
|
-
possibles.push foundinc unless foundinc.nil?
|
|
743
|
-
end
|
|
744
|
-
end
|
|
745
|
-
return name if store.namespace_exists?(name)
|
|
746
|
-
return possibles.last
|
|
747
|
-
end
|
|
809
|
+
def qualify_superclass fq_sub_tag
|
|
810
|
+
store.qualify_superclass fq_sub_tag
|
|
748
811
|
end
|
|
749
812
|
|
|
750
813
|
# Get the namespace's type (Class or Module).
|
|
@@ -761,8 +824,8 @@ module Solargraph
|
|
|
761
824
|
|
|
762
825
|
# Sort an array of pins to put nil or undefined variables last.
|
|
763
826
|
#
|
|
764
|
-
# @param pins [Enumerable<
|
|
765
|
-
# @return [Enumerable<
|
|
827
|
+
# @param pins [Enumerable<Pin::BaseVariable>]
|
|
828
|
+
# @return [Enumerable<Pin::BaseVariable>]
|
|
766
829
|
def prefer_non_nil_variables pins
|
|
767
830
|
result = []
|
|
768
831
|
nil_pins = []
|
|
@@ -776,37 +839,107 @@ module Solargraph
|
|
|
776
839
|
result + nil_pins
|
|
777
840
|
end
|
|
778
841
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
842
|
+
include Logging
|
|
843
|
+
|
|
844
|
+
private
|
|
845
|
+
|
|
846
|
+
# @param alias_pin [Pin::MethodAlias]
|
|
847
|
+
# @return [Pin::Method, nil]
|
|
848
|
+
def resolve_method_alias(alias_pin)
|
|
849
|
+
ancestors = store.get_ancestors(alias_pin.full_context.reduce_class_type.tag)
|
|
850
|
+
original = nil
|
|
851
|
+
|
|
852
|
+
# Search each ancestor for the original method
|
|
853
|
+
ancestors.each do |ancestor_fqns|
|
|
854
|
+
next if ancestor_fqns.nil?
|
|
855
|
+
ancestor_method_path = "#{ancestor_fqns}#{alias_pin.scope == :instance ? '#' : '.'}#{alias_pin.original}"
|
|
856
|
+
|
|
857
|
+
# Search for the original method in the ancestor
|
|
858
|
+
original = store.get_path_pins(ancestor_method_path).find do |candidate_pin|
|
|
859
|
+
next if candidate_pin == alias_pin
|
|
860
|
+
|
|
861
|
+
if candidate_pin.is_a?(Pin::MethodAlias)
|
|
862
|
+
# recursively resolve method aliases
|
|
863
|
+
resolved = resolve_method_alias(candidate_pin)
|
|
864
|
+
break resolved if resolved
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
candidate_pin.is_a?(Pin::Method) && candidate_pin.scope == alias_pin.scope
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
break if original
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
# @sg-ignore ignore `received nil` for original
|
|
874
|
+
create_resolved_alias_pin(alias_pin, original) if original
|
|
788
875
|
end
|
|
789
876
|
|
|
790
|
-
#
|
|
791
|
-
# @
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
origin = get_method_stack(pin.full_context.tag, pin.original, scope: pin.scope).first
|
|
797
|
-
@method_alias_stack.pop
|
|
798
|
-
return nil if origin.nil?
|
|
877
|
+
# Fast path for creating resolved alias pins without individual method stack lookups
|
|
878
|
+
# @param alias_pin [Pin::MethodAlias] The alias pin to resolve
|
|
879
|
+
# @param original [Pin::Method] The original method pin that was already found
|
|
880
|
+
# @return [Pin::Method] The resolved method pin
|
|
881
|
+
def create_resolved_alias_pin(alias_pin, original)
|
|
882
|
+
# Build the resolved method pin directly (same logic as resolve_method_alias but without lookup)
|
|
799
883
|
args = {
|
|
800
|
-
location:
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
884
|
+
location: alias_pin.location,
|
|
885
|
+
type_location: original.type_location,
|
|
886
|
+
closure: alias_pin.closure,
|
|
887
|
+
name: alias_pin.name,
|
|
888
|
+
comments: original.comments,
|
|
889
|
+
scope: original.scope,
|
|
890
|
+
visibility: original.visibility,
|
|
891
|
+
signatures: original.signatures.map(&:clone).freeze,
|
|
892
|
+
attribute: original.attribute?,
|
|
893
|
+
generics: original.generics.clone,
|
|
894
|
+
return_type: original.return_type,
|
|
895
|
+
source: :resolve_method_alias
|
|
808
896
|
}
|
|
809
|
-
Pin::Method.new **args
|
|
897
|
+
resolved_pin = Pin::Method.new **args
|
|
898
|
+
|
|
899
|
+
# Clone signatures and parameters
|
|
900
|
+
resolved_pin.signatures.each do |sig|
|
|
901
|
+
sig.parameters = sig.parameters.map(&:clone).freeze
|
|
902
|
+
sig.source = :resolve_method_alias
|
|
903
|
+
sig.parameters.each do |param|
|
|
904
|
+
param.closure = resolved_pin
|
|
905
|
+
param.source = :resolve_method_alias
|
|
906
|
+
param.reset_generated!
|
|
907
|
+
end
|
|
908
|
+
sig.closure = resolved_pin
|
|
909
|
+
sig.reset_generated!
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
resolved_pin
|
|
913
|
+
end
|
|
914
|
+
|
|
915
|
+
# @param namespace_pin [Pin::Namespace]
|
|
916
|
+
# @param rooted_type [ComplexType]
|
|
917
|
+
# @param pins [Enumerable<Pin::Base>]
|
|
918
|
+
# @return [Array<Pin::Base>]
|
|
919
|
+
def erase_generics(namespace_pin, rooted_type, pins)
|
|
920
|
+
return pins unless should_erase_generics_when_done?(namespace_pin, rooted_type)
|
|
921
|
+
|
|
922
|
+
logger.debug("Erasing generics on namespace_pin=#{namespace_pin} / rooted_type=#{rooted_type}")
|
|
923
|
+
pins.map do |method_pin|
|
|
924
|
+
method_pin.erase_generics(namespace_pin.generics)
|
|
925
|
+
end
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
# @param namespace_pin [Pin::Namespace]
|
|
929
|
+
# @param rooted_type [ComplexType]
|
|
930
|
+
def should_erase_generics_when_done?(namespace_pin, rooted_type)
|
|
931
|
+
has_generics?(namespace_pin) && !can_resolve_generics?(namespace_pin, rooted_type)
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
# @param namespace_pin [Pin::Namespace, Pin::Constant]
|
|
935
|
+
def has_generics?(namespace_pin)
|
|
936
|
+
namespace_pin.is_a?(Pin::Namespace) && !namespace_pin.generics.empty?
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
# @param namespace_pin [Pin::Namespace]
|
|
940
|
+
# @param rooted_type [ComplexType]
|
|
941
|
+
def can_resolve_generics?(namespace_pin, rooted_type)
|
|
942
|
+
has_generics?(namespace_pin) && !rooted_type.all_params.empty?
|
|
810
943
|
end
|
|
811
944
|
end
|
|
812
945
|
end
|