solargraph 0.58.3 → 0.59.2
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/.envrc +3 -0
- data/.github/workflows/linting.yml +12 -5
- data/.github/workflows/plugins.yml +54 -34
- data/.github/workflows/rspec.yml +15 -28
- data/.github/workflows/typecheck.yml +6 -3
- data/.rubocop.yml +38 -6
- data/.rubocop_todo.yml +53 -966
- data/CHANGELOG.md +24 -0
- data/Gemfile +3 -1
- data/README.md +3 -3
- data/Rakefile +26 -23
- data/bin/solargraph +2 -1
- data/lib/solargraph/api_map/cache.rb +3 -3
- data/lib/solargraph/api_map/constants.rb +12 -3
- data/lib/solargraph/api_map/index.rb +29 -18
- data/lib/solargraph/api_map/source_to_yard.rb +22 -9
- data/lib/solargraph/api_map/store.rb +40 -30
- data/lib/solargraph/api_map.rb +160 -78
- data/lib/solargraph/bench.rb +2 -3
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +31 -18
- data/lib/solargraph/complex_type/unique_type.rb +221 -63
- data/lib/solargraph/complex_type.rb +173 -59
- data/lib/solargraph/convention/active_support_concern.rb +111 -111
- data/lib/solargraph/convention/base.rb +50 -50
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
- data/lib/solargraph/convention/data_definition.rb +5 -2
- data/lib/solargraph/convention/gemfile.rb +1 -1
- data/lib/solargraph/convention/gemspec.rb +1 -1
- data/lib/solargraph/convention/rakefile.rb +1 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
- data/lib/solargraph/convention/struct_definition.rb +8 -4
- data/lib/solargraph/convention.rb +2 -2
- data/lib/solargraph/converters/dd.rb +2 -0
- data/lib/solargraph/converters/dl.rb +2 -0
- data/lib/solargraph/converters/dt.rb +2 -0
- data/lib/solargraph/converters/misc.rb +2 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop.rb +11 -10
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/diagnostics/type_check.rb +11 -10
- data/lib/solargraph/diagnostics/update_errors.rb +4 -8
- data/lib/solargraph/diagnostics.rb +55 -55
- data/lib/solargraph/doc_map.rb +38 -39
- data/lib/solargraph/environ.rb +52 -52
- data/lib/solargraph/equality.rb +4 -4
- data/lib/solargraph/gem_pins.rb +4 -15
- data/lib/solargraph/language_server/error_codes.rb +10 -10
- data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
- data/lib/solargraph/language_server/host/dispatch.rb +3 -3
- data/lib/solargraph/language_server/host/message_worker.rb +4 -3
- data/lib/solargraph/language_server/host/sources.rb +2 -1
- data/lib/solargraph/language_server/host.rb +35 -28
- data/lib/solargraph/language_server/message/base.rb +1 -1
- data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
- data/lib/solargraph/language_server/message/extended/document.rb +1 -0
- data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
- data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
- data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
- data/lib/solargraph/language_server/message/extended/search.rb +1 -1
- data/lib/solargraph/language_server/message/initialize.rb +20 -14
- data/lib/solargraph/language_server/message/initialized.rb +28 -28
- data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
- data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
- data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
- data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
- data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
- data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
- data/lib/solargraph/language_server/message/text_document.rb +28 -28
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
- data/lib/solargraph/language_server/message.rb +1 -1
- data/lib/solargraph/language_server/progress.rb +143 -143
- data/lib/solargraph/language_server/request.rb +4 -2
- data/lib/solargraph/language_server/transport/adapter.rb +68 -68
- data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
- data/lib/solargraph/language_server/uri_helpers.rb +2 -2
- data/lib/solargraph/language_server.rb +20 -20
- data/lib/solargraph/library.rb +57 -38
- data/lib/solargraph/location.rb +17 -14
- data/lib/solargraph/logging.rb +22 -4
- data/lib/solargraph/page.rb +1 -1
- data/lib/solargraph/parser/comment_ripper.rb +19 -4
- data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
- data/lib/solargraph/parser/node_processor/base.rb +34 -4
- data/lib/solargraph/parser/node_processor.rb +8 -7
- data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +51 -25
- data/lib/solargraph/parser/parser_gem/node_methods.rb +181 -73
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/parser_gem.rb +2 -0
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +3 -1
- data/lib/solargraph/parser.rb +2 -0
- data/lib/solargraph/pin/base.rb +126 -82
- data/lib/solargraph/pin/base_variable.rb +273 -24
- data/lib/solargraph/pin/block.rb +29 -6
- data/lib/solargraph/pin/breakable.rb +7 -1
- data/lib/solargraph/pin/callable.rb +65 -21
- data/lib/solargraph/pin/closure.rb +7 -10
- data/lib/solargraph/pin/common.rb +24 -6
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/constant.rb +3 -5
- data/lib/solargraph/pin/conversions.rb +10 -4
- data/lib/solargraph/pin/delegated_method.rb +19 -8
- data/lib/solargraph/pin/documenting.rb +4 -2
- data/lib/solargraph/pin/instance_variable.rb +5 -1
- data/lib/solargraph/pin/keyword.rb +0 -4
- data/lib/solargraph/pin/local_variable.rb +15 -59
- data/lib/solargraph/pin/method.rb +158 -104
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +19 -12
- data/lib/solargraph/pin/parameter.rb +102 -36
- data/lib/solargraph/pin/proxy_type.rb +4 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/require.rb +14 -14
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference/type_alias.rb +16 -0
- data/lib/solargraph/pin/reference.rb +20 -0
- data/lib/solargraph/pin/search.rb +8 -7
- data/lib/solargraph/pin/signature.rb +15 -12
- data/lib/solargraph/pin/singleton.rb +11 -11
- data/lib/solargraph/pin/symbol.rb +2 -1
- data/lib/solargraph/pin/until.rb +2 -4
- data/lib/solargraph/pin/while.rb +2 -4
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin_cache.rb +22 -19
- data/lib/solargraph/position.rb +17 -10
- data/lib/solargraph/range.rb +16 -15
- data/lib/solargraph/rbs_map/conversions.rb +367 -231
- data/lib/solargraph/rbs_map/core_fills.rb +18 -11
- data/lib/solargraph/rbs_map/core_map.rb +24 -17
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
- data/lib/solargraph/rbs_map.rb +76 -32
- data/lib/solargraph/server_methods.rb +1 -1
- data/lib/solargraph/shell.rb +258 -66
- data/lib/solargraph/source/chain/array.rb +3 -12
- data/lib/solargraph/source/chain/block_symbol.rb +13 -13
- data/lib/solargraph/source/chain/block_variable.rb +13 -13
- data/lib/solargraph/source/chain/call.rb +96 -56
- data/lib/solargraph/source/chain/class_variable.rb +1 -1
- data/lib/solargraph/source/chain/constant.rb +5 -1
- data/lib/solargraph/source/chain/global_variable.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +8 -5
- data/lib/solargraph/source/chain/head.rb +19 -19
- data/lib/solargraph/source/chain/if.rb +12 -10
- data/lib/solargraph/source/chain/instance_variable.rb +24 -1
- data/lib/solargraph/source/chain/link.rb +12 -22
- data/lib/solargraph/source/chain/literal.rb +22 -15
- data/lib/solargraph/source/chain/or.rb +10 -4
- data/lib/solargraph/source/chain/q_call.rb +2 -0
- data/lib/solargraph/source/chain/variable.rb +3 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -3
- data/lib/solargraph/source/chain.rb +51 -38
- data/lib/solargraph/source/change.rb +12 -5
- data/lib/solargraph/source/cursor.rb +33 -18
- data/lib/solargraph/source/encoding_fixes.rb +6 -7
- data/lib/solargraph/source/source_chainer.rb +56 -32
- data/lib/solargraph/source/updater.rb +5 -1
- data/lib/solargraph/source.rb +59 -35
- data/lib/solargraph/source_map/clip.rb +54 -30
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +69 -42
- data/lib/solargraph/source_map.rb +21 -9
- data/lib/solargraph/type_checker/problem.rb +3 -1
- data/lib/solargraph/type_checker/rules.rb +81 -8
- data/lib/solargraph/type_checker.rb +196 -122
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +50 -28
- data/lib/solargraph/yard_map/cache.rb +25 -25
- data/lib/solargraph/yard_map/helpers.rb +8 -3
- data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
- data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
- data/lib/solargraph/yard_map/mapper.rb +13 -8
- data/lib/solargraph/yard_map.rb +17 -18
- data/lib/solargraph/yard_tags.rb +2 -2
- data/lib/solargraph/yardoc.rb +7 -4
- data/lib/solargraph.rb +33 -10
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/shims/ast/0/node.rbs +1 -1
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/solargraph.gemspec +37 -35
- metadata +41 -42
- data/lib/solargraph/type_checker/checks.rb +0 -124
- data/lib/solargraph/type_checker/param_def.rb +0 -37
- data/lib/solargraph/yard_map/to_method.rb +0 -89
- data/rbs/fills/tuple/tuple.rbs +0 -149
|
@@ -5,7 +5,9 @@ module Solargraph
|
|
|
5
5
|
class Chain
|
|
6
6
|
class Variable < Link
|
|
7
7
|
def resolve api_map, name_pin, locals
|
|
8
|
-
api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select
|
|
8
|
+
api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select do |p|
|
|
9
|
+
p.name == word
|
|
10
|
+
end
|
|
9
11
|
end
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -11,9 +11,7 @@ module Solargraph
|
|
|
11
11
|
attr_reader :arguments
|
|
12
12
|
|
|
13
13
|
# @param word [String]
|
|
14
|
-
# @param arguments [::Array<Chain>]
|
|
15
14
|
# @param with_block [Boolean] True if the chain is inside a block
|
|
16
|
-
# @param head [Boolean] True if the call is the start of its chain
|
|
17
15
|
def initialize word, with_block = false
|
|
18
16
|
super(word, nil, [], with_block)
|
|
19
17
|
end
|
|
@@ -22,7 +20,7 @@ module Solargraph
|
|
|
22
20
|
# @param name_pin [Pin::Base]
|
|
23
21
|
# @param locals [::Array<Pin::Base>]
|
|
24
22
|
def resolve api_map, name_pin, locals
|
|
25
|
-
|
|
23
|
+
super_pins(api_map, name_pin)
|
|
26
24
|
end
|
|
27
25
|
end
|
|
28
26
|
end
|
|
@@ -48,11 +48,6 @@ module Solargraph
|
|
|
48
48
|
|
|
49
49
|
attr_reader :node
|
|
50
50
|
|
|
51
|
-
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
52
|
-
protected def equality_fields
|
|
53
|
-
[links, node]
|
|
54
|
-
end
|
|
55
|
-
|
|
56
51
|
# @param node [Parser::AST::Node, nil]
|
|
57
52
|
# @param links [::Array<Chain::Link>]
|
|
58
53
|
# @param splat [Boolean]
|
|
@@ -71,6 +66,7 @@ module Solargraph
|
|
|
71
66
|
|
|
72
67
|
# @return [Chain]
|
|
73
68
|
def base
|
|
69
|
+
# @sg-ignore Need to add nil check here
|
|
74
70
|
@base ||= Chain.new(links[0..-2])
|
|
75
71
|
end
|
|
76
72
|
|
|
@@ -78,25 +74,25 @@ module Solargraph
|
|
|
78
74
|
#
|
|
79
75
|
# @param api_map [ApiMap]
|
|
80
76
|
#
|
|
81
|
-
# @param name_pin [Pin::Base] A pin
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
77
|
+
# @param name_pin [Pin::Base] A pin representing the closure in
|
|
78
|
+
# which expression is evaluated (e.g., a Method pin, or a
|
|
79
|
+
# Module or Class pin if not run within a method - both in
|
|
80
|
+
# terms of the closure around the chain, as well as the self
|
|
81
|
+
# type used for any method calls in head position.
|
|
86
82
|
#
|
|
87
83
|
# Requirements for name_pin:
|
|
88
84
|
#
|
|
89
85
|
# * name_pin.context: This should be a type representing the
|
|
90
|
-
# namespace where we can look up non-local variables
|
|
91
|
-
#
|
|
92
|
-
#
|
|
86
|
+
# namespace where we can look up non-local variables. If
|
|
87
|
+
# it is a Class<X>, we will look up :class scoped
|
|
88
|
+
# instance variables.
|
|
93
89
|
#
|
|
94
90
|
# * name_pin.binder: Used for method call lookups only
|
|
95
91
|
# (Chain::Call links). For method calls as the first
|
|
96
92
|
# element in the chain, 'name_pin.binder' should be the
|
|
97
93
|
# same as name_pin.context above. For method calls later
|
|
98
|
-
# in the chain (e.g., 'b' in a.b.c
|
|
99
|
-
# 'a'.
|
|
94
|
+
# in the chain, it changes. (e.g., for 'b' in a.b.c, it
|
|
95
|
+
# should represent the type of 'a').
|
|
100
96
|
#
|
|
101
97
|
# @param locals [::Array<Pin::LocalVariable>] Any local
|
|
102
98
|
# variables / method parameters etc visible by the statement
|
|
@@ -113,11 +109,14 @@ module Solargraph
|
|
|
113
109
|
#
|
|
114
110
|
# @todo ProxyType uses 'type' for the binder, but '
|
|
115
111
|
working_pin = name_pin
|
|
112
|
+
# @sg-ignore Need to add nil check here
|
|
116
113
|
links[0..-2].each do |link|
|
|
117
114
|
pins = link.resolve(api_map, working_pin, locals)
|
|
118
115
|
type = infer_from_definitions(pins, working_pin, api_map, locals)
|
|
119
116
|
if type.undefined?
|
|
120
|
-
logger.debug
|
|
117
|
+
logger.debug do
|
|
118
|
+
"Chain#define(links=#{links.map(&:desc)}, name_pin=#{name_pin.inspect}, locals=#{locals}) => [] - undefined type from #{link.desc}"
|
|
119
|
+
end
|
|
121
120
|
return []
|
|
122
121
|
end
|
|
123
122
|
# We continue to use the context from the head pin, in case
|
|
@@ -126,7 +125,9 @@ module Solargraph
|
|
|
126
125
|
# for the binder, as this is chaining off of it, and the
|
|
127
126
|
# binder is now the lhs of the rhs we are evaluating.
|
|
128
127
|
working_pin = Pin::ProxyType.anonymous(name_pin.context, binder: type, closure: name_pin, source: :chain)
|
|
129
|
-
logger.debug
|
|
128
|
+
logger.debug do
|
|
129
|
+
"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}"
|
|
130
|
+
end
|
|
130
131
|
end
|
|
131
132
|
links.last.last_context = working_pin
|
|
132
133
|
links.last.resolve(api_map, working_pin, locals)
|
|
@@ -138,7 +139,8 @@ module Solargraph
|
|
|
138
139
|
# @return [ComplexType]
|
|
139
140
|
# @sg-ignore
|
|
140
141
|
def infer api_map, name_pin, locals
|
|
141
|
-
|
|
142
|
+
# includes binder as it is mutable in Pin::Block
|
|
143
|
+
cache_key = [node, node&.location, links, name_pin&.return_type, name_pin&.binder, locals]
|
|
142
144
|
if @@inference_invalidation_key == api_map.hash
|
|
143
145
|
cached = @@inference_cache[cache_key]
|
|
144
146
|
return cached if cached
|
|
@@ -147,23 +149,31 @@ module Solargraph
|
|
|
147
149
|
@@inference_cache = {}
|
|
148
150
|
end
|
|
149
151
|
out = infer_uncached(api_map, name_pin, locals).downcast_to_literal_if_possible
|
|
150
|
-
logger.debug
|
|
152
|
+
logger.debug do
|
|
153
|
+
"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}"
|
|
154
|
+
end
|
|
151
155
|
@@inference_cache[cache_key] = out
|
|
152
156
|
end
|
|
153
157
|
|
|
154
158
|
# @param api_map [ApiMap]
|
|
155
159
|
# @param name_pin [Pin::Base]
|
|
156
160
|
# @param locals [::Array<Pin::LocalVariable>]
|
|
157
|
-
# @return [ComplexType]
|
|
161
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
158
162
|
def infer_uncached api_map, name_pin, locals
|
|
159
163
|
pins = define(api_map, name_pin, locals)
|
|
160
164
|
if pins.empty?
|
|
161
|
-
logger.debug
|
|
165
|
+
logger.debug do
|
|
166
|
+
"Chain#infer_uncached(links=#{links.map(&:desc)}, locals=#{locals.map(&:desc)}) => undefined - no pins"
|
|
167
|
+
end
|
|
162
168
|
return ComplexType::UNDEFINED
|
|
163
169
|
end
|
|
164
170
|
type = infer_from_definitions(pins, links.last.last_context, api_map, locals)
|
|
165
171
|
out = maybe_nil(type)
|
|
166
|
-
logger.debug
|
|
172
|
+
logger.debug do
|
|
173
|
+
"Chain#infer_uncached(links=#{links.map(&:desc)}, locals=#{locals.map(&:desc)}, " \
|
|
174
|
+
"name_pin=#{name_pin}, name_pin.closure=#{name_pin&.closure&.inspect}, " \
|
|
175
|
+
"name_pin.binder=#{name_pin&.binder}) => #{out.rooted_tags.inspect}"
|
|
176
|
+
end
|
|
167
177
|
out
|
|
168
178
|
end
|
|
169
179
|
|
|
@@ -209,12 +219,12 @@ module Solargraph
|
|
|
209
219
|
private
|
|
210
220
|
|
|
211
221
|
# @param pins [::Array<Pin::Base>]
|
|
212
|
-
# @param
|
|
222
|
+
# @param name_pin [Pin::Base]
|
|
213
223
|
# @param api_map [ApiMap]
|
|
214
224
|
# @param locals [::Enumerable<Pin::LocalVariable>]
|
|
215
|
-
# @return [ComplexType]
|
|
216
|
-
def infer_from_definitions pins,
|
|
217
|
-
# @type [::Array<ComplexType>]
|
|
225
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
226
|
+
def infer_from_definitions pins, name_pin, api_map, locals
|
|
227
|
+
# @type [::Array<ComplexType, ComplexType::UniqueType>]
|
|
218
228
|
types = []
|
|
219
229
|
unresolved_pins = []
|
|
220
230
|
# @todo this param tag shouldn't be needed to probe the type
|
|
@@ -232,7 +242,8 @@ module Solargraph
|
|
|
232
242
|
# @todo even at strong, no typechecking complaint
|
|
233
243
|
# happens when a [Pin::Base,nil] is passed into a method
|
|
234
244
|
# that accepts only [Pin::Namespace] as an argument
|
|
235
|
-
|
|
245
|
+
# @sg-ignore Need to add nil check here
|
|
246
|
+
type = type.resolve_generics(pin.closure, name_pin.binder)
|
|
236
247
|
end
|
|
237
248
|
types << type
|
|
238
249
|
else
|
|
@@ -241,17 +252,13 @@ module Solargraph
|
|
|
241
252
|
end
|
|
242
253
|
|
|
243
254
|
# Limit method inference recursion
|
|
244
|
-
if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
|
|
245
|
-
return ComplexType::UNDEFINED
|
|
246
|
-
end
|
|
255
|
+
return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
|
|
247
256
|
|
|
248
257
|
@@inference_depth += 1
|
|
249
258
|
# @param pin [Pin::Base]
|
|
250
259
|
unresolved_pins.each do |pin|
|
|
251
260
|
# Avoid infinite recursion
|
|
252
|
-
if @@inference_stack.include?(pin.identity)
|
|
253
|
-
next
|
|
254
|
-
end
|
|
261
|
+
next if @@inference_stack.include?(pin.identity)
|
|
255
262
|
|
|
256
263
|
@@inference_stack.push(pin.identity)
|
|
257
264
|
type = pin.probe(api_map)
|
|
@@ -271,21 +278,27 @@ module Solargraph
|
|
|
271
278
|
else
|
|
272
279
|
ComplexType.new(types)
|
|
273
280
|
end
|
|
274
|
-
if
|
|
281
|
+
if name_pin.nil? || name_pin.context.undefined?
|
|
275
282
|
# up to downstream to resolve self type
|
|
276
283
|
return type
|
|
277
284
|
end
|
|
278
|
-
|
|
279
|
-
type.self_to_type(context.return_type)
|
|
285
|
+
type.self_to_type(name_pin.context)
|
|
280
286
|
end
|
|
281
287
|
|
|
282
|
-
# @param type [ComplexType]
|
|
283
|
-
# @return [ComplexType]
|
|
288
|
+
# @param type [ComplexType, ComplexType::UniqueType]
|
|
289
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
284
290
|
def maybe_nil type
|
|
285
291
|
return type if type.undefined? || type.void? || type.nullable?
|
|
286
292
|
return type unless nullable?
|
|
287
293
|
ComplexType.new(type.items + [ComplexType::NIL])
|
|
288
294
|
end
|
|
295
|
+
|
|
296
|
+
protected
|
|
297
|
+
|
|
298
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
299
|
+
def equality_fields
|
|
300
|
+
[links, node]
|
|
301
|
+
end
|
|
289
302
|
end
|
|
290
303
|
end
|
|
291
304
|
end
|
|
@@ -7,13 +7,13 @@ module Solargraph
|
|
|
7
7
|
class Change
|
|
8
8
|
include EncodingFixes
|
|
9
9
|
|
|
10
|
-
# @return [Range]
|
|
10
|
+
# @return [Range, nil]
|
|
11
11
|
attr_reader :range
|
|
12
12
|
|
|
13
13
|
# @return [String]
|
|
14
14
|
attr_reader :new_text
|
|
15
15
|
|
|
16
|
-
# @param range [Range] The starting and ending positions of the change.
|
|
16
|
+
# @param range [Range, nil] The starting and ending positions of the change.
|
|
17
17
|
# If nil, the original text will be overwritten.
|
|
18
18
|
# @param new_text [String] The text to be changed.
|
|
19
19
|
def initialize range, new_text
|
|
@@ -28,12 +28,14 @@ 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
|
|
31
|
+
if nullable && !range.nil? && new_text.match(/[.\[{(@$:]$/)
|
|
32
32
|
[':', '@'].each do |dupable|
|
|
33
33
|
next unless new_text == dupable
|
|
34
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
34
35
|
offset = Position.to_offset(text, range.start)
|
|
35
36
|
if text[offset - 1] == dupable
|
|
36
37
|
p = Position.from_offset(text, offset - 1)
|
|
38
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
37
39
|
r = Change.new(Range.new(p, range.start), ' ')
|
|
38
40
|
text = r.write(text)
|
|
39
41
|
end
|
|
@@ -58,10 +60,13 @@ module Solargraph
|
|
|
58
60
|
fixed
|
|
59
61
|
else
|
|
60
62
|
result = commit text, fixed
|
|
63
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
61
64
|
off = Position.to_offset(text, range.start)
|
|
65
|
+
# @sg-ignore Need to add nil check here
|
|
62
66
|
match = result[0, off].match(/[.:]+\z/)
|
|
63
67
|
if match
|
|
64
|
-
|
|
68
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
69
|
+
result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..]
|
|
65
70
|
end
|
|
66
71
|
result
|
|
67
72
|
end
|
|
@@ -73,9 +78,11 @@ module Solargraph
|
|
|
73
78
|
# @param insert [String]
|
|
74
79
|
# @return [String]
|
|
75
80
|
def commit text, insert
|
|
81
|
+
# @sg-ignore Need to add nil check here
|
|
76
82
|
start_offset = Position.to_offset(text, range.start)
|
|
83
|
+
# @sg-ignore Need to add nil check here
|
|
77
84
|
end_offset = Position.to_offset(text, range.ending)
|
|
78
|
-
(start_offset
|
|
85
|
+
(start_offset.zero? ? '' : text[0..(start_offset - 1)].to_s) + normalize(insert) + text[end_offset..].to_s
|
|
79
86
|
end
|
|
80
87
|
end
|
|
81
88
|
end
|
|
@@ -19,7 +19,7 @@ module Solargraph
|
|
|
19
19
|
@position = Position.normalize(position)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
# @return [String]
|
|
22
|
+
# @return [String, nil]
|
|
23
23
|
def filename
|
|
24
24
|
source.filename
|
|
25
25
|
end
|
|
@@ -35,13 +35,17 @@ module Solargraph
|
|
|
35
35
|
# The part of the word before the current position. Given the text
|
|
36
36
|
# `foo.bar`, the start_of_word at position(0, 6) is `ba`.
|
|
37
37
|
#
|
|
38
|
+
# @sg-ignore Need to add nil check here
|
|
38
39
|
# @return [String]
|
|
39
40
|
def start_of_word
|
|
40
41
|
@start_of_word ||= begin
|
|
41
|
-
match = source.code[0..offset-1].to_s.match(start_word_pattern)
|
|
42
|
+
match = source.code[0..(offset - 1)].to_s.match(start_word_pattern)
|
|
42
43
|
result = (match ? match[0] : '')
|
|
43
44
|
# Including the preceding colon if the word appears to be a symbol
|
|
44
|
-
|
|
45
|
+
# @sg-ignore Need to add nil check here
|
|
46
|
+
if source.code[0..(offset - result.length - 1)].end_with?(':') && !source.code[0..(offset - result.length - 1)].end_with?('::')
|
|
47
|
+
result = ":#{result}"
|
|
48
|
+
end
|
|
45
49
|
result
|
|
46
50
|
end
|
|
47
51
|
end
|
|
@@ -50,16 +54,17 @@ module Solargraph
|
|
|
50
54
|
# `foo.bar`, the end_of_word at position (0,6) is `r`.
|
|
51
55
|
#
|
|
52
56
|
# @return [String]
|
|
57
|
+
# @sg-ignore Need to add nil check here
|
|
53
58
|
def end_of_word
|
|
54
59
|
@end_of_word ||= begin
|
|
55
|
-
match = source.code[offset
|
|
60
|
+
match = source.code[offset..].to_s.match(end_word_pattern)
|
|
56
61
|
match ? match[0] : ''
|
|
57
62
|
end
|
|
58
63
|
end
|
|
59
64
|
|
|
60
65
|
# @return [Boolean]
|
|
61
66
|
def start_of_constant?
|
|
62
|
-
source.code[offset-2, 2] == '::'
|
|
67
|
+
source.code[offset - 2, 2] == '::'
|
|
63
68
|
end
|
|
64
69
|
|
|
65
70
|
# The range of the word at the current position.
|
|
@@ -110,7 +115,17 @@ module Solargraph
|
|
|
110
115
|
def recipient
|
|
111
116
|
@recipient ||= begin
|
|
112
117
|
node = recipient_node
|
|
113
|
-
|
|
118
|
+
if node.nil?
|
|
119
|
+
nil
|
|
120
|
+
else
|
|
121
|
+
rng = Range.from_node(node)
|
|
122
|
+
if rng
|
|
123
|
+
Cursor.new(source, rng.ending)
|
|
124
|
+
else
|
|
125
|
+
pos = Position.new(position.line, [position.column - 1, 0].max)
|
|
126
|
+
Cursor.new(source, pos)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
114
129
|
end
|
|
115
130
|
end
|
|
116
131
|
alias receiver recipient
|
|
@@ -122,18 +137,18 @@ module Solargraph
|
|
|
122
137
|
|
|
123
138
|
# @return [Position]
|
|
124
139
|
def node_position
|
|
125
|
-
@node_position ||=
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
@node_position ||= if start_of_word.empty?
|
|
141
|
+
# @sg-ignore Need to add nil check here
|
|
142
|
+
match = source.code[0, offset].match(/\s*(\.|:+)\s*$/)
|
|
143
|
+
if match
|
|
144
|
+
# @sg-ignore Need to add nil check here
|
|
145
|
+
Position.from_offset(source.code, offset - match[0].length)
|
|
146
|
+
else
|
|
147
|
+
position
|
|
148
|
+
end
|
|
149
|
+
else
|
|
150
|
+
position
|
|
151
|
+
end
|
|
137
152
|
end
|
|
138
153
|
|
|
139
154
|
# @return [Parser::AST::Node, nil]
|
|
@@ -10,13 +10,12 @@ module Solargraph
|
|
|
10
10
|
# @param string [String]
|
|
11
11
|
# @return [String]
|
|
12
12
|
def normalize string
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
end
|
|
13
|
+
string.dup.force_encoding('UTF-8')
|
|
14
|
+
rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError,
|
|
15
|
+
::Encoding::InvalidByteSequenceError => e
|
|
16
|
+
# @todo Improve error handling
|
|
17
|
+
Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
|
|
18
|
+
string
|
|
20
19
|
end
|
|
21
20
|
end
|
|
22
21
|
end
|
|
@@ -32,26 +32,47 @@ 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
|
-
|
|
36
|
-
return Chain.new([Chain::Literal.new('
|
|
37
|
-
|
|
35
|
+
# if phrase =~ /^[0-9]+\.$/
|
|
36
|
+
# return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])),
|
|
37
|
+
# Chain::UNDEFINED_CALL])
|
|
38
|
+
# end
|
|
39
|
+
if phrase.start_with?(':') && !phrase.start_with?('::')
|
|
40
|
+
return Chain.new([Chain::Literal.new('Symbol',
|
|
41
|
+
# @sg-ignore Need to add nil check here
|
|
42
|
+
phrase[1..].to_sym)])
|
|
43
|
+
end
|
|
44
|
+
if end_of_phrase.strip == '::' && source.code[Position.to_offset(
|
|
45
|
+
source.code, position
|
|
46
|
+
)].to_s.match?(/[a-z]/i)
|
|
47
|
+
return SourceChainer.chain(source,
|
|
48
|
+
Position.new(position.line,
|
|
49
|
+
position.character + 1))
|
|
50
|
+
end
|
|
38
51
|
begin
|
|
39
52
|
return Chain.new([]) if phrase.end_with?('..')
|
|
53
|
+
# @type [::Parser::AST::Node, nil]
|
|
40
54
|
node = nil
|
|
55
|
+
# @type [::Parser::AST::Node, nil]
|
|
41
56
|
parent = nil
|
|
42
57
|
if !source.repaired? && source.parsed? && source.synchronized?
|
|
43
58
|
tree = source.tree_at(position.line, position.column)
|
|
44
59
|
node, parent = tree[0..2]
|
|
45
60
|
elsif source.parsed? && source.repaired? && end_of_phrase == '.'
|
|
46
61
|
node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
|
|
47
|
-
|
|
62
|
+
# provide filename and line so that we can look up local variables there later
|
|
63
|
+
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
|
|
48
64
|
elsif source.repaired?
|
|
49
|
-
node = Parser.parse(fixed_phrase)
|
|
65
|
+
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
|
|
50
66
|
else
|
|
51
|
-
|
|
67
|
+
unless source.error_ranges.any? do |r|
|
|
68
|
+
r.nil? || r.include?(fixed_position)
|
|
69
|
+
end
|
|
70
|
+
node, parent = source.tree_at(fixed_position.line,
|
|
71
|
+
fixed_position.column)[0..2]
|
|
72
|
+
end
|
|
52
73
|
# Exception for positions that chain literal nodes in unsynchronized sources
|
|
53
74
|
node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
|
|
54
|
-
node = Parser.parse(fixed_phrase) if node.nil?
|
|
75
|
+
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
|
|
55
76
|
end
|
|
56
77
|
rescue Parser::SyntaxError
|
|
57
78
|
return Chain.new([Chain::UNDEFINED_CALL])
|
|
@@ -79,14 +100,16 @@ module Solargraph
|
|
|
79
100
|
# @return [Solargraph::Source]
|
|
80
101
|
attr_reader :source
|
|
81
102
|
|
|
103
|
+
# @sg-ignore Need to add nil check here
|
|
82
104
|
# @return [String]
|
|
83
105
|
def phrase
|
|
84
|
-
@phrase ||= source.code[signature_data..offset-1]
|
|
106
|
+
@phrase ||= source.code[signature_data..(offset - 1)]
|
|
85
107
|
end
|
|
86
108
|
|
|
109
|
+
# @sg-ignore Need to add nil check here
|
|
87
110
|
# @return [String]
|
|
88
111
|
def fixed_phrase
|
|
89
|
-
@fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
|
|
112
|
+
@fixed_phrase ||= phrase[0..-(end_of_phrase.length + 1)]
|
|
90
113
|
end
|
|
91
114
|
|
|
92
115
|
# @return [Position]
|
|
@@ -95,6 +118,7 @@ module Solargraph
|
|
|
95
118
|
end
|
|
96
119
|
|
|
97
120
|
# @return [String]
|
|
121
|
+
# @sg-ignore Need to add nil check here
|
|
98
122
|
def end_of_phrase
|
|
99
123
|
@end_of_phrase ||= begin
|
|
100
124
|
match = phrase.match(/\s*(\.{1}|::)\s*$/)
|
|
@@ -137,47 +161,47 @@ module Solargraph
|
|
|
137
161
|
brackets = 0
|
|
138
162
|
squares = 0
|
|
139
163
|
parens = 0
|
|
140
|
-
index -=1
|
|
164
|
+
index -= 1
|
|
141
165
|
in_whitespace = false
|
|
142
166
|
while index >= 0
|
|
143
167
|
pos = Position.from_offset(@source.code, index)
|
|
144
|
-
break if index
|
|
145
|
-
break if brackets
|
|
168
|
+
break if index.positive? && @source.comment_at?(pos)
|
|
169
|
+
break if brackets.positive? || parens.positive? || squares.positive?
|
|
146
170
|
char = @source.code[index, 1]
|
|
147
171
|
break if char.nil? # @todo Is this the right way to handle this?
|
|
148
|
-
if brackets.zero?
|
|
172
|
+
if brackets.zero? && parens.zero? && squares.zero? && [' ', "\r", "\n", "\t"].include?(char)
|
|
149
173
|
in_whitespace = true
|
|
150
174
|
else
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
175
|
+
# @sg-ignore Need to add nil check here
|
|
176
|
+
if brackets.zero? && parens.zero? && squares.zero? && in_whitespace && !((char == '.') || @source.code[(index + 1)..].strip.start_with?('.'))
|
|
177
|
+
@source.code[(index + 1)..]
|
|
178
|
+
# @sg-ignore Need to add nil check here
|
|
179
|
+
@source.code[(index + 1)..].lstrip
|
|
180
|
+
# @sg-ignore Need to add nil check here
|
|
181
|
+
index += (@source.code[(index + 1)..].length - @source.code[(index + 1)..].lstrip.length)
|
|
182
|
+
break
|
|
158
183
|
end
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
184
|
+
case char
|
|
185
|
+
when ')'
|
|
186
|
+
parens -= 1
|
|
187
|
+
when ']'
|
|
188
|
+
squares -= 1
|
|
189
|
+
when '}'
|
|
164
190
|
brackets -= 1
|
|
165
|
-
|
|
191
|
+
when '('
|
|
166
192
|
parens += 1
|
|
167
|
-
|
|
193
|
+
when '{'
|
|
168
194
|
brackets += 1
|
|
169
|
-
|
|
195
|
+
when '['
|
|
170
196
|
squares += 1
|
|
171
197
|
end
|
|
172
|
-
if brackets.zero?
|
|
198
|
+
if brackets.zero? && parens.zero? && squares.zero?
|
|
173
199
|
break if ['"', "'", ',', ';', '%'].include?(char)
|
|
174
200
|
break if ['!', '?'].include?(char) && index < offset - 1
|
|
175
201
|
break if char == '$'
|
|
176
202
|
if char == '@'
|
|
177
203
|
index -= 1
|
|
178
|
-
if @source.code[index, 1] == '@'
|
|
179
|
-
index -= 1
|
|
180
|
-
end
|
|
204
|
+
index -= 1 if @source.code[index, 1] == '@'
|
|
181
205
|
break
|
|
182
206
|
end
|
|
183
207
|
elsif parens == 1 || brackets == 1 || squares == 1
|
|
@@ -29,14 +29,18 @@ module Solargraph
|
|
|
29
29
|
|
|
30
30
|
# @param text [String]
|
|
31
31
|
# @param nullable [Boolean]
|
|
32
|
+
# @sg-ignore changes doesn't mutate @output, so this can never be nil
|
|
32
33
|
# @return [String]
|
|
33
34
|
def write text, nullable = false
|
|
34
35
|
can_nullify = (nullable and changes.length == 1)
|
|
35
|
-
return @output if @input == text
|
|
36
|
+
return @output if (@input == text) && (can_nullify == @did_nullify)
|
|
36
37
|
@input = text
|
|
37
38
|
@output = text
|
|
38
39
|
@did_nullify = can_nullify
|
|
39
40
|
changes.each do |ch|
|
|
41
|
+
# @sg-ignore Wrong argument type for
|
|
42
|
+
# Solargraph::Source::Change#write: text expected String,
|
|
43
|
+
# received String, nil
|
|
40
44
|
@output = ch.write(@output, can_nullify)
|
|
41
45
|
end
|
|
42
46
|
@output
|