solargraph 0.39.16 → 0.40.3
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/.travis.yml +4 -8
- data/CHANGELOG.md +998 -0
- data/SPONSORS.md +1 -0
- data/lib/solargraph.rb +2 -4
- data/lib/solargraph/api_map.rb +61 -63
- data/lib/solargraph/api_map/cache.rb +2 -2
- data/lib/solargraph/api_map/store.rb +3 -7
- data/lib/solargraph/{bundle.rb → bench.rb} +6 -2
- data/lib/solargraph/compat.rb +14 -0
- data/lib/solargraph/convention.rb +13 -4
- data/lib/solargraph/convention/base.rb +16 -8
- data/lib/solargraph/convention/gemfile.rb +2 -5
- data/lib/solargraph/convention/gemspec.rb +3 -6
- data/lib/solargraph/convention/rspec.rb +3 -6
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -20
- data/lib/solargraph/environ.rb +11 -6
- data/lib/solargraph/language_server/host.rb +5 -0
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +6 -1
- data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/formatting.rb +47 -20
- data/lib/solargraph/library.rb +6 -8
- data/lib/solargraph/parser/legacy/node_methods.rb +9 -0
- data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +1 -1
- data/lib/solargraph/parser/legacy/node_processors/send_node.rb +34 -22
- data/lib/solargraph/parser/node_processor/base.rb +3 -0
- data/lib/solargraph/parser/rubyvm/node_methods.rb +18 -1
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +1 -1
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +1 -1
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +38 -28
- data/lib/solargraph/pin.rb +0 -3
- data/lib/solargraph/pin/common.rb +1 -1
- data/lib/solargraph/pin/conversions.rb +1 -1
- data/lib/solargraph/pin/documenting.rb +3 -9
- data/lib/solargraph/pin/method.rb +141 -7
- data/lib/solargraph/pin/method_alias.rb +1 -1
- data/lib/solargraph/position.rb +2 -14
- data/lib/solargraph/source.rb +10 -6
- data/lib/solargraph/source/chain.rb +3 -3
- data/lib/solargraph/source_map.rb +4 -1
- data/lib/solargraph/source_map/clip.rb +3 -2
- data/lib/solargraph/source_map/mapper.rb +10 -6
- data/lib/solargraph/type_checker.rb +50 -44
- data/lib/solargraph/type_checker/checks.rb +5 -1
- data/lib/solargraph/type_checker/param_def.rb +1 -1
- data/lib/solargraph/type_checker/rules.rb +5 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +15 -0
- data/lib/solargraph/yard_map.rb +38 -47
- data/lib/solargraph/yard_map/core_fills.rb +185 -0
- data/lib/solargraph/yard_map/helpers.rb +16 -0
- data/lib/solargraph/yard_map/mapper.rb +11 -5
- data/lib/solargraph/{pin/yard_pin/constant.rb → yard_map/mapper/to_constant.rb} +6 -6
- data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
- data/lib/solargraph/{pin/yard_pin/namespace.rb → yard_map/mapper/to_namespace.rb} +6 -6
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +1 -1
- data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
- data/lib/solargraph/{pin/yard_pin/method.rb → yard_map/to_method.rb} +29 -30
- data/solargraph.gemspec +5 -5
- metadata +22 -36
- data/lib/solargraph/core_fills.rb +0 -164
- data/lib/solargraph/pin/attribute.rb +0 -49
- data/lib/solargraph/pin/base_method.rb +0 -149
- data/lib/solargraph/pin/yard_pin.rb +0 -12
- data/lib/solargraph/pin/yard_pin/yard_mixin.rb +0 -20
- data/lib/solargraph/stdlib_fills.rb +0 -40
- data/travis-bundler.rb +0 -11
@@ -27,6 +27,7 @@ module Solargraph
|
|
27
27
|
@region = region
|
28
28
|
@pins = pins
|
29
29
|
@locals = locals
|
30
|
+
@processed_children = false
|
30
31
|
end
|
31
32
|
|
32
33
|
# Subclasses should override this method to generate new pins.
|
@@ -41,6 +42,8 @@ module Solargraph
|
|
41
42
|
# @param subregion [Region]
|
42
43
|
# @return [void]
|
43
44
|
def process_children subregion = region
|
45
|
+
return if @processed_children
|
46
|
+
@processed_children = true
|
44
47
|
node.children.each do |child|
|
45
48
|
next unless Parser.is_ast_node?(child)
|
46
49
|
NodeProcessor.process(child, subregion, pins, locals)
|
@@ -90,7 +90,9 @@ module Solargraph
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def convert_hash node
|
93
|
-
return {} unless node?(node) && node.type == :HASH
|
93
|
+
return {} unless node?(node) && node.type == :HASH
|
94
|
+
return convert_hash(node.children[0].children[1]) if splatted_hash?(node)
|
95
|
+
return {} unless node?(node.children[0])
|
94
96
|
result = {}
|
95
97
|
index = 0
|
96
98
|
until index > node.children[0].children.length - 2
|
@@ -103,6 +105,21 @@ module Solargraph
|
|
103
105
|
result
|
104
106
|
end
|
105
107
|
|
108
|
+
def splatted_hash? node
|
109
|
+
splatted_node?(node) && node.children[0].children[1].type == :HASH
|
110
|
+
end
|
111
|
+
|
112
|
+
def splatted_node? node
|
113
|
+
node?(node.children[0]) &&
|
114
|
+
[:ARRAY, :LIST].include?(node.children[0].type) &&
|
115
|
+
node.children[0].children[0].nil? &&
|
116
|
+
node?(node.children[0].children[1])
|
117
|
+
end
|
118
|
+
|
119
|
+
def splatted_call? node
|
120
|
+
splatted_node?(node) && node.children[0].children[1].type != :HASH
|
121
|
+
end
|
122
|
+
|
106
123
|
def node? node
|
107
124
|
node.is_a?(RubyVM::AbstractSyntaxTree::Node)
|
108
125
|
end
|
@@ -6,7 +6,7 @@ module Solargraph
|
|
6
6
|
module NodeProcessors
|
7
7
|
class ArgsNode < Parser::NodeProcessor::Base
|
8
8
|
def process
|
9
|
-
if region.closure.is_a?(Pin::
|
9
|
+
if region.closure.is_a?(Pin::Method) || region.closure.is_a?(Pin::Block)
|
10
10
|
if region.lvars[0].nil?
|
11
11
|
node.children[0].times do |i|
|
12
12
|
locals.push Solargraph::Pin::Parameter.new(
|
@@ -19,7 +19,7 @@ module Solargraph
|
|
19
19
|
if region.visibility == :module_function
|
20
20
|
rng = Range.from_node(node)
|
21
21
|
named_path = named_path_pin(rng.start)
|
22
|
-
if named_path.is_a?(Pin::
|
22
|
+
if named_path.is_a?(Pin::Method)
|
23
23
|
pins.push Solargraph::Pin::InstanceVariable.new(
|
24
24
|
location: loc,
|
25
25
|
closure: Pin::Namespace.new(type: :module, closure: region.closure.closure, name: region.closure.name),
|
@@ -9,21 +9,7 @@ module Solargraph
|
|
9
9
|
|
10
10
|
def process
|
11
11
|
if [:private, :public, :protected].include?(node.children[0])
|
12
|
-
|
13
|
-
node.children.last.children[0..-2].each do |child|
|
14
|
-
# next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
|
15
|
-
next unless child.type == :LIT || child.type == :STR
|
16
|
-
name = child.children[0].to_s
|
17
|
-
matches = pins.select{ |pin| pin.is_a?(Pin::BaseMethod) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
|
18
|
-
matches.each do |pin|
|
19
|
-
# @todo Smelly instance variable access
|
20
|
-
pin.instance_variable_set(:@visibility, node.children[0])
|
21
|
-
end
|
22
|
-
end
|
23
|
-
else
|
24
|
-
# @todo Smelly instance variable access
|
25
|
-
region.instance_variable_set(:@visibility, node.children[0])
|
26
|
-
end
|
12
|
+
process_visibility
|
27
13
|
elsif node.children[0] == :module_function
|
28
14
|
process_module_function
|
29
15
|
elsif node.children[0] == :require
|
@@ -33,8 +19,7 @@ module Solargraph
|
|
33
19
|
elsif node.children[0] == :alias_method
|
34
20
|
process_alias_method
|
35
21
|
elsif node.children[0] == :private_class_method
|
36
|
-
|
37
|
-
return if process_private_class_method
|
22
|
+
process_private_class_method
|
38
23
|
elsif [:attr_reader, :attr_writer, :attr_accessor].include?(node.children[0])
|
39
24
|
process_attribute
|
40
25
|
elsif node.children[0] == :include
|
@@ -53,6 +38,28 @@ module Solargraph
|
|
53
38
|
|
54
39
|
private
|
55
40
|
|
41
|
+
# @return [void]
|
42
|
+
def process_visibility
|
43
|
+
if node.type == :FCALL && Parser.is_ast_node?(node.children.last)
|
44
|
+
node.children.last.children[0..-2].each do |child|
|
45
|
+
# next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
|
46
|
+
if child.type == :LIT || child.type == :STR
|
47
|
+
name = child.children[0].to_s
|
48
|
+
matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
|
49
|
+
matches.each do |pin|
|
50
|
+
# @todo Smelly instance variable access
|
51
|
+
pin.instance_variable_set(:@visibility, node.children[0])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
process_children region.update(visibility: node.children[0])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
# @todo Smelly instance variable access
|
59
|
+
region.instance_variable_set(:@visibility, node.children[0])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
56
63
|
# @return [void]
|
57
64
|
def process_attribute
|
58
65
|
return unless Parser.is_ast_node?(node.children[1])
|
@@ -62,26 +69,30 @@ module Solargraph
|
|
62
69
|
clos = region.closure
|
63
70
|
cmnt = comments_for(node)
|
64
71
|
if node.children[0] == :attr_reader || node.children[0] == :attr_accessor
|
65
|
-
pins.push Solargraph::Pin::
|
72
|
+
pins.push Solargraph::Pin::Method.new(
|
66
73
|
location: loc,
|
67
74
|
closure: clos,
|
68
75
|
name: a.children[0].to_s,
|
69
76
|
comments: cmnt,
|
70
|
-
access: :reader,
|
71
77
|
scope: region.scope || :instance,
|
72
|
-
visibility: region.visibility
|
78
|
+
visibility: region.visibility,
|
79
|
+
attribute: true
|
73
80
|
)
|
74
81
|
end
|
75
82
|
if node.children[0] == :attr_writer || node.children[0] == :attr_accessor
|
76
|
-
pins.push Solargraph::Pin::
|
83
|
+
pins.push Solargraph::Pin::Method.new(
|
77
84
|
location: loc,
|
78
85
|
closure: clos,
|
79
86
|
name: "#{a.children[0]}=",
|
80
87
|
comments: cmnt,
|
81
|
-
access: :writer,
|
82
88
|
scope: region.scope || :instance,
|
83
|
-
visibility: region.visibility
|
89
|
+
visibility: region.visibility,
|
90
|
+
attribute: true
|
84
91
|
)
|
92
|
+
pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
|
93
|
+
if pins.last.return_type.defined?
|
94
|
+
pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
|
95
|
+
end
|
85
96
|
end
|
86
97
|
end
|
87
98
|
end
|
@@ -166,7 +177,7 @@ module Solargraph
|
|
166
177
|
node.children.last.children[0..-2].each do |x|
|
167
178
|
next unless [:LIT, :STR].include?(x.type)
|
168
179
|
cn = x.children[0].to_s
|
169
|
-
ref = pins.select{|p|
|
180
|
+
ref = pins.select { |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == cn }.first
|
170
181
|
unless ref.nil?
|
171
182
|
pins.delete ref
|
172
183
|
mm = Solargraph::Pin::Method.new(
|
@@ -215,6 +226,7 @@ module Solargraph
|
|
215
226
|
|
216
227
|
# @return [void]
|
217
228
|
def process_private_constant
|
229
|
+
return unless Parser.is_ast_node?(node.children.last)
|
218
230
|
node.children.last.children[0..-2].each do |child|
|
219
231
|
if [:LIT, :STR].include?(child.type)
|
220
232
|
cn = child.children[0].to_s
|
@@ -242,20 +254,18 @@ module Solargraph
|
|
242
254
|
)
|
243
255
|
end
|
244
256
|
|
245
|
-
# @return [
|
257
|
+
# @return [void]
|
246
258
|
def process_private_class_method
|
247
259
|
return false unless Parser.is_ast_node?(node.children.last)
|
248
260
|
if node.children.last.children.first.type == :DEFN
|
249
261
|
process_children region.update(scope: :class, visibility: :private)
|
250
|
-
true
|
251
262
|
else
|
252
263
|
node.children.last.children[0..-2].each do |child|
|
253
264
|
if child.type == :LIT && child.children.first.is_a?(::Symbol)
|
254
265
|
sym_name = child.children.first.to_s
|
255
|
-
ref = pins.select{|p|
|
266
|
+
ref = pins.select { |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == sym_name }.first
|
256
267
|
# HACK: Smelly instance variable access
|
257
268
|
ref.instance_variable_set(:@visibility, :private) unless ref.nil?
|
258
|
-
false
|
259
269
|
end
|
260
270
|
end
|
261
271
|
end
|
data/lib/solargraph/pin.rb
CHANGED
@@ -9,10 +9,8 @@ module Solargraph
|
|
9
9
|
autoload :Common, 'solargraph/pin/common'
|
10
10
|
autoload :Conversions, 'solargraph/pin/conversions'
|
11
11
|
autoload :Base, 'solargraph/pin/base'
|
12
|
-
autoload :BaseMethod, 'solargraph/pin/base_method'
|
13
12
|
autoload :Method, 'solargraph/pin/method'
|
14
13
|
autoload :MethodAlias, 'solargraph/pin/method_alias'
|
15
|
-
autoload :Attribute, 'solargraph/pin/attribute'
|
16
14
|
autoload :BaseVariable, 'solargraph/pin/base_variable'
|
17
15
|
autoload :InstanceVariable, 'solargraph/pin/instance_variable'
|
18
16
|
autoload :ClassVariable, 'solargraph/pin/class_variable'
|
@@ -30,7 +28,6 @@ module Solargraph
|
|
30
28
|
autoload :Localized, 'solargraph/pin/localized'
|
31
29
|
autoload :ProxyType, 'solargraph/pin/proxy_type'
|
32
30
|
autoload :DuckMethod, 'solargraph/pin/duck_method'
|
33
|
-
autoload :YardPin, 'solargraph/pin/yard_pin'
|
34
31
|
autoload :Singleton, 'solargraph/pin/singleton'
|
35
32
|
autoload :KeywordParam, 'solargraph/pin/keyword_param'
|
36
33
|
|
@@ -54,7 +54,7 @@ module Solargraph
|
|
54
54
|
until here.nil?
|
55
55
|
if here.is_a?(Pin::Namespace)
|
56
56
|
return here.return_type
|
57
|
-
elsif here.is_a?(Pin::
|
57
|
+
elsif here.is_a?(Pin::Method)
|
58
58
|
if here.scope == :instance
|
59
59
|
return ComplexType.try_parse(here.context.namespace)
|
60
60
|
else
|
@@ -47,7 +47,7 @@ module Solargraph
|
|
47
47
|
# This property is not cached in an instance variable because it can
|
48
48
|
# change when pins get proxied.
|
49
49
|
detail = String.new
|
50
|
-
detail += "(#{parameters.map(&:full).join(', ')}) " unless !is_a?(Pin::
|
50
|
+
detail += "(#{parameters.map(&:full).join(', ')}) " unless !is_a?(Pin::Method) || parameters.empty?
|
51
51
|
detail += "=#{probed? ? '~' : (proxied? ? '^' : '>')} #{return_type.to_s}" unless return_type.undefined?
|
52
52
|
detail.strip!
|
53
53
|
return nil if detail.empty?
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'kramdown'
|
4
|
+
require 'kramdown-parser-gfm'
|
4
5
|
require 'yard'
|
5
6
|
require 'reverse_markdown'
|
6
7
|
require 'solargraph/converters/dl'
|
@@ -8,9 +9,6 @@ require 'solargraph/converters/dt'
|
|
8
9
|
require 'solargraph/converters/dd'
|
9
10
|
require 'solargraph/converters/misc'
|
10
11
|
|
11
|
-
# HACK: Setting :html_parser through `Maruku.new` does not work
|
12
|
-
MaRuKu::Globals[:html_parser] = 'nokogiri'
|
13
|
-
|
14
12
|
module Solargraph
|
15
13
|
module Pin
|
16
14
|
# A module to add the Pin::Base#documentation method.
|
@@ -41,11 +39,7 @@ module Solargraph
|
|
41
39
|
|
42
40
|
def to_s
|
43
41
|
return "\n```ruby\n#{@plaintext}#{@plaintext.end_with?("\n") ? '' : "\n"}```\n\n" if code?
|
44
|
-
ReverseMarkdown.convert unescape_brackets(
|
45
|
-
rescue MaRuKu::Exception
|
46
|
-
# Maruku exceptions usually indicate that the documentation is in
|
47
|
-
# RDoc syntax.
|
48
|
-
ReverseMarkdown.convert YARD::Templates::Helpers::Markup::RDocMarkup.new(@plaintext).to_html
|
42
|
+
ReverseMarkdown.convert unescape_brackets(Kramdown::Document.new(escape_brackets(@plaintext), input: 'GFM').to_html)
|
49
43
|
end
|
50
44
|
|
51
45
|
private
|
@@ -2,18 +2,29 @@
|
|
2
2
|
|
3
3
|
module Solargraph
|
4
4
|
module Pin
|
5
|
-
class
|
5
|
+
# The base class for method and attribute pins.
|
6
|
+
#
|
7
|
+
class Method < Closure
|
6
8
|
include Solargraph::Parser::NodeMethods
|
7
9
|
|
8
10
|
# @return [Array<Pin::Parameter>]
|
9
11
|
attr_reader :parameters
|
10
12
|
|
11
|
-
# @
|
12
|
-
|
13
|
-
|
13
|
+
# @return [::Symbol] :public, :private, or :protected
|
14
|
+
attr_reader :visibility
|
15
|
+
|
16
|
+
# @return [Parser::AST::Node]
|
17
|
+
attr_reader :node
|
18
|
+
|
19
|
+
# @param visibility [::Symbol] :public, :protected, or :private
|
20
|
+
# @param explicit [Boolean]
|
21
|
+
def initialize visibility: :public, explicit: true, parameters: [], node: nil, attribute: false, **splat
|
14
22
|
super(**splat)
|
23
|
+
@visibility = visibility
|
24
|
+
@explicit = explicit
|
15
25
|
@parameters = parameters
|
16
26
|
@node = node
|
27
|
+
@attribute = attribute
|
17
28
|
end
|
18
29
|
|
19
30
|
# @return [Array<String>]
|
@@ -22,11 +33,70 @@ module Solargraph
|
|
22
33
|
end
|
23
34
|
|
24
35
|
def completion_item_kind
|
25
|
-
Solargraph::LanguageServer::CompletionItemKinds::METHOD
|
36
|
+
attribute? ? Solargraph::LanguageServer::CompletionItemKinds::PROPERTY : Solargraph::LanguageServer::CompletionItemKinds::METHOD
|
26
37
|
end
|
27
38
|
|
28
39
|
def symbol_kind
|
29
|
-
LanguageServer::SymbolKinds::METHOD
|
40
|
+
attribute? ? Solargraph::LanguageServer::SymbolKinds::PROPERTY : LanguageServer::SymbolKinds::METHOD
|
41
|
+
end
|
42
|
+
|
43
|
+
def return_type
|
44
|
+
@return_type ||= generate_complex_type
|
45
|
+
end
|
46
|
+
|
47
|
+
def path
|
48
|
+
@path ||= "#{namespace}#{(scope == :instance ? '#' : '.')}#{name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def typify api_map
|
52
|
+
decl = super
|
53
|
+
return decl unless decl.undefined?
|
54
|
+
type = see_reference(api_map) || typify_from_super(api_map)
|
55
|
+
return type.qualify(api_map, namespace) unless type.nil?
|
56
|
+
name.end_with?('?') ? ComplexType::BOOLEAN : ComplexType::UNDEFINED
|
57
|
+
end
|
58
|
+
|
59
|
+
def documentation
|
60
|
+
if @documentation.nil?
|
61
|
+
@documentation ||= super || ''
|
62
|
+
param_tags = docstring.tags(:param)
|
63
|
+
unless param_tags.nil? or param_tags.empty?
|
64
|
+
@documentation += "\n\n" unless @documentation.empty?
|
65
|
+
@documentation += "Params:\n"
|
66
|
+
lines = []
|
67
|
+
param_tags.each do |p|
|
68
|
+
l = "* #{p.name}"
|
69
|
+
l += " [#{escape_brackets(p.types.join(', '))}]" unless p.types.nil? or p.types.empty?
|
70
|
+
l += " #{p.text}"
|
71
|
+
lines.push l
|
72
|
+
end
|
73
|
+
@documentation += lines.join("\n")
|
74
|
+
end
|
75
|
+
return_tags = docstring.tags(:return)
|
76
|
+
unless return_tags.empty?
|
77
|
+
@documentation += "\n\n" unless @documentation.empty?
|
78
|
+
@documentation += "Returns:\n"
|
79
|
+
lines = []
|
80
|
+
return_tags.each do |r|
|
81
|
+
l = "*"
|
82
|
+
l += " [#{escape_brackets(r.types.join(', '))}]" unless r.types.nil? or r.types.empty?
|
83
|
+
l += " #{r.text}"
|
84
|
+
lines.push l
|
85
|
+
end
|
86
|
+
@documentation += lines.join("\n")
|
87
|
+
end
|
88
|
+
@documentation += "\n\n" unless @documentation.empty?
|
89
|
+
@documentation += "Visibility: #{visibility}"
|
90
|
+
end
|
91
|
+
@documentation.to_s
|
92
|
+
end
|
93
|
+
|
94
|
+
def explicit?
|
95
|
+
@explicit
|
96
|
+
end
|
97
|
+
|
98
|
+
def attribute?
|
99
|
+
@attribute
|
30
100
|
end
|
31
101
|
|
32
102
|
def nearly? other
|
@@ -37,7 +107,7 @@ module Solargraph
|
|
37
107
|
end
|
38
108
|
|
39
109
|
def probe api_map
|
40
|
-
infer_from_return_nodes(api_map)
|
110
|
+
attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
|
41
111
|
end
|
42
112
|
|
43
113
|
def try_merge! pin
|
@@ -70,6 +140,57 @@ module Solargraph
|
|
70
140
|
|
71
141
|
private
|
72
142
|
|
143
|
+
# @return [ComplexType]
|
144
|
+
def generate_complex_type
|
145
|
+
tags = docstring.tags(:return).map(&:types).flatten.reject(&:nil?)
|
146
|
+
return ComplexType::UNDEFINED if tags.empty?
|
147
|
+
ComplexType.try_parse *tags
|
148
|
+
end
|
149
|
+
|
150
|
+
# @param api_map [ApiMap]
|
151
|
+
# @return [ComplexType, nil]
|
152
|
+
def see_reference api_map
|
153
|
+
docstring.ref_tags.each do |ref|
|
154
|
+
next unless ref.tag_name == 'return' && ref.owner
|
155
|
+
result = resolve_reference(ref.owner.to_s, api_map)
|
156
|
+
return result unless result.nil?
|
157
|
+
end
|
158
|
+
match = comments.match(/^[ \t]*\(see (.*)\)/m)
|
159
|
+
return nil if match.nil?
|
160
|
+
resolve_reference match[1], api_map
|
161
|
+
end
|
162
|
+
|
163
|
+
# @param api_map [ApiMap]
|
164
|
+
# @return [ComplexType, nil]
|
165
|
+
def typify_from_super api_map
|
166
|
+
stack = api_map.get_method_stack(namespace, name, scope: scope).reject { |pin| pin.path == path }
|
167
|
+
return nil if stack.empty?
|
168
|
+
stack.each do |pin|
|
169
|
+
return pin.return_type unless pin.return_type.undefined?
|
170
|
+
end
|
171
|
+
nil
|
172
|
+
end
|
173
|
+
|
174
|
+
# @param ref [String]
|
175
|
+
# @param api_map [ApiMap]
|
176
|
+
# @return [ComplexType]
|
177
|
+
def resolve_reference ref, api_map
|
178
|
+
parts = ref.split(/[\.#]/)
|
179
|
+
if parts.first.empty? || parts.one?
|
180
|
+
path = "#{namespace}#{ref}"
|
181
|
+
else
|
182
|
+
fqns = api_map.qualify(parts.first, namespace)
|
183
|
+
return ComplexType::UNDEFINED if fqns.nil?
|
184
|
+
path = fqns + ref[parts.first.length] + parts.last
|
185
|
+
end
|
186
|
+
pins = api_map.get_path_pins(path)
|
187
|
+
pins.each do |pin|
|
188
|
+
type = pin.typify(api_map)
|
189
|
+
return type unless type.undefined?
|
190
|
+
end
|
191
|
+
nil
|
192
|
+
end
|
193
|
+
|
73
194
|
# @return [Parser::AST::Node, nil]
|
74
195
|
def method_body_node
|
75
196
|
return nil if node.nil?
|
@@ -106,6 +227,19 @@ module Solargraph
|
|
106
227
|
return ComplexType::UNDEFINED if result.empty?
|
107
228
|
ComplexType.try_parse(*result.map(&:tag).uniq)
|
108
229
|
end
|
230
|
+
|
231
|
+
def infer_from_iv api_map
|
232
|
+
types = []
|
233
|
+
varname = "@#{name.gsub(/=$/, '')}"
|
234
|
+
pins = api_map.get_instance_variable_pins(binder.namespace, binder.scope).select { |iv| iv.name == varname }
|
235
|
+
pins.each do |pin|
|
236
|
+
type = pin.typify(api_map)
|
237
|
+
type = pin.probe(api_map) if type.undefined?
|
238
|
+
types.push type if type.defined?
|
239
|
+
end
|
240
|
+
return ComplexType::UNDEFINED if types.empty?
|
241
|
+
ComplexType.try_parse(*types.map(&:tag).uniq)
|
242
|
+
end
|
109
243
|
end
|
110
244
|
end
|
111
245
|
end
|