solargraph 0.54.4 → 0.56.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 +2 -0
- data/.github/workflows/typecheck.yml +3 -1
- data/.gitignore +2 -0
- data/CHANGELOG.md +62 -0
- data/README.md +13 -3
- data/lib/solargraph/api_map/index.rb +24 -16
- data/lib/solargraph/api_map/store.rb +48 -23
- data/lib/solargraph/api_map.rb +175 -77
- data/lib/solargraph/bench.rb +17 -1
- data/lib/solargraph/complex_type/type_methods.rb +6 -1
- data/lib/solargraph/complex_type/unique_type.rb +98 -9
- data/lib/solargraph/complex_type.rb +35 -6
- data/lib/solargraph/convention/base.rb +3 -3
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +60 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +89 -0
- data/lib/solargraph/convention/data_definition.rb +104 -0
- data/lib/solargraph/convention/gemspec.rb +2 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +60 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +100 -0
- data/lib/solargraph/convention/struct_definition.rb +141 -0
- data/lib/solargraph/convention.rb +5 -3
- data/lib/solargraph/doc_map.rb +277 -57
- data/lib/solargraph/gem_pins.rb +53 -37
- data/lib/solargraph/language_server/host/message_worker.rb +10 -7
- data/lib/solargraph/language_server/host.rb +12 -2
- 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/library.rb +45 -17
- data/lib/solargraph/location.rb +21 -0
- data/lib/solargraph/logging.rb +1 -0
- data/lib/solargraph/parser/comment_ripper.rb +12 -6
- data/lib/solargraph/parser/flow_sensitive_typing.rb +227 -0
- data/lib/solargraph/parser/node_methods.rb +14 -0
- data/lib/solargraph/parser/node_processor/base.rb +9 -4
- data/lib/solargraph/parser/node_processor.rb +21 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +16 -14
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +10 -10
- data/lib/solargraph/parser/parser_gem/node_methods.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +4 -2
- 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 +21 -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 +4 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -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 +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +28 -16
- 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 +1 -1
- data/lib/solargraph/parser.rb +1 -0
- data/lib/solargraph/pin/base.rb +316 -28
- data/lib/solargraph/pin/base_variable.rb +16 -9
- data/lib/solargraph/pin/block.rb +2 -0
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +74 -3
- data/lib/solargraph/pin/closure.rb +18 -1
- data/lib/solargraph/pin/common.rb +5 -0
- data/lib/solargraph/pin/delegated_method.rb +20 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +15 -6
- data/lib/solargraph/pin/method.rb +169 -43
- data/lib/solargraph/pin/namespace.rb +17 -9
- data/lib/solargraph/pin/parameter.rb +60 -11
- data/lib/solargraph/pin/proxy_type.rb +12 -6
- data/lib/solargraph/pin/reference/override.rb +10 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/signature.rb +42 -0
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +3 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +4 -1
- data/lib/solargraph/pin_cache.rb +185 -0
- data/lib/solargraph/position.rb +9 -0
- data/lib/solargraph/range.rb +9 -0
- data/lib/solargraph/rbs_map/conversions.rb +221 -67
- data/lib/solargraph/rbs_map/core_fills.rb +32 -16
- data/lib/solargraph/rbs_map/core_map.rb +34 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +74 -17
- data/lib/solargraph/shell.rb +17 -18
- data/lib/solargraph/source/chain/array.rb +11 -7
- 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 +53 -23
- data/lib/solargraph/source/chain/constant.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +4 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +2 -0
- data/lib/solargraph/source/chain/literal.rb +22 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +78 -48
- data/lib/solargraph/source/source_chainer.rb +2 -2
- data/lib/solargraph/source_map/clip.rb +3 -1
- data/lib/solargraph/source_map/mapper.rb +9 -5
- data/lib/solargraph/source_map.rb +0 -17
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker.rb +35 -8
- 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/workspace/config.rb +1 -1
- data/lib/solargraph/workspace.rb +23 -5
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
- data/lib/solargraph/yard_map/mapper.rb +4 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph/yardoc.rb +7 -8
- data/lib/solargraph.rb +32 -1
- data/rbs/fills/tuple.rbs +150 -0
- data/rbs_collection.yaml +19 -0
- data/solargraph.gemspec +2 -1
- metadata +37 -9
- data/lib/solargraph/cache.rb +0 -77
@@ -5,23 +5,46 @@ module Solargraph
|
|
5
5
|
# Ruby core pins
|
6
6
|
#
|
7
7
|
class CoreMap
|
8
|
-
include Conversions
|
9
8
|
|
10
|
-
def
|
11
|
-
|
9
|
+
def resolved?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
FILLS_DIRECTORY = File.join(File.dirname(__FILE__), '..', '..', '..', 'rbs', 'fills')
|
14
|
+
|
15
|
+
def initialize; end
|
16
|
+
|
17
|
+
def pins
|
18
|
+
return @pins if @pins
|
19
|
+
|
20
|
+
@pins = []
|
21
|
+
cache = PinCache.deserialize_core
|
12
22
|
if cache
|
13
|
-
pins.replace cache
|
23
|
+
@pins.replace cache
|
14
24
|
else
|
15
|
-
loader
|
16
|
-
|
17
|
-
|
18
|
-
pins.concat RbsMap::CoreFills::ALL
|
25
|
+
loader.add(path: Pathname(FILLS_DIRECTORY))
|
26
|
+
@pins = conversions.pins
|
27
|
+
@pins.concat RbsMap::CoreFills::ALL
|
19
28
|
processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
|
20
|
-
|
21
|
-
pins.replace processed
|
29
|
+
@pins.replace processed
|
22
30
|
|
23
|
-
|
31
|
+
PinCache.serialize_core @pins
|
24
32
|
end
|
33
|
+
@pins
|
34
|
+
end
|
35
|
+
|
36
|
+
def loader
|
37
|
+
@loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def loader
|
43
|
+
@loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
|
44
|
+
end
|
45
|
+
|
46
|
+
def conversions
|
47
|
+
@conversions ||= Conversions.new(loader: loader)
|
25
48
|
end
|
26
49
|
end
|
27
50
|
end
|
@@ -7,19 +7,29 @@ module Solargraph
|
|
7
7
|
# Ruby stdlib pins
|
8
8
|
#
|
9
9
|
class StdlibMap < RbsMap
|
10
|
+
include Logging
|
11
|
+
|
10
12
|
# @type [Hash{String => RbsMap}]
|
11
13
|
@stdlib_maps_hash = {}
|
12
14
|
|
13
15
|
# @param library [String]
|
14
16
|
def initialize library
|
15
|
-
|
16
|
-
if
|
17
|
-
pins
|
17
|
+
cached_pins = PinCache.deserialize_stdlib_require library
|
18
|
+
if cached_pins
|
19
|
+
@pins = cached_pins
|
18
20
|
@resolved = true
|
21
|
+
@loaded = true
|
22
|
+
logger.debug { "Deserialized #{cached_pins.length} cached pins for stdlib require #{library.inspect}" }
|
19
23
|
else
|
20
24
|
super
|
21
|
-
|
22
|
-
|
25
|
+
unless resolved?
|
26
|
+
@pins = []
|
27
|
+
logger.info { "Could not resolve #{library.inspect}" }
|
28
|
+
return
|
29
|
+
end
|
30
|
+
generated_pins = pins
|
31
|
+
logger.debug { "Found #{generated_pins.length} pins for stdlib library #{library}" }
|
32
|
+
PinCache.serialize_stdlib_require library, generated_pins
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
data/lib/solargraph/rbs_map.rb
CHANGED
@@ -10,25 +10,78 @@ module Solargraph
|
|
10
10
|
autoload :CoreFills, 'solargraph/rbs_map/core_fills'
|
11
11
|
autoload :StdlibMap, 'solargraph/rbs_map/stdlib_map'
|
12
12
|
|
13
|
-
include
|
13
|
+
include Logging
|
14
14
|
|
15
15
|
# @type [Hash{String => RbsMap}]
|
16
16
|
@@rbs_maps_hash = {}
|
17
17
|
|
18
18
|
attr_reader :library
|
19
19
|
|
20
|
+
attr_reader :rbs_collection_paths
|
21
|
+
|
22
|
+
attr_reader :rbs_collection_config_path
|
23
|
+
|
20
24
|
# @param library [String]
|
21
25
|
# @param version [String, nil]
|
22
|
-
# @param
|
23
|
-
def initialize library, version = nil,
|
26
|
+
# @param rbs_collection_paths [Array<Pathname, String>]
|
27
|
+
def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: []
|
28
|
+
if rbs_collection_config_path.nil? && !rbs_collection_paths.empty?
|
29
|
+
raise 'Please provide rbs_collection_config_path if you provide rbs_collection_paths'
|
30
|
+
end
|
24
31
|
@library = library
|
25
32
|
@version = version
|
26
|
-
@
|
27
|
-
@
|
28
|
-
loader = RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
33
|
+
@rbs_collection_config_path = rbs_collection_config_path
|
34
|
+
@rbs_collection_paths = rbs_collection_paths
|
29
35
|
add_library loader, library, version
|
30
|
-
|
31
|
-
|
36
|
+
end
|
37
|
+
|
38
|
+
def loader
|
39
|
+
@loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return string representing the version of the RBS info fetched
|
43
|
+
# for the given library. Must change when the RBS info is
|
44
|
+
# updated upstream for the same library and version. May change
|
45
|
+
# if the config for where information comes form changes.
|
46
|
+
def cache_key
|
47
|
+
@hextdigest ||= begin
|
48
|
+
data = nil
|
49
|
+
if rbs_collection_config_path
|
50
|
+
lockfile_path = RBS::Collection::Config.to_lockfile_path(Pathname.new(rbs_collection_config_path))
|
51
|
+
if lockfile_path.exist?
|
52
|
+
collection_config = RBS::Collection::Config.from_path lockfile_path
|
53
|
+
gem_config = collection_config.gem(library)
|
54
|
+
data = gem_config&.to_s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
if data.nil? || data.empty?
|
58
|
+
if resolved?
|
59
|
+
# definitely came from the gem itself and not elsewhere -
|
60
|
+
# only one version per gem
|
61
|
+
'gem-export'
|
62
|
+
else
|
63
|
+
'unresolved'
|
64
|
+
end
|
65
|
+
else
|
66
|
+
Digest::SHA1.hexdigest(data)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path
|
72
|
+
rbs_map = RbsMap.new(gemspec.name, gemspec.version,
|
73
|
+
rbs_collection_paths: [rbs_collection_path].compact,
|
74
|
+
rbs_collection_config_path: rbs_collection_config_path)
|
75
|
+
return rbs_map if rbs_map.resolved?
|
76
|
+
|
77
|
+
# try any version of the gem in the collection
|
78
|
+
RbsMap.new(gemspec.name, nil,
|
79
|
+
rbs_collection_paths: [rbs_collection_path].compact,
|
80
|
+
rbs_collection_config_path: rbs_collection_config_path)
|
81
|
+
end
|
82
|
+
|
83
|
+
def pins
|
84
|
+
@pins ||= resolved? ? conversions.pins : []
|
32
85
|
end
|
33
86
|
|
34
87
|
# @generic T
|
@@ -52,9 +105,10 @@ module Solargraph
|
|
52
105
|
|
53
106
|
def repository
|
54
107
|
@repository ||= RBS::Repository.new(no_stdlib: false).tap do |repo|
|
55
|
-
|
56
|
-
|
57
|
-
|
108
|
+
@rbs_collection_paths.each do |dir|
|
109
|
+
dir_path = Pathname.new(dir)
|
110
|
+
repo.add(dir_path) if dir_path.exist? && dir_path.directory?
|
111
|
+
end
|
58
112
|
end
|
59
113
|
end
|
60
114
|
|
@@ -64,12 +118,15 @@ module Solargraph
|
|
64
118
|
@@rbs_maps_hash[library] ||= RbsMap.new(library)
|
65
119
|
end
|
66
120
|
|
67
|
-
|
68
|
-
|
69
|
-
|
121
|
+
private
|
122
|
+
|
123
|
+
def loader
|
124
|
+
@loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
70
125
|
end
|
71
126
|
|
72
|
-
|
127
|
+
def conversions
|
128
|
+
@conversions ||= Conversions.new(loader: loader)
|
129
|
+
end
|
73
130
|
|
74
131
|
# @param loader [RBS::EnvironmentLoader]
|
75
132
|
# @param library [String]
|
@@ -77,10 +134,10 @@ module Solargraph
|
|
77
134
|
def add_library loader, library, version
|
78
135
|
@resolved = if loader.has_library?(library: library, version: version)
|
79
136
|
loader.add library: library, version: version
|
80
|
-
|
137
|
+
logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" }
|
81
138
|
true
|
82
139
|
else
|
83
|
-
|
140
|
+
logger.info { "#{short_name} did not find data for library #{library}:#{version}" }
|
84
141
|
false
|
85
142
|
end
|
86
143
|
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -90,19 +90,20 @@ module Solargraph
|
|
90
90
|
# @return [void]
|
91
91
|
def clear
|
92
92
|
puts "Deleting all cached documentation (gems, core and stdlib)"
|
93
|
-
Solargraph::
|
93
|
+
Solargraph::PinCache.clear
|
94
94
|
end
|
95
95
|
map 'clear-cache' => :clear
|
96
96
|
map 'clear-cores' => :clear
|
97
97
|
|
98
98
|
desc 'cache', 'Cache a gem', hide: true
|
99
|
+
option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
|
99
100
|
# @return [void]
|
100
101
|
# @param gem [String]
|
101
102
|
# @param version [String, nil]
|
102
103
|
def cache gem, version = nil
|
104
|
+
api_map = Solargraph::ApiMap.load(Dir.pwd)
|
103
105
|
spec = Gem::Specification.find_by_name(gem, version)
|
104
|
-
|
105
|
-
Cache.save('gems', "#{spec.name}-#{spec.version}.ser", pins)
|
106
|
+
api_map.cache_gem(spec, rebuild: options[:rebuild], out: $stdout)
|
106
107
|
end
|
107
108
|
|
108
109
|
desc 'uncache GEM [...GEM]', "Delete specific cached gem documentation"
|
@@ -117,18 +118,17 @@ module Solargraph
|
|
117
118
|
raise ArgumentError, 'No gems specified.' if gems.empty?
|
118
119
|
gems.each do |gem|
|
119
120
|
if gem == 'core'
|
120
|
-
|
121
|
+
PinCache.uncache_core
|
121
122
|
next
|
122
123
|
end
|
123
124
|
|
124
125
|
if gem == 'stdlib'
|
125
|
-
|
126
|
+
PinCache.uncache_stdlib
|
126
127
|
next
|
127
128
|
end
|
128
129
|
|
129
130
|
spec = Gem::Specification.find_by_name(gem)
|
130
|
-
|
131
|
-
Cache.uncache('gems', "#{spec.name}-#{spec.version}.yardoc")
|
131
|
+
PinCache.uncache_gem(spec, out: $stdout)
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
@@ -137,15 +137,18 @@ module Solargraph
|
|
137
137
|
# @param names [Array<String>]
|
138
138
|
# @return [void]
|
139
139
|
def gems *names
|
140
|
+
api_map = ApiMap.load('.')
|
140
141
|
if names.empty?
|
141
|
-
Gem::Specification.to_a.each { |spec| do_cache spec }
|
142
|
+
Gem::Specification.to_a.each { |spec| do_cache spec, api_map }
|
143
|
+
STDERR.puts "Documentation cached for all #{Gem::Specification.count} gems."
|
142
144
|
else
|
143
145
|
names.each do |name|
|
144
146
|
spec = Gem::Specification.find_by_name(*name.split('='))
|
145
|
-
do_cache spec
|
147
|
+
do_cache spec, api_map
|
146
148
|
rescue Gem::MissingSpecError
|
147
149
|
warn "Gem '#{name}' not found"
|
148
150
|
end
|
151
|
+
STDERR.puts "Documentation cached for #{names.count} gems."
|
149
152
|
end
|
150
153
|
end
|
151
154
|
|
@@ -206,6 +209,7 @@ module Solargraph
|
|
206
209
|
# @return [void]
|
207
210
|
def scan
|
208
211
|
directory = File.realpath(options[:directory])
|
212
|
+
# @type [Solargraph::ApiMap, nil]
|
209
213
|
api_map = nil
|
210
214
|
time = Benchmark.measure {
|
211
215
|
api_map = Solargraph::ApiMap.load_with_cache(directory, $stdout)
|
@@ -255,15 +259,10 @@ module Solargraph
|
|
255
259
|
|
256
260
|
# @param gemspec [Gem::Specification]
|
257
261
|
# @return [void]
|
258
|
-
def do_cache gemspec
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
else
|
263
|
-
puts "#{cached ? 'Rebuilding' : 'Caching'} gem documentation for #{gemspec.name} #{gemspec.version}"
|
264
|
-
pins = GemPins.build(gemspec)
|
265
|
-
Cache.save('gems', "#{gemspec.name}-#{gemspec.version}.ser", pins)
|
266
|
-
end
|
262
|
+
def do_cache gemspec, api_map
|
263
|
+
# @todo if the rebuild: option is passed as a positional arg,
|
264
|
+
# typecheck doesn't complain on the below line
|
265
|
+
api_map.cache_gem(gemspec, rebuild: options.rebuild, out: $stdout)
|
267
266
|
end
|
268
267
|
end
|
269
268
|
end
|
@@ -3,8 +3,9 @@ module Solargraph
|
|
3
3
|
class Chain
|
4
4
|
class Array < Literal
|
5
5
|
# @param children [::Array<Chain>]
|
6
|
-
|
7
|
-
|
6
|
+
# @param node [Parser::AST::Node]
|
7
|
+
def initialize children, node
|
8
|
+
super('::Array', node)
|
8
9
|
@children = children
|
9
10
|
end
|
10
11
|
|
@@ -17,15 +18,18 @@ module Solargraph
|
|
17
18
|
# @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
|
18
19
|
def resolve api_map, name_pin, locals
|
19
20
|
child_types = @children.map do |child|
|
20
|
-
child.infer(api_map, name_pin, locals)
|
21
|
+
child.infer(api_map, name_pin, locals).simplify_literals
|
21
22
|
end
|
22
|
-
|
23
|
-
|
23
|
+
type = if child_types.length == 0 || child_types.any?(&:undefined?)
|
24
|
+
ComplexType::UniqueType.new('Array', rooted: true)
|
25
|
+
elsif child_types.uniq.length == 1 && child_types.first.defined?
|
24
26
|
ComplexType::UniqueType.new('Array', [], child_types.uniq, rooted: true, parameters_type: :list)
|
27
|
+
elsif child_types.length == 0
|
28
|
+
ComplexType::UniqueType.new('Array', rooted: true, parameters_type: :list)
|
25
29
|
else
|
26
|
-
ComplexType::UniqueType.new('Array', rooted: true)
|
30
|
+
ComplexType::UniqueType.new('Array', [], child_types, rooted: true, parameters_type: :fixed)
|
27
31
|
end
|
28
|
-
[Pin::ProxyType.anonymous(type)]
|
32
|
+
[Pin::ProxyType.anonymous(type, source: :chain)]
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -3,12 +3,20 @@
|
|
3
3
|
module Solargraph
|
4
4
|
class Source
|
5
5
|
class Chain
|
6
|
+
#
|
7
|
+
# Handles both method calls and local variable references by
|
8
|
+
# first looking for a variable with the name 'word', then
|
9
|
+
# proceeding to method signature resolution if not found.
|
10
|
+
#
|
6
11
|
class Call < Chain::Link
|
7
12
|
include Solargraph::Parser::NodeMethods
|
8
13
|
|
9
14
|
# @return [String]
|
10
15
|
attr_reader :word
|
11
16
|
|
17
|
+
# @return [Location]
|
18
|
+
attr_reader :location
|
19
|
+
|
12
20
|
# @return [::Array<Chain>]
|
13
21
|
attr_reader :arguments
|
14
22
|
|
@@ -16,10 +24,12 @@ module Solargraph
|
|
16
24
|
attr_reader :block
|
17
25
|
|
18
26
|
# @param word [String]
|
27
|
+
# @param location [Location, nil]
|
19
28
|
# @param arguments [::Array<Chain>]
|
20
29
|
# @param block [Chain, nil]
|
21
|
-
def initialize word, arguments = [], block = nil
|
30
|
+
def initialize word, location = nil, arguments = [], block = nil
|
22
31
|
@word = word
|
32
|
+
@location = location
|
23
33
|
@arguments = arguments
|
24
34
|
@block = block
|
25
35
|
fix_block_pass
|
@@ -35,20 +45,21 @@ module Solargraph
|
|
35
45
|
end
|
36
46
|
|
37
47
|
# @param api_map [ApiMap]
|
38
|
-
# @param name_pin [Pin::Closure] name_pin.binder should give us the object on which 'word' will be invoked
|
48
|
+
# @param name_pin [Pin::Closure] name_pin.binder should give us the type of the object on which 'word' will be invoked
|
39
49
|
# @param locals [::Array<Pin::LocalVariable>]
|
40
50
|
def resolve api_map, name_pin, locals
|
41
51
|
return super_pins(api_map, name_pin) if word == 'super'
|
42
52
|
return yield_pins(api_map, name_pin) if word == 'yield'
|
43
53
|
found = if head?
|
44
|
-
locals
|
54
|
+
api_map.visible_pins(locals, word, name_pin, location)
|
45
55
|
else
|
46
56
|
[]
|
47
57
|
end
|
48
58
|
return inferred_pins(found, api_map, name_pin, locals) unless found.empty?
|
49
59
|
pins = name_pin.binder.each_unique_type.flat_map do |context|
|
50
|
-
|
51
|
-
api_map.get_method_stack(
|
60
|
+
ns_tag = context.namespace == '' ? '' : context.namespace_type.tag
|
61
|
+
stack = api_map.get_method_stack(ns_tag, word, scope: context.scope)
|
62
|
+
[stack.first].compact
|
52
63
|
end
|
53
64
|
return [] if pins.empty?
|
54
65
|
inferred_pins(pins, api_map, name_pin, locals)
|
@@ -72,7 +83,9 @@ module Solargraph
|
|
72
83
|
# use it. If we didn't pass a block, the logic below will
|
73
84
|
# reject it regardless
|
74
85
|
|
75
|
-
|
86
|
+
with_block, without_block = overloads.partition(&:block?)
|
87
|
+
sorted_overloads = with_block + without_block
|
88
|
+
# @type [Pin::Signature, nil]
|
76
89
|
new_signature_pin = nil
|
77
90
|
sorted_overloads.each do |ol|
|
78
91
|
next unless ol.arity_matches?(arguments, with_block?)
|
@@ -85,13 +98,8 @@ module Solargraph
|
|
85
98
|
match = ol.parameters.any?(&:restarg?)
|
86
99
|
break
|
87
100
|
end
|
88
|
-
atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(name_pin.context), locals)
|
89
|
-
|
90
|
-
# inheritance chain if we don't have them on this pin
|
91
|
-
ptype = param.typify api_map
|
92
|
-
# @todo Weak type comparison
|
93
|
-
# unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
|
94
|
-
unless ptype.undefined? || atype.name == ptype.name || ptype.any? { |current_ptype| api_map.super_and_sub?(current_ptype.name, atype.name) } || ptype.generic? || param.restarg?
|
101
|
+
atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(name_pin.context, source: :chain), locals)
|
102
|
+
unless param.compatible_arg?(atype, api_map) || param.restarg?
|
95
103
|
match = false
|
96
104
|
break
|
97
105
|
end
|
@@ -106,9 +114,30 @@ module Solargraph
|
|
106
114
|
blocktype = block_call_type(api_map, name_pin, locals)
|
107
115
|
end
|
108
116
|
end
|
117
|
+
# @type new_signature_pin [Pin::Signature]
|
109
118
|
new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
|
110
119
|
new_return_type = new_signature_pin.return_type
|
111
|
-
|
120
|
+
if head?
|
121
|
+
# If we're at the head of the chain, we called a
|
122
|
+
# method somewhere that marked itself as returning
|
123
|
+
# self. Given we didn't invoke this on an object,
|
124
|
+
# this must be a method in this same class - so we
|
125
|
+
# use our own self type
|
126
|
+
self_type = name_pin.context
|
127
|
+
else
|
128
|
+
# if we're past the head in the chain, whatever the
|
129
|
+
# type of the lhs side is what 'self' will be in its
|
130
|
+
# declaration - we can't just use the type of the
|
131
|
+
# method pin, as this might be a subclass of the
|
132
|
+
# place where the method is defined
|
133
|
+
self_type = name_pin.binder
|
134
|
+
end
|
135
|
+
# This same logic applies to the YARD work done by
|
136
|
+
# 'with_params()'.
|
137
|
+
#
|
138
|
+
# qualify(), however, happens in the namespace where
|
139
|
+
# the docs were written - from the method pin.
|
140
|
+
type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, p.namespace) if new_return_type.defined?
|
112
141
|
type ||= ComplexType::UNDEFINED
|
113
142
|
end
|
114
143
|
break if type.defined?
|
@@ -124,13 +153,14 @@ module Solargraph
|
|
124
153
|
end
|
125
154
|
p
|
126
155
|
end
|
127
|
-
|
128
|
-
|
129
|
-
|
156
|
+
logger.debug { "Call#inferred_pins(name_pin.binder=#{name_pin.binder}, word=#{word}, pins=#{pins.map(&:desc)}, name_pin=#{name_pin}) - result=#{result}" }
|
157
|
+
out = result.map do |pin|
|
158
|
+
if pin.path == 'Class#new' && name_pin.binder.tag != 'Class'
|
159
|
+
reduced_context = name_pin.binder.reduce_class_type
|
130
160
|
pin.proxy(reduced_context)
|
131
161
|
else
|
132
162
|
next pin if pin.return_type.undefined?
|
133
|
-
selfy = pin.return_type.self_to_type(name_pin.
|
163
|
+
selfy = pin.return_type.self_to_type(name_pin.binder)
|
134
164
|
selfy == pin.return_type ? pin : pin.proxy(selfy)
|
135
165
|
end
|
136
166
|
end
|
@@ -152,7 +182,7 @@ module Solargraph
|
|
152
182
|
result = inner_process_macro(pin, macro, api_map, context, locals)
|
153
183
|
return result unless result.return_type.undefined?
|
154
184
|
end
|
155
|
-
Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
|
185
|
+
Pin::ProxyType.anonymous(ComplexType::UNDEFINED, source: :chain)
|
156
186
|
end
|
157
187
|
|
158
188
|
# @param pin [Pin::Method]
|
@@ -167,7 +197,7 @@ module Solargraph
|
|
167
197
|
result = inner_process_macro(pin, macro, api_map, context, locals)
|
168
198
|
return result unless result.return_type.undefined?
|
169
199
|
end
|
170
|
-
Pin::ProxyType.anonymous ComplexType::UNDEFINED
|
200
|
+
Pin::ProxyType.anonymous ComplexType::UNDEFINED, source: :chain
|
171
201
|
end
|
172
202
|
|
173
203
|
# @param pin [Pin::Base]
|
@@ -177,7 +207,7 @@ module Solargraph
|
|
177
207
|
# @param locals [::Array<Pin::LocalVariable, Pin::Parameter>]
|
178
208
|
# @return [Pin::ProxyType]
|
179
209
|
def inner_process_macro pin, macro, api_map, context, locals
|
180
|
-
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
|
210
|
+
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals), source: :chain) }
|
181
211
|
txt = macro.tag.text.clone
|
182
212
|
if txt.empty? && macro.tag.name
|
183
213
|
named = api_map.named_macro(macro.tag.name)
|
@@ -191,9 +221,9 @@ module Solargraph
|
|
191
221
|
docstring = Solargraph::Source.parse_docstring(txt).to_docstring
|
192
222
|
tag = docstring.tag(:return)
|
193
223
|
unless tag.nil? || tag.types.nil?
|
194
|
-
return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types))
|
224
|
+
return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types), source: :chain)
|
195
225
|
end
|
196
|
-
Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
|
226
|
+
Pin::ProxyType.anonymous(ComplexType::UNDEFINED, source: :chain)
|
197
227
|
end
|
198
228
|
|
199
229
|
# @param docstring [YARD::Docstring]
|
@@ -5,9 +5,10 @@ module Solargraph
|
|
5
5
|
class Chain
|
6
6
|
class Hash < Literal
|
7
7
|
# @param type [String]
|
8
|
+
# @param node [Parser::AST::Node]
|
8
9
|
# @param splatted [Boolean]
|
9
|
-
def initialize type, splatted = false
|
10
|
-
super(type)
|
10
|
+
def initialize type, node, splatted = false
|
11
|
+
super(type, node)
|
11
12
|
@splatted = splatted
|
12
13
|
end
|
13
14
|
|
@@ -21,7 +22,7 @@ module Solargraph
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def resolve api_map, name_pin, locals
|
24
|
-
[Pin::ProxyType.anonymous(@complex_type)]
|
25
|
+
[Pin::ProxyType.anonymous(@complex_type, source: :chain)]
|
25
26
|
end
|
26
27
|
|
27
28
|
def splatted?
|
@@ -9,7 +9,7 @@ module Solargraph
|
|
9
9
|
# @note Chain::Head is only intended to handle `self` and `super`.
|
10
10
|
class Head < Link
|
11
11
|
def resolve api_map, name_pin, locals
|
12
|
-
return [Pin::ProxyType.anonymous(name_pin.binder)] if word == 'self'
|
12
|
+
return [Pin::ProxyType.anonymous(name_pin.binder, source: :chain)] if word == 'self'
|
13
13
|
# return super_pins(api_map, name_pin) if word == 'super'
|
14
14
|
[]
|
15
15
|
end
|
@@ -20,7 +20,7 @@ module Solargraph
|
|
20
20
|
|
21
21
|
def resolve api_map, name_pin, locals
|
22
22
|
types = @links.map { |link| link.infer(api_map, name_pin, locals) }
|
23
|
-
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.try_parse(types.map(&:tag).uniq.join(', ')))]
|
23
|
+
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.try_parse(types.map(&:tag).uniq.join(', ')), source: :chain)]
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'parser'
|
4
|
+
|
3
5
|
module Solargraph
|
4
6
|
class Source
|
5
7
|
class Chain
|
@@ -8,9 +10,22 @@ module Solargraph
|
|
8
10
|
@word ||= "<#{@type}>"
|
9
11
|
end
|
10
12
|
|
13
|
+
attr_reader :value
|
14
|
+
|
11
15
|
# @param type [String]
|
12
|
-
|
16
|
+
# @param node [Parser::AST::Node, Object]
|
17
|
+
def initialize type, node
|
18
|
+
if node.is_a?(::Parser::AST::Node)
|
19
|
+
if node.type == :true
|
20
|
+
@value = true
|
21
|
+
elsif node.type == :false
|
22
|
+
@value = false
|
23
|
+
elsif [:int, :sym].include?(node.type)
|
24
|
+
@value = node.children.first
|
25
|
+
end
|
26
|
+
end
|
13
27
|
@type = type
|
28
|
+
@literal_type = ComplexType.try_parse(@value.inspect)
|
14
29
|
@complex_type = ComplexType.try_parse(type)
|
15
30
|
end
|
16
31
|
|
@@ -20,7 +35,12 @@ module Solargraph
|
|
20
35
|
end
|
21
36
|
|
22
37
|
def resolve api_map, name_pin, locals
|
23
|
-
|
38
|
+
if api_map.super_and_sub?(@complex_type.name, @literal_type.name)
|
39
|
+
[Pin::ProxyType.anonymous(@literal_type, source: :chain)]
|
40
|
+
else
|
41
|
+
# we don't support this value as a literal type
|
42
|
+
[Pin::ProxyType.anonymous(@complex_type, source: :chain)]
|
43
|
+
end
|
24
44
|
end
|
25
45
|
end
|
26
46
|
end
|
@@ -15,7 +15,7 @@ module Solargraph
|
|
15
15
|
|
16
16
|
def resolve api_map, name_pin, locals
|
17
17
|
types = @links.map { |link| link.infer(api_map, name_pin, locals) }
|
18
|
-
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.new(types.uniq))]
|
18
|
+
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.new(types.uniq), source: :chain)]
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|