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
|
@@ -5,10 +5,18 @@ require 'solargraph/source/chain/link'
|
|
|
5
5
|
|
|
6
6
|
module Solargraph
|
|
7
7
|
class Source
|
|
8
|
-
#
|
|
9
|
-
#
|
|
8
|
+
#
|
|
9
|
+
# Represents an expression as a single call chain at the parse
|
|
10
|
+
# tree level, made up of constants, variables, and method calls,
|
|
11
|
+
# each represented as a Link object.
|
|
12
|
+
#
|
|
13
|
+
# Computes Pins and/or ComplexTypes representing the interpreted
|
|
14
|
+
# expression.
|
|
10
15
|
#
|
|
11
16
|
class Chain
|
|
17
|
+
include Equality
|
|
18
|
+
include Logging
|
|
19
|
+
|
|
12
20
|
autoload :Link, 'solargraph/source/chain/link'
|
|
13
21
|
autoload :Call, 'solargraph/source/chain/call'
|
|
14
22
|
autoload :QCall, 'solargraph/source/chain/q_call'
|
|
@@ -32,7 +40,7 @@ module Solargraph
|
|
|
32
40
|
@@inference_invalidation_key = nil
|
|
33
41
|
@@inference_cache = {}
|
|
34
42
|
|
|
35
|
-
UNDEFINED_CALL = Chain::Call.new('<undefined>')
|
|
43
|
+
UNDEFINED_CALL = Chain::Call.new('<undefined>', nil)
|
|
36
44
|
UNDEFINED_CONSTANT = Chain::Constant.new('<undefined>')
|
|
37
45
|
|
|
38
46
|
# @return [::Array<Source::Chain::Link>]
|
|
@@ -40,6 +48,11 @@ module Solargraph
|
|
|
40
48
|
|
|
41
49
|
attr_reader :node
|
|
42
50
|
|
|
51
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
52
|
+
protected def equality_fields
|
|
53
|
+
[links, node]
|
|
54
|
+
end
|
|
55
|
+
|
|
43
56
|
# @param node [Parser::AST::Node, nil]
|
|
44
57
|
# @param links [::Array<Chain::Link>]
|
|
45
58
|
# @param splat [Boolean]
|
|
@@ -61,54 +74,97 @@ module Solargraph
|
|
|
61
74
|
@base ||= Chain.new(links[0..-2])
|
|
62
75
|
end
|
|
63
76
|
|
|
77
|
+
# Determine potential Pins returned by this chain of words
|
|
78
|
+
#
|
|
64
79
|
# @param api_map [ApiMap]
|
|
65
|
-
# @param name_pin [Pin::Base]
|
|
66
|
-
# @param locals [::Enumerable<Pin::LocalVariable>]
|
|
67
80
|
#
|
|
68
|
-
# @
|
|
81
|
+
# @param name_pin [Pin::Base] A pin
|
|
82
|
+
# representing the place in which expression is evaluated (e.g.,
|
|
83
|
+
# a Method pin, or a Module or Class pin if not run within a
|
|
84
|
+
# method - both in terms of the closure around the chain, as well
|
|
85
|
+
# as the self type used for any method calls in head position.
|
|
86
|
+
#
|
|
87
|
+
# Requirements for name_pin:
|
|
88
|
+
#
|
|
89
|
+
# * name_pin.context: This should be a type representing the
|
|
90
|
+
# namespace where we can look up non-local variables and
|
|
91
|
+
# method names. If it is a Class<X>, we will look up
|
|
92
|
+
# :class scoped methods/variables.
|
|
93
|
+
#
|
|
94
|
+
# * name_pin.binder: Used for method call lookups only
|
|
95
|
+
# (Chain::Call links). For method calls as the first
|
|
96
|
+
# element in the chain, 'name_pin.binder' should be the
|
|
97
|
+
# same as name_pin.context above. For method calls later
|
|
98
|
+
# in the chain (e.g., 'b' in a.b.c), it should represent
|
|
99
|
+
# 'a'.
|
|
100
|
+
#
|
|
101
|
+
# @param locals [::Array<Pin::LocalVariable>] Any local
|
|
102
|
+
# variables / method parameters etc visible by the statement
|
|
103
|
+
#
|
|
104
|
+
# @return [::Array<Pin::Base>] Pins representing possible return
|
|
105
|
+
# types of this method.
|
|
69
106
|
def define api_map, name_pin, locals
|
|
70
107
|
return [] if undefined?
|
|
108
|
+
|
|
109
|
+
# working_pin is the surrounding closure pin for the link
|
|
110
|
+
# being processed, whose #binder method will provide the LHS /
|
|
111
|
+
# 'self type' of the next link (same as the #return_type method
|
|
112
|
+
# --the type of the result so far).
|
|
113
|
+
#
|
|
114
|
+
# @todo ProxyType uses 'type' for the binder, but '
|
|
71
115
|
working_pin = name_pin
|
|
72
116
|
links[0..-2].each do |link|
|
|
73
117
|
pins = link.resolve(api_map, working_pin, locals)
|
|
74
|
-
type =
|
|
75
|
-
|
|
76
|
-
|
|
118
|
+
type = infer_from_definitions(pins, working_pin, api_map, locals)
|
|
119
|
+
if type.undefined?
|
|
120
|
+
logger.debug { "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) => [] - undefined type from #{link.desc}" }
|
|
121
|
+
return []
|
|
122
|
+
end
|
|
123
|
+
# We continue to use the context from the head pin, in case
|
|
124
|
+
# we need it to, for instance, provide context for a block
|
|
125
|
+
# evaluation. However, we use the last link's return type
|
|
126
|
+
# for the binder, as this is chaining off of it, and the
|
|
127
|
+
# binder is now the lhs of the rhs we are evaluating.
|
|
128
|
+
working_pin = Pin::ProxyType.anonymous(name_pin.context, binder: type, closure: name_pin, source: :chain)
|
|
129
|
+
logger.debug { "Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) - after processing #{link.desc}, new working_pin=#{working_pin} with binder #{working_pin.binder}" }
|
|
77
130
|
end
|
|
78
|
-
links.last.last_context =
|
|
131
|
+
links.last.last_context = working_pin
|
|
79
132
|
links.last.resolve(api_map, working_pin, locals)
|
|
80
133
|
end
|
|
81
134
|
|
|
82
135
|
# @param api_map [ApiMap]
|
|
83
|
-
# @param name_pin [Pin::Base]
|
|
84
|
-
# @param locals [::
|
|
136
|
+
# @param name_pin [Pin::Base] The pin for the closure in which this code runs
|
|
137
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
|
85
138
|
# @return [ComplexType]
|
|
86
139
|
# @sg-ignore
|
|
87
140
|
def infer api_map, name_pin, locals
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
@@inference_cache = {}
|
|
141
|
+
cache_key = [node, node&.location, links, name_pin&.return_type, locals]
|
|
142
|
+
if @@inference_invalidation_key == api_map.hash
|
|
143
|
+
cached = @@inference_cache[cache_key]
|
|
144
|
+
return cached if cached
|
|
145
|
+
else
|
|
94
146
|
@@inference_invalidation_key = api_map.hash
|
|
147
|
+
@@inference_cache = {}
|
|
95
148
|
end
|
|
96
|
-
|
|
97
|
-
|
|
149
|
+
out = infer_uncached(api_map, name_pin, locals).downcast_to_literal_if_possible
|
|
150
|
+
logger.debug { "Chain#infer() - caching result - cache_key_hash=#{cache_key.hash}, links.map(&:hash)=#{links.map(&:hash)}, links=#{links}, cache_key.map(&:hash) = #{cache_key.map(&:hash)}, cache_key=#{cache_key}" }
|
|
151
|
+
@@inference_cache[cache_key] = out
|
|
98
152
|
end
|
|
99
153
|
|
|
100
154
|
# @param api_map [ApiMap]
|
|
101
155
|
# @param name_pin [Pin::Base]
|
|
102
|
-
# @param locals [::
|
|
156
|
+
# @param locals [::Array<Pin::LocalVariable>]
|
|
103
157
|
# @return [ComplexType]
|
|
104
158
|
def infer_uncached api_map, name_pin, locals
|
|
105
|
-
from_here = base.infer(api_map, name_pin, locals) unless links.length == 1
|
|
106
|
-
if from_here
|
|
107
|
-
name_pin = name_pin.proxy(from_here)
|
|
108
|
-
end
|
|
109
159
|
pins = define(api_map, name_pin, locals)
|
|
110
|
-
|
|
111
|
-
|
|
160
|
+
if pins.empty?
|
|
161
|
+
logger.debug { "Chain#infer_uncached(links=#{links.map(&:desc)}, locals=#{locals.map(&:desc)}) => undefined - no pins" }
|
|
162
|
+
return ComplexType::UNDEFINED
|
|
163
|
+
end
|
|
164
|
+
type = infer_from_definitions(pins, links.last.last_context, api_map, locals)
|
|
165
|
+
out = maybe_nil(type)
|
|
166
|
+
logger.debug { "Chain#infer_uncached(links=#{self.links.map(&:desc)}, locals=#{locals.map(&:desc)}, name_pin=#{name_pin}, name_pin.closure=#{name_pin.closure.inspect}, name_pin.binder=#{name_pin.binder}) => #{out.rooted_tags.inspect}" }
|
|
167
|
+
out
|
|
112
168
|
end
|
|
113
169
|
|
|
114
170
|
# @return [Boolean]
|
|
@@ -137,6 +193,19 @@ module Solargraph
|
|
|
137
193
|
links.any?(&:nullable?)
|
|
138
194
|
end
|
|
139
195
|
|
|
196
|
+
include Logging
|
|
197
|
+
|
|
198
|
+
# @return [String]
|
|
199
|
+
def desc
|
|
200
|
+
links.map(&:desc).to_s
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def to_s
|
|
204
|
+
desc
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
include Logging
|
|
208
|
+
|
|
140
209
|
private
|
|
141
210
|
|
|
142
211
|
# @param pins [::Array<Pin::Base>]
|
|
@@ -144,16 +213,18 @@ module Solargraph
|
|
|
144
213
|
# @param api_map [ApiMap]
|
|
145
214
|
# @param locals [::Enumerable<Pin::LocalVariable>]
|
|
146
215
|
# @return [ComplexType]
|
|
147
|
-
def
|
|
148
|
-
|
|
216
|
+
def infer_from_definitions pins, context, api_map, locals
|
|
217
|
+
# @type [::Array<ComplexType>]
|
|
218
|
+
types = []
|
|
219
|
+
unresolved_pins = []
|
|
149
220
|
# @todo this param tag shouldn't be needed to probe the type
|
|
150
221
|
# @todo ...but given it is needed, typecheck should complain that it is needed
|
|
151
222
|
# @param pin [Pin::Base]
|
|
152
223
|
pins.each do |pin|
|
|
153
224
|
# Avoid infinite recursion
|
|
154
|
-
next if @@inference_stack.include?(pin
|
|
225
|
+
next if @@inference_stack.include?(pin)
|
|
155
226
|
|
|
156
|
-
@@inference_stack.push pin
|
|
227
|
+
@@inference_stack.push pin
|
|
157
228
|
type = pin.typify(api_map)
|
|
158
229
|
@@inference_stack.pop
|
|
159
230
|
if type.defined?
|
|
@@ -161,45 +232,51 @@ module Solargraph
|
|
|
161
232
|
# @todo even at strong, no typechecking complaint
|
|
162
233
|
# happens when a [Pin::Base,nil] is passed into a method
|
|
163
234
|
# that accepts only [Pin::Namespace] as an argument
|
|
164
|
-
type = type.resolve_generics(pin.closure, context.
|
|
165
|
-
end
|
|
166
|
-
if type.defined?
|
|
167
|
-
possibles.push type
|
|
168
|
-
break if pin.is_a?(Pin::Method)
|
|
235
|
+
type = type.resolve_generics(pin.closure, context.binder)
|
|
169
236
|
end
|
|
237
|
+
types << type
|
|
238
|
+
else
|
|
239
|
+
unresolved_pins << pin
|
|
170
240
|
end
|
|
171
241
|
end
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
@@inference_stack.pop
|
|
185
|
-
if type.defined?
|
|
186
|
-
possibles.push type
|
|
187
|
-
break if pin.is_a?(Pin::Method)
|
|
188
|
-
end
|
|
242
|
+
|
|
243
|
+
# Limit method inference recursion
|
|
244
|
+
if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
|
|
245
|
+
return ComplexType::UNDEFINED
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
@@inference_depth += 1
|
|
249
|
+
# @param pin [Pin::Base]
|
|
250
|
+
unresolved_pins.each do |pin|
|
|
251
|
+
# Avoid infinite recursion
|
|
252
|
+
if @@inference_stack.include?(pin.identity)
|
|
253
|
+
next
|
|
189
254
|
end
|
|
190
|
-
|
|
255
|
+
|
|
256
|
+
@@inference_stack.push(pin.identity)
|
|
257
|
+
type = pin.probe(api_map)
|
|
258
|
+
@@inference_stack.pop
|
|
259
|
+
types.push type if type
|
|
191
260
|
end
|
|
192
|
-
|
|
261
|
+
@@inference_depth -= 1
|
|
193
262
|
|
|
194
|
-
type = if
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
263
|
+
type = if types.empty?
|
|
264
|
+
ComplexType::UNDEFINED
|
|
265
|
+
elsif types.length > 1
|
|
266
|
+
# Move nil to the end by convention
|
|
267
|
+
|
|
268
|
+
# @param a [ComplexType::UniqueType]
|
|
269
|
+
sorted = types.flat_map(&:items).sort { |a, _| a.tag == 'nil' ? 1 : 0 }
|
|
270
|
+
ComplexType.new(sorted.uniq)
|
|
271
|
+
else
|
|
272
|
+
ComplexType.new(types)
|
|
273
|
+
end
|
|
274
|
+
if context.nil? || context.return_type.undefined?
|
|
275
|
+
# up to downstream to resolve self type
|
|
276
|
+
return type
|
|
199
277
|
end
|
|
200
|
-
return type if context.nil? || context.return_type.undefined?
|
|
201
278
|
|
|
202
|
-
type.
|
|
279
|
+
type.self_to_type(context.return_type)
|
|
203
280
|
end
|
|
204
281
|
|
|
205
282
|
# @param type [ComplexType]
|
|
@@ -207,7 +284,7 @@ module Solargraph
|
|
|
207
284
|
def maybe_nil type
|
|
208
285
|
return type if type.undefined? || type.void? || type.nullable?
|
|
209
286
|
return type unless nullable?
|
|
210
|
-
ComplexType.
|
|
287
|
+
ComplexType.new(type.items + [ComplexType::NIL])
|
|
211
288
|
end
|
|
212
289
|
end
|
|
213
290
|
end
|
|
@@ -28,7 +28,7 @@ module Solargraph
|
|
|
28
28
|
# syntax errors will be repaired.
|
|
29
29
|
# @return [String] The updated text.
|
|
30
30
|
def write text, nullable = false
|
|
31
|
-
if nullable and !range.nil? and new_text.match(/[
|
|
31
|
+
if nullable and !range.nil? and new_text.match(/[.\[{(@$:]$/)
|
|
32
32
|
[':', '@'].each do |dupable|
|
|
33
33
|
next unless new_text == dupable
|
|
34
34
|
offset = Position.to_offset(text, range.start)
|
|
@@ -59,7 +59,7 @@ module Solargraph
|
|
|
59
59
|
else
|
|
60
60
|
result = commit text, fixed
|
|
61
61
|
off = Position.to_offset(text, range.start)
|
|
62
|
-
match = result[0, off].match(/[
|
|
62
|
+
match = result[0, off].match(/[.:]+\z/)
|
|
63
63
|
if match
|
|
64
64
|
result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..-1]
|
|
65
65
|
end
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Solargraph
|
|
4
4
|
class Source
|
|
5
|
-
# Information about a
|
|
6
|
-
# there.
|
|
5
|
+
# Information about a single Position in a Source, including the
|
|
6
|
+
# word located there.
|
|
7
7
|
#
|
|
8
8
|
class Cursor
|
|
9
9
|
# @return [Position]
|
|
@@ -124,7 +124,7 @@ module Solargraph
|
|
|
124
124
|
def node_position
|
|
125
125
|
@node_position ||= begin
|
|
126
126
|
if start_of_word.empty?
|
|
127
|
-
match = source.code[0, offset].match(
|
|
127
|
+
match = source.code[0, offset].match(/\s*(\.|:+)\s*$/)
|
|
128
128
|
if match
|
|
129
129
|
Position.from_offset(source.code, offset - match[0].length)
|
|
130
130
|
else
|
|
@@ -159,7 +159,7 @@ module Solargraph
|
|
|
159
159
|
#
|
|
160
160
|
# @return [Regexp]
|
|
161
161
|
def end_word_pattern
|
|
162
|
-
/^([a-z0-9_]|[^\u0000-\u007F])*[
|
|
162
|
+
/^([a-z0-9_]|[^\u0000-\u007F])*[?!]?/i
|
|
163
163
|
end
|
|
164
164
|
end
|
|
165
165
|
end
|
|
@@ -32,8 +32,8 @@ module Solargraph
|
|
|
32
32
|
# @return [Source::Chain]
|
|
33
33
|
def chain
|
|
34
34
|
# Special handling for files that end with an integer and a period
|
|
35
|
-
return Chain.new([Chain::Literal.new('Integer'), Chain::UNDEFINED_CALL]) if phrase =~ /^[0-9]+\.$/
|
|
36
|
-
return Chain.new([Chain::Literal.new('Symbol')]) if phrase.start_with?(':') && !phrase.start_with?('::')
|
|
35
|
+
return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])), Chain::UNDEFINED_CALL]) if phrase =~ /^[0-9]+\.$/
|
|
36
|
+
return Chain.new([Chain::Literal.new('Symbol', phrase[1..].to_sym)]) if phrase.start_with?(':') && !phrase.start_with?('::')
|
|
37
37
|
return SourceChainer.chain(source, Position.new(position.line, position.character + 1)) if end_of_phrase.strip == '::' && source.code[Position.to_offset(source.code, position)].to_s.match?(/[a-z]/i)
|
|
38
38
|
begin
|
|
39
39
|
return Chain.new([]) if phrase.end_with?('..')
|
|
@@ -97,7 +97,7 @@ module Solargraph
|
|
|
97
97
|
# @return [String]
|
|
98
98
|
def end_of_phrase
|
|
99
99
|
@end_of_phrase ||= begin
|
|
100
|
-
match = phrase.match(
|
|
100
|
+
match = phrase.match(/\s*(\.{1}|::)\s*$/)
|
|
101
101
|
if match
|
|
102
102
|
match[0]
|
|
103
103
|
else
|