solargraph 0.39.16 → 0.40.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|