solargraph 0.54.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/linting.yml +127 -0
- data/.github/workflows/plugins.yml +184 -6
- data/.github/workflows/rspec.yml +55 -5
- data/.github/workflows/typecheck.yml +8 -3
- data/.gitignore +7 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +1279 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +171 -0
- data/README.md +20 -6
- data/Rakefile +125 -13
- data/bin/solargraph +8 -5
- data/lib/solargraph/api_map/cache.rb +13 -3
- data/lib/solargraph/api_map/constants.rb +279 -0
- data/lib/solargraph/api_map/index.rb +193 -0
- data/lib/solargraph/api_map/source_to_yard.rb +13 -4
- data/lib/solargraph/api_map/store.rb +207 -132
- data/lib/solargraph/api_map.rb +394 -261
- data/lib/solargraph/bench.rb +18 -1
- data/lib/solargraph/complex_type/type_methods.rb +29 -12
- data/lib/solargraph/complex_type/unique_type.rb +205 -26
- data/lib/solargraph/complex_type.rb +126 -26
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +20 -3
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
- data/lib/solargraph/convention/data_definition.rb +105 -0
- data/lib/solargraph/convention/gemspec.rb +3 -2
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
- data/lib/solargraph/convention/struct_definition.rb +164 -0
- data/lib/solargraph/convention.rb +36 -4
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/doc_map.rb +316 -64
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/equality.rb +34 -0
- data/lib/solargraph/gem_pins.rb +64 -38
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +54 -5
- data/lib/solargraph/language_server/host.rb +36 -18
- data/lib/solargraph/language_server/message/base.rb +20 -12
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- data/lib/solargraph/language_server/message/initialize.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +5 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +23 -2
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +4 -3
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +27 -2
- data/lib/solargraph/language_server/request.rb +4 -1
- data/lib/solargraph/library.rb +83 -73
- data/lib/solargraph/location.rb +45 -1
- data/lib/solargraph/logging.rb +12 -2
- data/lib/solargraph/page.rb +3 -0
- data/lib/solargraph/parser/comment_ripper.rb +20 -7
- data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +26 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +10 -18
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_methods.rb +10 -19
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +26 -20
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +14 -2
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +16 -6
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +64 -32
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
- data/lib/solargraph/parser/region.rb +4 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +3 -5
- data/lib/solargraph/pin/base.rb +417 -42
- data/lib/solargraph/pin/base_variable.rb +21 -12
- data/lib/solargraph/pin/block.rb +9 -26
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +231 -0
- data/lib/solargraph/pin/closure.rb +30 -10
- data/lib/solargraph/pin/common.rb +12 -7
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/conversions.rb +3 -2
- data/lib/solargraph/pin/delegated_method.rb +20 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/instance_variable.rb +2 -2
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +15 -7
- data/lib/solargraph/pin/method.rb +241 -70
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/namespace.rb +21 -13
- data/lib/solargraph/pin/parameter.rb +94 -32
- data/lib/solargraph/pin/proxy_type.rb +17 -7
- data/lib/solargraph/pin/reference/override.rb +24 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +17 -0
- data/lib/solargraph/pin/search.rb +6 -1
- data/lib/solargraph/pin/signature.rb +39 -121
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +8 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +8 -2
- data/lib/solargraph/pin_cache.rb +245 -0
- data/lib/solargraph/position.rb +19 -0
- data/lib/solargraph/range.rb +23 -4
- data/lib/solargraph/rbs_map/conversions.rb +315 -99
- data/lib/solargraph/rbs_map/core_fills.rb +50 -16
- data/lib/solargraph/rbs_map/core_map.rb +41 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +87 -16
- data/lib/solargraph/shell.rb +117 -17
- data/lib/solargraph/source/chain/array.rb +13 -8
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +135 -66
- data/lib/solargraph/source/chain/constant.rb +3 -66
- data/lib/solargraph/source/chain/hash.rb +9 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +7 -2
- data/lib/solargraph/source/chain/link.rb +38 -6
- data/lib/solargraph/source/chain/literal.rb +27 -2
- data/lib/solargraph/source/chain/or.rb +2 -2
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +140 -63
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +4 -4
- data/lib/solargraph/source/source_chainer.rb +3 -3
- data/lib/solargraph/source.rb +110 -89
- data/lib/solargraph/source_map/clip.rb +22 -28
- data/lib/solargraph/source_map/data.rb +34 -0
- data/lib/solargraph/source_map/mapper.rb +11 -7
- data/lib/solargraph/source_map.rb +50 -43
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +35 -8
- data/lib/solargraph/type_checker.rb +331 -189
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +25 -5
- data/lib/solargraph/workspace/require_paths.rb +97 -0
- data/lib/solargraph/workspace.rb +53 -72
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +8 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +55 -19
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +11 -7
- data/lib/solargraph/yard_map/mapper.rb +5 -3
- data/lib/solargraph/yard_map/to_method.rb +6 -3
- data/lib/solargraph/yardoc.rb +45 -10
- data/lib/solargraph.rb +35 -1
- data/rbs/fills/bundler/0/bundler.rbs +4271 -0
- data/rbs/fills/open3/0/open3.rbs +172 -0
- data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
- data/rbs/fills/rubygems/0/errors.rbs +364 -0
- data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
- data/rbs/fills/rubygems/0/specification.rbs +1753 -0
- data/rbs/fills/tuple/tuple.rbs +149 -0
- data/rbs_collection.yaml +19 -0
- data/sig/shims/ast/0/node.rbs +5 -0
- data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
- data/sig/shims/ast/2.4/ast.rbs +73 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
- data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
- data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -0
- data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
- data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
- data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
- data/solargraph.gemspec +32 -10
- metadata +237 -37
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/cache.rb +0 -77
- data/lib/solargraph/parser/node_methods.rb +0 -83
|
@@ -3,10 +3,20 @@
|
|
|
3
3
|
module Solargraph
|
|
4
4
|
class Source
|
|
5
5
|
class Chain
|
|
6
|
-
|
|
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
|
+
#
|
|
11
|
+
class Call < Chain::Link
|
|
12
|
+
include Solargraph::Parser::NodeMethods
|
|
13
|
+
|
|
7
14
|
# @return [String]
|
|
8
15
|
attr_reader :word
|
|
9
16
|
|
|
17
|
+
# @return [Location]
|
|
18
|
+
attr_reader :location
|
|
19
|
+
|
|
10
20
|
# @return [::Array<Chain>]
|
|
11
21
|
attr_reader :arguments
|
|
12
22
|
|
|
@@ -14,47 +24,55 @@ module Solargraph
|
|
|
14
24
|
attr_reader :block
|
|
15
25
|
|
|
16
26
|
# @param word [String]
|
|
27
|
+
# @param location [Location, nil]
|
|
17
28
|
# @param arguments [::Array<Chain>]
|
|
18
29
|
# @param block [Chain, nil]
|
|
19
|
-
def initialize word, arguments = [], block = nil
|
|
30
|
+
def initialize word, location = nil, arguments = [], block = nil
|
|
20
31
|
@word = word
|
|
32
|
+
@location = location
|
|
21
33
|
@arguments = arguments
|
|
22
34
|
@block = block
|
|
23
35
|
fix_block_pass
|
|
24
36
|
end
|
|
25
37
|
|
|
38
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
39
|
+
protected def equality_fields
|
|
40
|
+
super + [arguments, block]
|
|
41
|
+
end
|
|
42
|
+
|
|
26
43
|
def with_block?
|
|
27
44
|
!!@block
|
|
28
45
|
end
|
|
29
46
|
|
|
30
47
|
# @param api_map [ApiMap]
|
|
31
|
-
# @param name_pin [Pin::
|
|
48
|
+
# @param name_pin [Pin::Closure] name_pin.binder should give us the type of the object on which 'word' will be invoked
|
|
32
49
|
# @param locals [::Array<Pin::LocalVariable>]
|
|
33
50
|
def resolve api_map, name_pin, locals
|
|
34
51
|
return super_pins(api_map, name_pin) if word == 'super'
|
|
35
52
|
return yield_pins(api_map, name_pin) if word == 'yield'
|
|
36
53
|
found = if head?
|
|
37
|
-
locals
|
|
54
|
+
api_map.visible_pins(locals, word, name_pin, location)
|
|
38
55
|
else
|
|
39
56
|
[]
|
|
40
57
|
end
|
|
41
|
-
return inferred_pins(found, api_map, name_pin
|
|
42
|
-
# @param [ComplexType::UniqueType]
|
|
58
|
+
return inferred_pins(found, api_map, name_pin, locals) unless found.empty?
|
|
43
59
|
pins = name_pin.binder.each_unique_type.flat_map do |context|
|
|
44
|
-
|
|
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
|
|
45
63
|
end
|
|
46
64
|
return [] if pins.empty?
|
|
47
|
-
inferred_pins(pins, api_map, name_pin
|
|
65
|
+
inferred_pins(pins, api_map, name_pin, locals)
|
|
48
66
|
end
|
|
49
67
|
|
|
50
68
|
private
|
|
51
69
|
|
|
52
70
|
# @param pins [::Enumerable<Pin::Method>]
|
|
53
71
|
# @param api_map [ApiMap]
|
|
54
|
-
# @param
|
|
55
|
-
# @param locals [::Array<Pin::LocalVariable>]
|
|
72
|
+
# @param name_pin [Pin::Base]
|
|
73
|
+
# @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
|
|
56
74
|
# @return [::Array<Pin::Base>]
|
|
57
|
-
def inferred_pins pins, api_map,
|
|
75
|
+
def inferred_pins pins, api_map, name_pin, locals
|
|
58
76
|
result = pins.map do |p|
|
|
59
77
|
next p unless p.is_a?(Pin::Method)
|
|
60
78
|
overloads = p.signatures
|
|
@@ -65,10 +83,12 @@ module Solargraph
|
|
|
65
83
|
# use it. If we didn't pass a block, the logic below will
|
|
66
84
|
# reject it regardless
|
|
67
85
|
|
|
68
|
-
|
|
86
|
+
with_block, without_block = overloads.partition(&:block?)
|
|
87
|
+
sorted_overloads = with_block + without_block
|
|
88
|
+
# @type [Pin::Signature, nil]
|
|
69
89
|
new_signature_pin = nil
|
|
70
90
|
sorted_overloads.each do |ol|
|
|
71
|
-
next unless arity_matches?(arguments,
|
|
91
|
+
next unless ol.arity_matches?(arguments, with_block?)
|
|
72
92
|
match = true
|
|
73
93
|
|
|
74
94
|
atypes = []
|
|
@@ -78,10 +98,11 @@ module Solargraph
|
|
|
78
98
|
match = ol.parameters.any?(&:restarg?)
|
|
79
99
|
break
|
|
80
100
|
end
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
101
|
+
arg_name_pin = Pin::ProxyType.anonymous(name_pin.context,
|
|
102
|
+
gates: name_pin.gates,
|
|
103
|
+
source: :chain)
|
|
104
|
+
atype = atypes[idx] ||= arg.infer(api_map, arg_name_pin, locals)
|
|
105
|
+
unless param.compatible_arg?(atype, api_map) || param.restarg?
|
|
85
106
|
match = false
|
|
86
107
|
break
|
|
87
108
|
end
|
|
@@ -89,11 +110,37 @@ module Solargraph
|
|
|
89
110
|
if match
|
|
90
111
|
if ol.block && with_block?
|
|
91
112
|
block_atypes = ol.block.parameters.map(&:return_type)
|
|
92
|
-
|
|
113
|
+
if block.links.map(&:class) == [BlockSymbol]
|
|
114
|
+
# like the bar in foo(&:bar)
|
|
115
|
+
blocktype = block_symbol_call_type(api_map, name_pin.context, block_atypes, locals)
|
|
116
|
+
else
|
|
117
|
+
blocktype = block_call_type(api_map, name_pin, locals)
|
|
118
|
+
end
|
|
93
119
|
end
|
|
120
|
+
# @type new_signature_pin [Pin::Signature]
|
|
94
121
|
new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
|
|
95
122
|
new_return_type = new_signature_pin.return_type
|
|
96
|
-
|
|
123
|
+
if head?
|
|
124
|
+
# If we're at the head of the chain, we called a
|
|
125
|
+
# method somewhere that marked itself as returning
|
|
126
|
+
# self. Given we didn't invoke this on an object,
|
|
127
|
+
# this must be a method in this same class - so we
|
|
128
|
+
# use our own self type
|
|
129
|
+
self_type = name_pin.context
|
|
130
|
+
else
|
|
131
|
+
# if we're past the head in the chain, whatever the
|
|
132
|
+
# type of the lhs side is what 'self' will be in its
|
|
133
|
+
# declaration - we can't just use the type of the
|
|
134
|
+
# method pin, as this might be a subclass of the
|
|
135
|
+
# place where the method is defined
|
|
136
|
+
self_type = name_pin.binder
|
|
137
|
+
end
|
|
138
|
+
# This same logic applies to the YARD work done by
|
|
139
|
+
# 'with_params()'.
|
|
140
|
+
#
|
|
141
|
+
# qualify(), however, happens in the namespace where
|
|
142
|
+
# the docs were written - from the method pin.
|
|
143
|
+
type = with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, *p.gates) if new_return_type.defined?
|
|
97
144
|
type ||= ComplexType::UNDEFINED
|
|
98
145
|
end
|
|
99
146
|
break if type.defined?
|
|
@@ -101,20 +148,22 @@ module Solargraph
|
|
|
101
148
|
p = p.with_single_signature(new_signature_pin) unless new_signature_pin.nil?
|
|
102
149
|
next p.proxy(type) if type.defined?
|
|
103
150
|
if !p.macros.empty?
|
|
104
|
-
result = process_macro(p, api_map, context, locals)
|
|
151
|
+
result = process_macro(p, api_map, name_pin.context, locals)
|
|
105
152
|
next result unless result.return_type.undefined?
|
|
106
153
|
elsif !p.directives.empty?
|
|
107
|
-
result = process_directive(p, api_map, context, locals)
|
|
154
|
+
result = process_directive(p, api_map, name_pin.context, locals)
|
|
108
155
|
next result unless result.return_type.undefined?
|
|
109
156
|
end
|
|
110
157
|
p
|
|
111
158
|
end
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
159
|
+
logger.debug { "Call#inferred_pins(name_pin.binder=#{name_pin.binder}, word=#{word}, pins=#{pins.map(&:desc)}, name_pin=#{name_pin}) - result=#{result}" }
|
|
160
|
+
out = result.map do |pin|
|
|
161
|
+
if pin.path == 'Class#new' && name_pin.binder.tag != 'Class'
|
|
162
|
+
reduced_context = name_pin.binder.reduce_class_type
|
|
163
|
+
pin.proxy(reduced_context)
|
|
115
164
|
else
|
|
116
165
|
next pin if pin.return_type.undefined?
|
|
117
|
-
selfy = pin.return_type.
|
|
166
|
+
selfy = pin.return_type.self_to_type(name_pin.binder)
|
|
118
167
|
selfy == pin.return_type ? pin : pin.proxy(selfy)
|
|
119
168
|
end
|
|
120
169
|
end
|
|
@@ -123,7 +172,7 @@ module Solargraph
|
|
|
123
172
|
# @param pin [Pin::Base]
|
|
124
173
|
# @param api_map [ApiMap]
|
|
125
174
|
# @param context [ComplexType]
|
|
126
|
-
# @param locals [
|
|
175
|
+
# @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
|
|
127
176
|
# @return [Pin::Base]
|
|
128
177
|
def process_macro pin, api_map, context, locals
|
|
129
178
|
pin.macros.each do |macro|
|
|
@@ -136,13 +185,13 @@ module Solargraph
|
|
|
136
185
|
result = inner_process_macro(pin, macro, api_map, context, locals)
|
|
137
186
|
return result unless result.return_type.undefined?
|
|
138
187
|
end
|
|
139
|
-
Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
|
|
188
|
+
Pin::ProxyType.anonymous(ComplexType::UNDEFINED, source: :chain)
|
|
140
189
|
end
|
|
141
190
|
|
|
142
191
|
# @param pin [Pin::Method]
|
|
143
192
|
# @param api_map [ApiMap]
|
|
144
193
|
# @param context [ComplexType]
|
|
145
|
-
# @param locals [
|
|
194
|
+
# @param locals [::Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
|
|
146
195
|
# @return [Pin::ProxyType]
|
|
147
196
|
def process_directive pin, api_map, context, locals
|
|
148
197
|
pin.directives.each do |dir|
|
|
@@ -151,17 +200,17 @@ module Solargraph
|
|
|
151
200
|
result = inner_process_macro(pin, macro, api_map, context, locals)
|
|
152
201
|
return result unless result.return_type.undefined?
|
|
153
202
|
end
|
|
154
|
-
Pin::ProxyType.anonymous ComplexType::UNDEFINED
|
|
203
|
+
Pin::ProxyType.anonymous ComplexType::UNDEFINED, source: :chain
|
|
155
204
|
end
|
|
156
205
|
|
|
157
206
|
# @param pin [Pin::Base]
|
|
158
207
|
# @param macro [YARD::Tags::MacroDirective]
|
|
159
208
|
# @param api_map [ApiMap]
|
|
160
209
|
# @param context [ComplexType]
|
|
161
|
-
# @param locals [
|
|
210
|
+
# @param locals [::Array<Pin::LocalVariable, Pin::Parameter>]
|
|
162
211
|
# @return [Pin::ProxyType]
|
|
163
212
|
def inner_process_macro pin, macro, api_map, context, locals
|
|
164
|
-
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
|
|
213
|
+
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals), source: :chain) }
|
|
165
214
|
txt = macro.tag.text.clone
|
|
166
215
|
if txt.empty? && macro.tag.name
|
|
167
216
|
named = api_map.named_macro(macro.tag.name)
|
|
@@ -175,9 +224,9 @@ module Solargraph
|
|
|
175
224
|
docstring = Solargraph::Source.parse_docstring(txt).to_docstring
|
|
176
225
|
tag = docstring.tag(:return)
|
|
177
226
|
unless tag.nil? || tag.types.nil?
|
|
178
|
-
return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types))
|
|
227
|
+
return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types), source: :chain)
|
|
179
228
|
end
|
|
180
|
-
Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
|
|
229
|
+
Pin::ProxyType.anonymous(ComplexType::UNDEFINED, source: :chain)
|
|
181
230
|
end
|
|
182
231
|
|
|
183
232
|
# @param docstring [YARD::Docstring]
|
|
@@ -192,24 +241,24 @@ module Solargraph
|
|
|
192
241
|
nil
|
|
193
242
|
end
|
|
194
243
|
|
|
195
|
-
# @param
|
|
196
|
-
# @
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
|
|
205
|
-
true
|
|
244
|
+
# @param name_pin [Pin::Base]
|
|
245
|
+
# @return [Pin::Method, nil]
|
|
246
|
+
def find_method_pin(name_pin)
|
|
247
|
+
method_pin = name_pin
|
|
248
|
+
until method_pin.is_a?(Pin::Method)
|
|
249
|
+
method_pin = method_pin.closure
|
|
250
|
+
return if method_pin.nil?
|
|
251
|
+
end
|
|
252
|
+
method_pin
|
|
206
253
|
end
|
|
207
254
|
|
|
208
255
|
# @param api_map [ApiMap]
|
|
209
256
|
# @param name_pin [Pin::Base]
|
|
210
257
|
# @return [::Array<Pin::Base>]
|
|
211
258
|
def super_pins api_map, name_pin
|
|
212
|
-
|
|
259
|
+
method_pin = find_method_pin(name_pin)
|
|
260
|
+
return [] if method_pin.nil?
|
|
261
|
+
pins = api_map.get_method_stack(method_pin.namespace, method_pin.name, scope: method_pin.context.scope)
|
|
213
262
|
pins.reject{|p| p.path == name_pin.path}
|
|
214
263
|
end
|
|
215
264
|
|
|
@@ -217,10 +266,14 @@ module Solargraph
|
|
|
217
266
|
# @param name_pin [Pin::Base]
|
|
218
267
|
# @return [::Array<Pin::Base>]
|
|
219
268
|
def yield_pins api_map, name_pin
|
|
220
|
-
method_pin =
|
|
221
|
-
return []
|
|
269
|
+
method_pin = find_method_pin(name_pin)
|
|
270
|
+
return [] unless method_pin
|
|
222
271
|
|
|
223
|
-
|
|
272
|
+
# @param signature_pin [Pin::Signature]
|
|
273
|
+
method_pin.signatures.map(&:block).compact.map do |signature_pin|
|
|
274
|
+
return_type = signature_pin.return_type.qualify(api_map, *name_pin.gates)
|
|
275
|
+
signature_pin.proxy(return_type)
|
|
276
|
+
end
|
|
224
277
|
end
|
|
225
278
|
|
|
226
279
|
# @param type [ComplexType]
|
|
@@ -228,7 +281,7 @@ module Solargraph
|
|
|
228
281
|
# @return [ComplexType]
|
|
229
282
|
def with_params type, context
|
|
230
283
|
return type unless type.to_s.include?('$')
|
|
231
|
-
ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:
|
|
284
|
+
ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:rooted_tag).join(', ')).gsub('<>', ''))
|
|
232
285
|
end
|
|
233
286
|
|
|
234
287
|
# @return [void]
|
|
@@ -242,25 +295,41 @@ module Solargraph
|
|
|
242
295
|
# @param block_parameter_types [::Array<ComplexType>]
|
|
243
296
|
# @param locals [::Array<Pin::LocalVariable>]
|
|
244
297
|
# @return [ComplexType, nil]
|
|
245
|
-
def
|
|
298
|
+
def block_symbol_call_type(api_map, context, block_parameter_types, locals)
|
|
299
|
+
# Ruby's shorthand for sending the passed in method name
|
|
300
|
+
# to the first yield parameter with no arguments
|
|
301
|
+
block_symbol_name = block.links.first.word
|
|
302
|
+
block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
|
|
303
|
+
callee = api_map.get_path_pins(block_symbol_call_path).first
|
|
304
|
+
return_type = callee&.return_type
|
|
305
|
+
# @todo: Figure out why we get unresolved generics at
|
|
306
|
+
# this point and need to assume method return types
|
|
307
|
+
# based on the generic type
|
|
308
|
+
return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
|
|
309
|
+
return_type || ComplexType::UNDEFINED
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# @param api_map [ApiMap]
|
|
313
|
+
# @return [Pin::Block, nil]
|
|
314
|
+
def find_block_pin(api_map)
|
|
315
|
+
node_location = Solargraph::Location.from_node(block.node)
|
|
316
|
+
return if node_location.nil?
|
|
317
|
+
block_pins = api_map.get_block_pins
|
|
318
|
+
block_pins.find { |pin| pin.location.contain?(node_location) }
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# @param api_map [ApiMap]
|
|
322
|
+
# @param name_pin [Pin::Base]
|
|
323
|
+
# @param block_parameter_types [::Array<ComplexType>]
|
|
324
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
|
325
|
+
# @return [ComplexType, nil]
|
|
326
|
+
def block_call_type(api_map, name_pin, locals)
|
|
246
327
|
return nil unless with_block?
|
|
247
328
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
block_symbol_name = block.links.first.word
|
|
253
|
-
block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
|
|
254
|
-
callee = api_map.get_path_pins(block_symbol_call_path).first
|
|
255
|
-
return_type = callee&.return_type
|
|
256
|
-
# @todo: Figure out why we get unresolved generics at
|
|
257
|
-
# this point and need to assume method return types
|
|
258
|
-
# based on the generic type
|
|
259
|
-
return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
|
|
260
|
-
return_type || ComplexType::UNDEFINED
|
|
261
|
-
else
|
|
262
|
-
block.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
|
263
|
-
end
|
|
329
|
+
block_context_pin = name_pin
|
|
330
|
+
block_pin = find_block_pin(api_map)
|
|
331
|
+
block_context_pin = block_pin.closure if block_pin
|
|
332
|
+
block.infer(api_map, block_context_pin, locals)
|
|
264
333
|
end
|
|
265
334
|
end
|
|
266
335
|
end
|
|
@@ -15,73 +15,10 @@ module Solargraph
|
|
|
15
15
|
gates = ['']
|
|
16
16
|
else
|
|
17
17
|
base = word
|
|
18
|
-
gates =
|
|
18
|
+
gates = name_pin.gates
|
|
19
19
|
end
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# @todo 'Wrong argument type for
|
|
23
|
-
# Solargraph::Source::Chain::Constant#deep_constant_type:
|
|
24
|
-
# gate expected String, received generic<Elem>' is because
|
|
25
|
-
# we lose 'rooted' information in the 'Chain::Array' class
|
|
26
|
-
# internally, leaving ::Array#each shadowed when it
|
|
27
|
-
# shouldn't be.
|
|
28
|
-
type = deep_constant_type(gate, api_map)
|
|
29
|
-
# Use deep inference to resolve root
|
|
30
|
-
parts[0..-2].each do |sym|
|
|
31
|
-
pins = api_map.get_constants('', type.namespace).select{ |pin| pin.name == sym }
|
|
32
|
-
type = first_pin_type(pins, api_map)
|
|
33
|
-
break if type.undefined?
|
|
34
|
-
end
|
|
35
|
-
next if type.undefined?
|
|
36
|
-
result = api_map.get_constants('', type.namespace).select { |pin| pin.name == parts.last }
|
|
37
|
-
return result unless result.empty?
|
|
38
|
-
end
|
|
39
|
-
[]
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
private
|
|
43
|
-
|
|
44
|
-
# @param pin [Pin::Base]
|
|
45
|
-
# @return [::Array<String>]
|
|
46
|
-
def crawl_gates pin
|
|
47
|
-
clos = pin
|
|
48
|
-
until clos.nil?
|
|
49
|
-
if clos.is_a?(Pin::Namespace)
|
|
50
|
-
gates = clos.gates
|
|
51
|
-
gates.push('') if gates.empty?
|
|
52
|
-
return gates
|
|
53
|
-
end
|
|
54
|
-
clos = clos.closure
|
|
55
|
-
end
|
|
56
|
-
['']
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# @param pins [::Array<Pin::Base>]
|
|
60
|
-
# @param api_map [ApiMap]
|
|
61
|
-
# @return [ComplexType]
|
|
62
|
-
def first_pin_type(pins, api_map)
|
|
63
|
-
type = ComplexType::UNDEFINED
|
|
64
|
-
pins.each do |pin|
|
|
65
|
-
type = pin.typify(api_map)
|
|
66
|
-
break if type.defined?
|
|
67
|
-
type = pin.probe(api_map)
|
|
68
|
-
break if type.defined?
|
|
69
|
-
end
|
|
70
|
-
type
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# @param gate [String]
|
|
74
|
-
# @param api_map [ApiMap]
|
|
75
|
-
# @return [ComplexType]
|
|
76
|
-
def deep_constant_type(gate, api_map)
|
|
77
|
-
type = ComplexType::ROOT
|
|
78
|
-
return type if gate == ''
|
|
79
|
-
gate.split('::').each do |word|
|
|
80
|
-
pins = api_map.get_constants('', type.namespace).select { |pin| pin.name == word }
|
|
81
|
-
type = first_pin_type(pins, api_map)
|
|
82
|
-
break if type.undefined?
|
|
83
|
-
end
|
|
84
|
-
type
|
|
20
|
+
fqns = api_map.resolve(base, gates)
|
|
21
|
+
api_map.get_path_pins(fqns)
|
|
85
22
|
end
|
|
86
23
|
end
|
|
87
24
|
end
|
|
@@ -5,18 +5,24 @@ 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
|
|
|
15
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
16
|
+
protected def equality_fields
|
|
17
|
+
super + [@splatted]
|
|
18
|
+
end
|
|
19
|
+
|
|
14
20
|
def word
|
|
15
21
|
@word ||= "<#{@type}>"
|
|
16
22
|
end
|
|
17
23
|
|
|
18
24
|
def resolve api_map, name_pin, locals
|
|
19
|
-
[Pin::ProxyType.anonymous(@complex_type)]
|
|
25
|
+
[Pin::ProxyType.anonymous(@complex_type, source: :chain)]
|
|
20
26
|
end
|
|
21
27
|
|
|
22
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
|
|
@@ -8,14 +8,19 @@ module Solargraph
|
|
|
8
8
|
'<if>'
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
# @param links [::Array<
|
|
11
|
+
# @param links [::Array<Chain>]
|
|
12
12
|
def initialize links
|
|
13
13
|
@links = links
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
17
|
+
protected def equality_fields
|
|
18
|
+
super + [@links]
|
|
19
|
+
end
|
|
20
|
+
|
|
16
21
|
def resolve api_map, name_pin, locals
|
|
17
22
|
types = @links.map { |link| link.infer(api_map, name_pin, locals) }
|
|
18
|
-
[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)]
|
|
19
24
|
end
|
|
20
25
|
end
|
|
21
26
|
end
|
|
@@ -4,6 +4,8 @@ module Solargraph
|
|
|
4
4
|
class Source
|
|
5
5
|
class Chain
|
|
6
6
|
class Link
|
|
7
|
+
include Equality
|
|
8
|
+
|
|
7
9
|
# @return [String]
|
|
8
10
|
attr_reader :word
|
|
9
11
|
|
|
@@ -15,6 +17,17 @@ module Solargraph
|
|
|
15
17
|
@word = word
|
|
16
18
|
end
|
|
17
19
|
|
|
20
|
+
# @sg-ignore two problems - Declared return type
|
|
21
|
+
# ::Solargraph::Source::Chain::Array does not match inferred
|
|
22
|
+
# type ::Array(::Class<::Solargraph::Source::Chain::Link>,
|
|
23
|
+
# ::String) for
|
|
24
|
+
# Solargraph::Source::Chain::Link#equality_fields
|
|
25
|
+
# and
|
|
26
|
+
# Not enough arguments to Module#protected
|
|
27
|
+
protected def equality_fields
|
|
28
|
+
[self.class, word]
|
|
29
|
+
end
|
|
30
|
+
|
|
18
31
|
def undefined?
|
|
19
32
|
word == '<undefined>'
|
|
20
33
|
end
|
|
@@ -25,24 +38,30 @@ module Solargraph
|
|
|
25
38
|
|
|
26
39
|
# @param api_map [ApiMap]
|
|
27
40
|
# @param name_pin [Pin::Base]
|
|
28
|
-
# @param locals [::
|
|
41
|
+
# @param locals [::Array<Pin::Base>]
|
|
29
42
|
# @return [::Array<Pin::Base>]
|
|
30
43
|
def resolve api_map, name_pin, locals
|
|
31
44
|
[]
|
|
32
45
|
end
|
|
33
46
|
|
|
47
|
+
# debugging description of contents; not for machine use
|
|
48
|
+
# @return [String]
|
|
49
|
+
def desc
|
|
50
|
+
word
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_s
|
|
54
|
+
desc
|
|
55
|
+
end
|
|
56
|
+
|
|
34
57
|
def inspect
|
|
35
|
-
"
|
|
58
|
+
"#<#{self.class} - `#{self.desc}`>"
|
|
36
59
|
end
|
|
37
60
|
|
|
38
61
|
def head?
|
|
39
62
|
@head ||= false
|
|
40
63
|
end
|
|
41
64
|
|
|
42
|
-
def == other
|
|
43
|
-
self.class == other.class and word == other.word
|
|
44
|
-
end
|
|
45
|
-
|
|
46
65
|
# Make a copy of this link marked as the head of a chain
|
|
47
66
|
#
|
|
48
67
|
# @return [self]
|
|
@@ -61,6 +80,19 @@ module Solargraph
|
|
|
61
80
|
false
|
|
62
81
|
end
|
|
63
82
|
|
|
83
|
+
# debugging description of contents; not for machine use
|
|
84
|
+
#
|
|
85
|
+
# @return [String]
|
|
86
|
+
def desc
|
|
87
|
+
word
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def inspect
|
|
91
|
+
"#<#{self.class} - `#{self.desc}`>"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
include Logging
|
|
95
|
+
|
|
64
96
|
protected
|
|
65
97
|
|
|
66
98
|
# Mark whether this link is the head of a chain
|
|
@@ -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,14 +10,37 @@ 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
|
|
|
32
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
33
|
+
protected def equality_fields
|
|
34
|
+
super + [@value, @type, @literal_type, @complex_type]
|
|
35
|
+
end
|
|
36
|
+
|
|
17
37
|
def resolve api_map, name_pin, locals
|
|
18
|
-
|
|
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
|
|
19
44
|
end
|
|
20
45
|
end
|
|
21
46
|
end
|
|
@@ -8,14 +8,14 @@ module Solargraph
|
|
|
8
8
|
'<or>'
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
# @param links [::Array<
|
|
11
|
+
# @param links [::Array<Chain>]
|
|
12
12
|
def initialize links
|
|
13
13
|
@links = links
|
|
14
14
|
end
|
|
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.
|
|
18
|
+
[Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.new(types.uniq), source: :chain)]
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -15,7 +15,7 @@ module Solargraph
|
|
|
15
15
|
# @param with_block [Boolean] True if the chain is inside a block
|
|
16
16
|
# @param head [Boolean] True if the call is the start of its chain
|
|
17
17
|
def initialize word, with_block = false
|
|
18
|
-
super(word, [], with_block)
|
|
18
|
+
super(word, nil, [], with_block)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# @param api_map [ApiMap]
|