solargraph 0.47.2 → 0.50.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/FUNDING.yml +1 -0
- data/.github/workflows/rspec.yml +1 -1
- data/CHANGELOG.md +40 -0
- data/LICENSE +1 -1
- data/README.md +9 -3
- data/SPONSORS.md +4 -4
- data/lib/solargraph/api_map/store.rb +13 -1
- data/lib/solargraph/api_map.rb +30 -12
- data/lib/solargraph/cache.rb +53 -0
- data/lib/solargraph/complex_type/type_methods.rb +10 -6
- data/lib/solargraph/complex_type/unique_type.rb +57 -0
- data/lib/solargraph/complex_type.rb +32 -3
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -0
- data/lib/solargraph/diagnostics/rubocop.rb +17 -3
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
- data/lib/solargraph/language_server/host/cataloger.rb +1 -1
- data/lib/solargraph/language_server/host.rb +22 -18
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/library.rb +25 -20
- data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +12 -2
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +24 -3
- data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -1
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +13 -2
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -8
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +14 -3
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
- data/lib/solargraph/pin/base.rb +5 -2
- data/lib/solargraph/pin/base_variable.rb +1 -1
- data/lib/solargraph/pin/conversions.rb +2 -6
- data/lib/solargraph/pin/method.rb +100 -10
- data/lib/solargraph/pin/namespace.rb +4 -1
- data/lib/solargraph/pin/parameter.rb +8 -3
- data/lib/solargraph/pin/signature.rb +23 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/rbs_map/conversions.rb +394 -0
- data/lib/solargraph/rbs_map/core_fills.rb +61 -0
- data/lib/solargraph/rbs_map/core_map.rb +38 -0
- data/lib/solargraph/rbs_map/core_signs.rb +33 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
- data/lib/solargraph/rbs_map.rb +73 -0
- data/lib/solargraph/shell.rb +50 -32
- data/lib/solargraph/source/chain/call.rb +35 -24
- data/lib/solargraph/source/chain.rb +22 -7
- data/lib/solargraph/source_map/clip.rb +5 -0
- data/lib/solargraph/source_map/mapper.rb +8 -4
- data/lib/solargraph/type_checker.rb +71 -65
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace.rb +11 -14
- data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
- data/lib/solargraph/yard_map.rb +35 -194
- data/lib/solargraph.rb +2 -2
- data/solargraph.gemspec +11 -6
- metadata +46 -37
- data/.travis.yml +0 -19
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/yardoc/2.2.2.tar.gz +0 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
class RbsMap
|
5
|
+
# Ruby core pins
|
6
|
+
#
|
7
|
+
class CoreMap
|
8
|
+
include Conversions
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
cache = Cache.load('core.ser')
|
12
|
+
if cache
|
13
|
+
pins.replace cache
|
14
|
+
else
|
15
|
+
loader = RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: true))
|
16
|
+
environment = RBS::Environment.from_loader(loader).resolve_type_names
|
17
|
+
environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
|
18
|
+
pins.concat RbsMap::CoreFills::ALL
|
19
|
+
processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
|
20
|
+
pins.replace processed
|
21
|
+
|
22
|
+
Cache.save('core.ser', pins)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_def_to_sigs decl, pin
|
27
|
+
stubs = CoreSigns.sign(pin.path)
|
28
|
+
return super unless stubs
|
29
|
+
stubs.map do |stub|
|
30
|
+
Pin::Signature.new(
|
31
|
+
[],
|
32
|
+
ComplexType.try_parse(stub.return_type)
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class RbsMap
|
3
|
+
module CoreSigns
|
4
|
+
Override = Pin::Reference::Override
|
5
|
+
|
6
|
+
class Stub
|
7
|
+
attr_reader :parameters
|
8
|
+
|
9
|
+
attr_reader :return_type
|
10
|
+
|
11
|
+
def initialize parameters, return_type
|
12
|
+
@parameters = parameters
|
13
|
+
@return_type = return_type
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
SIGNATURE_MAP = {
|
18
|
+
'Object#class' => [
|
19
|
+
Stub.new(
|
20
|
+
[],
|
21
|
+
'Class<self>'
|
22
|
+
)
|
23
|
+
]
|
24
|
+
}
|
25
|
+
|
26
|
+
# @param path [String]
|
27
|
+
# @return [Array<Stub>]
|
28
|
+
def self.sign path
|
29
|
+
SIGNATURE_MAP[path]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
module Solargraph
|
7
|
+
class RbsMap
|
8
|
+
# Ruby stdlib pins
|
9
|
+
#
|
10
|
+
class StdlibMap < RbsMap
|
11
|
+
# @type [Hash{String => RbsMap}]
|
12
|
+
@stdlib_maps_hash = {}
|
13
|
+
|
14
|
+
# @param library [String]
|
15
|
+
def initialize library
|
16
|
+
cache = Cache.load('stdlib', "#{library}.ser")
|
17
|
+
if cache
|
18
|
+
pins.replace cache
|
19
|
+
else
|
20
|
+
super
|
21
|
+
Cache.save('stdlib', "#{library}.ser", pins)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param library [String]
|
26
|
+
# @return [StdlibMap]
|
27
|
+
def self.load library
|
28
|
+
@stdlib_maps_hash[library] ||= StdlibMap.new(library)
|
29
|
+
end
|
30
|
+
|
31
|
+
def repository
|
32
|
+
@repository ||= RBS::Repository.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rbs'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
module Solargraph
|
7
|
+
class RbsMap
|
8
|
+
autoload :Conversions, 'solargraph/rbs_map/conversions'
|
9
|
+
autoload :CoreMap, 'solargraph/rbs_map/core_map'
|
10
|
+
autoload :CoreFills, 'solargraph/rbs_map/core_fills'
|
11
|
+
autoload :CoreSigns, 'solargraph/rbs_map/core_signs'
|
12
|
+
autoload :StdlibMap, 'solargraph/rbs_map/stdlib_map'
|
13
|
+
|
14
|
+
include Conversions
|
15
|
+
|
16
|
+
# @type [Hash{String => RbsMap}]
|
17
|
+
@@rbs_maps_hash = {}
|
18
|
+
|
19
|
+
attr_reader :library
|
20
|
+
|
21
|
+
# @param library [String]
|
22
|
+
def initialize library
|
23
|
+
@library = library
|
24
|
+
loader = RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
25
|
+
add_library loader, library
|
26
|
+
return unless resolved?
|
27
|
+
environment = RBS::Environment.from_loader(loader).resolve_type_names
|
28
|
+
environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def path_pin path
|
32
|
+
pins.find { |p| p.path == path }
|
33
|
+
end
|
34
|
+
|
35
|
+
def path_pins path
|
36
|
+
pins.select { |p| p.path == path }
|
37
|
+
end
|
38
|
+
|
39
|
+
def resolved?
|
40
|
+
@resolved
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param library [String]
|
44
|
+
# @return [RbsMap]
|
45
|
+
def self.load library
|
46
|
+
@@rbs_maps_hash[library] ||= RbsMap.new(library)
|
47
|
+
end
|
48
|
+
|
49
|
+
def repository
|
50
|
+
@repository ||= RBS::Repository.new(no_stdlib: true)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# @param loader [RBS::EnvironmentLoader]
|
56
|
+
# @param library [String]
|
57
|
+
# @return [Boolean] true if adding the library succeeded
|
58
|
+
def add_library loader, library
|
59
|
+
@resolved = if loader.has_library?(library: library, version: nil)
|
60
|
+
loader.add library: library
|
61
|
+
Solargraph.logger.info "#{short_name} successfully loaded library #{library}"
|
62
|
+
true
|
63
|
+
else
|
64
|
+
Solargraph.logger.info "#{short_name} failed to load library #{library}"
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def short_name
|
70
|
+
self.class.name.split('::').last
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -71,43 +71,46 @@ module Solargraph
|
|
71
71
|
STDOUT.puts "Configuration file initialized."
|
72
72
|
end
|
73
73
|
|
74
|
-
desc 'download-core [VERSION]', 'Download core documentation'
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
desc 'list-cores', 'List the local documentation versions'
|
74
|
+
desc 'download-core [VERSION]', 'Download core documentation [deprecated]', hide: true
|
75
|
+
long_desc %(
|
76
|
+
The `download-core` command is deprecated. Current versions of Solargraph
|
77
|
+
use RBS for core and stdlib documentation.
|
78
|
+
)
|
79
|
+
# @deprecated
|
80
|
+
def download_core _version = nil
|
81
|
+
puts 'The `download-core` command is deprecated.'
|
82
|
+
puts 'Current versions of Solargraph use RBS for core and stdlib documentation.'
|
83
|
+
end
|
84
|
+
|
85
|
+
desc 'list-cores', 'List the local documentation versions [deprecated]', hide: true
|
86
|
+
long_desc %(
|
87
|
+
The `list-cores` command is deprecated. Current versions of Solargraph use
|
88
|
+
RBS for core and stdlib documentation.
|
89
|
+
)
|
90
|
+
# @deprecated
|
92
91
|
def list_cores
|
93
|
-
puts
|
92
|
+
puts 'The `list-cores` command is deprecated.'
|
93
|
+
puts 'Current versions of Solargraph use RBS for core and stdlib documentation.'
|
94
94
|
end
|
95
95
|
|
96
|
-
desc 'available-cores', 'List available documentation versions'
|
96
|
+
desc 'available-cores', 'List available documentation versions [deprecated]', hide: true
|
97
|
+
long_desc %(
|
98
|
+
The `available-cores` command is deprecated. Current versions of Solargraph
|
99
|
+
use RBS for core and stdlib documentation.
|
100
|
+
)
|
101
|
+
# @deprecated
|
97
102
|
def available_cores
|
98
|
-
puts
|
103
|
+
puts 'The `available-cores` command is deprecated.'
|
104
|
+
puts 'Current versions of Solargraph use RBS for core and stdlib documentation.'
|
99
105
|
end
|
100
106
|
|
101
107
|
desc 'clear', 'Delete all cached documentation'
|
102
108
|
long_desc %(
|
103
109
|
This command will delete all core and gem documentation from the cache.
|
104
|
-
You can also delete specific gem caches with the `uncache` command or
|
105
|
-
update documentation for specific Ruby versions with the `download-core`
|
106
|
-
command.
|
107
110
|
)
|
108
111
|
def clear
|
109
112
|
puts "Deleting the cached documentation"
|
110
|
-
Solargraph::
|
113
|
+
Solargraph::Cache.clear
|
111
114
|
end
|
112
115
|
map 'clear-cache' => :clear
|
113
116
|
map 'clear-cores' => :clear
|
@@ -191,18 +194,33 @@ module Solargraph
|
|
191
194
|
puts "Scanned #{directory} (#{api_map.pins.length} pins) in #{time.real} seconds."
|
192
195
|
end
|
193
196
|
|
194
|
-
desc '
|
197
|
+
desc 'list', 'List the files in the workspace and the total count'
|
198
|
+
option :count, type: :boolean, aliases: :c, desc: 'Display the file count only', default: false
|
199
|
+
option :directory, type: :string, aliases: :d, desc: 'The directory to read', default: '.'
|
200
|
+
def list
|
201
|
+
workspace = Solargraph::Workspace.new(options[:directory])
|
202
|
+
unless options[:count]
|
203
|
+
workspace.filenames.each { |f| puts f }
|
204
|
+
end
|
205
|
+
puts "#{workspace.filenames.length} files total."
|
206
|
+
end
|
207
|
+
|
208
|
+
desc 'bundle', 'Generate documentation for bundled gems [deprecated]', hide: true
|
209
|
+
long_desc %(
|
210
|
+
The `bundle` command is deprecated. Solargraph currently uses RBS instead.
|
211
|
+
)
|
195
212
|
option :directory, type: :string, aliases: :d, desc: 'The workspace directory', default: '.'
|
196
213
|
option :rebuild, type: :boolean, aliases: :r, desc: 'Rebuild existing documentation', default: false
|
197
214
|
def bundle
|
198
|
-
|
215
|
+
puts 'The `bundle` command is deprecated. Solargraph currently uses RBS instead.'
|
199
216
|
end
|
200
217
|
|
201
|
-
desc 'rdoc GEM [VERSION]', 'Use RDoc to cache documentation'
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
218
|
+
desc 'rdoc GEM [VERSION]', 'Use RDoc to cache documentation [deprecated]', hide: true
|
219
|
+
long_desc %(
|
220
|
+
The `rdoc` command is deprecated. Solargraph currently uses RBS instead.
|
221
|
+
)
|
222
|
+
def rdoc _gem, _version = '>= 0'
|
223
|
+
puts 'The `rdoc` command is deprecated. Solargraph currently uses RBS instead.'
|
206
224
|
end
|
207
225
|
|
208
226
|
private
|
@@ -35,7 +35,10 @@ module Solargraph
|
|
35
35
|
[]
|
36
36
|
end
|
37
37
|
return inferred_pins(found, api_map, name_pin.context, locals) unless found.empty?
|
38
|
-
|
38
|
+
# @param [ComplexType::UniqueType]
|
39
|
+
pins = name_pin.binder.each_unique_type.flat_map do |context|
|
40
|
+
api_map.get_method_stack(context.namespace, word, scope: context.scope)
|
41
|
+
end
|
39
42
|
return [] if pins.empty?
|
40
43
|
inferred_pins(pins, api_map, name_pin.context, locals)
|
41
44
|
end
|
@@ -49,36 +52,32 @@ module Solargraph
|
|
49
52
|
# @return [Array<Pin::Base>]
|
50
53
|
def inferred_pins pins, api_map, context, locals
|
51
54
|
result = pins.map do |p|
|
52
|
-
|
55
|
+
next p unless p.is_a?(Pin::Method)
|
56
|
+
overloads = p.signatures
|
53
57
|
# next p if overloads.empty?
|
54
58
|
type = ComplexType::UNDEFINED
|
55
|
-
# @param [YARD::Tags::OverloadTag]
|
56
59
|
overloads.each do |ol|
|
57
|
-
next unless arguments_match(arguments, ol
|
58
|
-
next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
|
60
|
+
next unless arguments_match(arguments, ol)
|
61
|
+
# next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
|
59
62
|
match = true
|
60
63
|
arguments.each_with_index do |arg, idx|
|
61
|
-
achain = arguments[idx]
|
62
|
-
next if achain.nil?
|
63
64
|
param = ol.parameters[idx]
|
64
65
|
if param.nil?
|
65
|
-
match = false unless ol.parameters.
|
66
|
+
match = false unless ol.parameters.any?(&:restarg?)
|
66
67
|
break
|
67
68
|
end
|
68
|
-
|
69
|
-
next if par.nil? || par.types.nil? || par.types.empty?
|
70
|
-
atype = achain.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
71
|
-
other = ComplexType.try_parse(*par.types)
|
69
|
+
atype = arg.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
72
70
|
# @todo Weak type comparison
|
73
|
-
unless atype.tag ==
|
71
|
+
# unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
|
72
|
+
unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name)
|
74
73
|
match = false
|
75
74
|
break
|
76
75
|
end
|
77
76
|
end
|
78
77
|
if match
|
79
|
-
type = extra_return_type(
|
78
|
+
type = extra_return_type(p.docstring, context)
|
80
79
|
break if type
|
81
|
-
type =
|
80
|
+
type = with_params(ol.return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if ol.return_type.defined?
|
82
81
|
type ||= ComplexType::UNDEFINED
|
83
82
|
end
|
84
83
|
break if type.defined?
|
@@ -107,9 +106,13 @@ module Solargraph
|
|
107
106
|
p
|
108
107
|
end
|
109
108
|
result.map do |pin|
|
110
|
-
|
111
|
-
|
112
|
-
|
109
|
+
if pin.path == 'Class#new' && context.tag != 'Class'
|
110
|
+
pin.proxy(ComplexType.try_parse(context.namespace))
|
111
|
+
else
|
112
|
+
next pin if pin.return_type.undefined?
|
113
|
+
selfy = pin.return_type.self_to(context.tag)
|
114
|
+
selfy == pin.return_type ? pin : pin.proxy(selfy)
|
115
|
+
end
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
@@ -180,14 +183,15 @@ module Solargraph
|
|
180
183
|
end
|
181
184
|
|
182
185
|
# @param arguments [Array<Chain>]
|
183
|
-
# @param
|
186
|
+
# @param signature [Pin::Signature]
|
184
187
|
# @return [Boolean]
|
185
|
-
def arguments_match arguments,
|
188
|
+
def arguments_match arguments, signature
|
189
|
+
parameters = signature.parameters
|
186
190
|
argcount = arguments.length
|
187
|
-
# argcount -= 1 if !arguments.empty? && arguments.last.links.first.word.start_with?('&')
|
188
191
|
parcount = parameters.length
|
189
|
-
parcount -= 1 if !parameters.empty? && parameters.last.
|
190
|
-
return false if
|
192
|
+
parcount -= 1 if !parameters.empty? && parameters.last.block?
|
193
|
+
return false if signature.block? && !with_block?
|
194
|
+
return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
|
191
195
|
true
|
192
196
|
end
|
193
197
|
|
@@ -195,9 +199,16 @@ module Solargraph
|
|
195
199
|
# @param name_pin [Pin::Base]
|
196
200
|
# @return [Array<Pin::Base>]
|
197
201
|
def super_pins api_map, name_pin
|
198
|
-
pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.scope)
|
202
|
+
pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
|
199
203
|
pins.reject{|p| p.path == name_pin.path}
|
200
204
|
end
|
205
|
+
|
206
|
+
# @param type [ComplexType]
|
207
|
+
# @param context [ComplexType]
|
208
|
+
def with_params type, context
|
209
|
+
return type unless type.to_s.include?('$')
|
210
|
+
ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:tag).join(', ')).gsub('<>', ''))
|
211
|
+
end
|
201
212
|
end
|
202
213
|
end
|
203
214
|
end
|
@@ -63,11 +63,11 @@ module Solargraph
|
|
63
63
|
working_pin = name_pin
|
64
64
|
links[0..-2].each do |link|
|
65
65
|
pins = link.resolve(api_map, working_pin, locals)
|
66
|
-
type = infer_first_defined(pins, working_pin, api_map)
|
66
|
+
type = infer_first_defined(pins, working_pin, api_map, locals)
|
67
67
|
return [] if type.undefined?
|
68
68
|
working_pin = Pin::ProxyType.anonymous(type)
|
69
69
|
end
|
70
|
-
links.last.last_context =
|
70
|
+
links.last.last_context = name_pin
|
71
71
|
links.last.resolve(api_map, working_pin, locals)
|
72
72
|
end
|
73
73
|
|
@@ -76,8 +76,12 @@ module Solargraph
|
|
76
76
|
# @param locals [Array<Pin::Base>]
|
77
77
|
# @return [ComplexType]
|
78
78
|
def infer api_map, name_pin, locals
|
79
|
+
from_here = base.infer(api_map, name_pin, locals) unless links.length == 1
|
80
|
+
if from_here
|
81
|
+
name_pin = name_pin.proxy(from_here)
|
82
|
+
end
|
79
83
|
pins = define(api_map, name_pin, locals)
|
80
|
-
type = infer_first_defined(pins, links.last.last_context, api_map)
|
84
|
+
type = infer_first_defined(pins, links.last.last_context, api_map, locals)
|
81
85
|
maybe_nil(type)
|
82
86
|
end
|
83
87
|
|
@@ -110,9 +114,10 @@ module Solargraph
|
|
110
114
|
private
|
111
115
|
|
112
116
|
# @param pins [Array<Pin::Base>]
|
117
|
+
# @param context [Pin::Base]
|
113
118
|
# @param api_map [ApiMap]
|
114
119
|
# @return [ComplexType]
|
115
|
-
def infer_first_defined pins, context, api_map
|
120
|
+
def infer_first_defined pins, context, api_map, locals
|
116
121
|
possibles = []
|
117
122
|
pins.each do |pin|
|
118
123
|
# Avoid infinite recursion
|
@@ -121,8 +126,18 @@ module Solargraph
|
|
121
126
|
type = pin.typify(api_map)
|
122
127
|
@@inference_stack.pop
|
123
128
|
if type.defined?
|
124
|
-
|
125
|
-
|
129
|
+
if type.parameterized?
|
130
|
+
type = type.resolve_parameters(pin.closure, context)
|
131
|
+
# idx = pin.closure.parameters.index(type.subtypes.first.name)
|
132
|
+
# next if idx.nil?
|
133
|
+
# param_type = context.return_type.all_params[idx]
|
134
|
+
# next unless param_type
|
135
|
+
# type = ComplexType.try_parse(param_type.to_s)
|
136
|
+
end
|
137
|
+
if type.defined?
|
138
|
+
possibles.push type
|
139
|
+
break if pin.is_a?(Pin::Method)
|
140
|
+
end
|
126
141
|
end
|
127
142
|
end
|
128
143
|
if possibles.empty?
|
@@ -147,7 +162,7 @@ module Solargraph
|
|
147
162
|
sorted = possibles.map { |t| t.rooted? ? "::#{t}" : t.to_s }.sort { |a, _| a == 'nil' ? 1 : 0 }
|
148
163
|
ComplexType.parse(*sorted)
|
149
164
|
else
|
150
|
-
possibles.
|
165
|
+
ComplexType.parse(possibles.map(&:to_s).join(', '))
|
151
166
|
end
|
152
167
|
return type if context.nil? || context.return_type.undefined?
|
153
168
|
type.self_to(context.return_type.namespace)
|
@@ -43,6 +43,11 @@ module Solargraph
|
|
43
43
|
# @return [ComplexType]
|
44
44
|
def infer
|
45
45
|
result = cursor.chain.infer(api_map, block, locals)
|
46
|
+
if result.tag == 'Class'
|
47
|
+
# HACK: Exception to return Object from Class#new
|
48
|
+
dfn = cursor.chain.define(api_map, block, locals).first
|
49
|
+
return ComplexType.try_parse('Object') if dfn && dfn.path == 'Class#new'
|
50
|
+
end
|
46
51
|
return result unless result.tag == 'self'
|
47
52
|
ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
|
48
53
|
end
|
@@ -12,7 +12,7 @@ module Solargraph
|
|
12
12
|
|
13
13
|
private_class_method :new
|
14
14
|
|
15
|
-
|
15
|
+
DIRECTIVE_REGEXP = /(@\!method|@\!attribute|@\!visibility|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
|
16
16
|
|
17
17
|
# Generate the data.
|
18
18
|
#
|
@@ -24,6 +24,8 @@ module Solargraph
|
|
24
24
|
@code = source.code
|
25
25
|
@comments = source.comments
|
26
26
|
@pins, @locals = Parser.map(source)
|
27
|
+
@pins.each { |p| p.source = :code }
|
28
|
+
@locals.each { |l| l.source = :code }
|
27
29
|
process_comment_directives
|
28
30
|
[@pins, @locals]
|
29
31
|
# rescue Exception => e
|
@@ -63,7 +65,7 @@ module Solargraph
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def process_comment source_position, comment_position, comment
|
66
|
-
return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~
|
68
|
+
return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
|
67
69
|
cmnt = remove_inline_comment_hashes(comment)
|
68
70
|
parse = Solargraph::Source.parse_docstring(cmnt)
|
69
71
|
last_line = 0
|
@@ -196,6 +198,8 @@ module Solargraph
|
|
196
198
|
namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
|
197
199
|
when 'override'
|
198
200
|
pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
|
201
|
+
when 'macro'
|
202
|
+
# @todo Handle macros
|
199
203
|
end
|
200
204
|
end
|
201
205
|
|
@@ -209,7 +213,7 @@ module Solargraph
|
|
209
213
|
started = false
|
210
214
|
comment.lines.each { |l|
|
211
215
|
# Trim the comment and minimum leading whitespace
|
212
|
-
p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(
|
216
|
+
p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
|
213
217
|
if num.nil? && !p.strip.empty?
|
214
218
|
num = p.index(/[^ ]/)
|
215
219
|
started = true
|
@@ -224,7 +228,7 @@ module Solargraph
|
|
224
228
|
|
225
229
|
# @return [void]
|
226
230
|
def process_comment_directives
|
227
|
-
return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~
|
231
|
+
return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
|
228
232
|
code_lines = @code.lines
|
229
233
|
@source.associated_comments.each do |line, comments|
|
230
234
|
src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
|