solargraph 0.58.3 → 0.60.4
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 +53 -37
- data/.github/workflows/rspec.yml +18 -28
- data/.github/workflows/typecheck.yml +6 -3
- data/.rubocop.yml +39 -6
- data/.rubocop_todo.yml +53 -966
- data/CHANGELOG.md +67 -0
- data/Gemfile +6 -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 +13 -4
- data/lib/solargraph/api_map/index.rb +42 -20
- data/lib/solargraph/api_map/source_to_yard.rb +22 -9
- data/lib/solargraph/api_map/store.rb +61 -36
- data/lib/solargraph/api_map.rb +191 -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 +225 -63
- data/lib/solargraph/complex_type.rb +190 -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 +39 -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 +63 -40
- 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 +222 -72
- 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 +73 -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 +157 -85
- 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 +67 -23
- data/lib/solargraph/pin/closure.rb +7 -10
- data/lib/solargraph/pin/common.rb +36 -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 +208 -113
- 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 +227 -238
- 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/rbs_translator.rb +206 -0
- data/lib/solargraph/server_methods.rb +1 -1
- data/lib/solargraph/shell.rb +330 -71
- 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 +159 -89
- 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 +19 -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 +87 -43
- 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 +71 -43
- 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 +30 -133
- data/lib/solargraph/source_map.rb +35 -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 +208 -125
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace/gemspecs.rb +373 -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/directives/attribute_directive.rb +65 -0
- data/lib/solargraph/yard_map/directives/domain_directive.rb +30 -0
- data/lib/solargraph/yard_map/directives/method_directive.rb +51 -0
- data/lib/solargraph/yard_map/directives/override_directive.rb +30 -0
- data/lib/solargraph/yard_map/directives/parse_directive.rb +53 -0
- data/lib/solargraph/yard_map/directives/visibility_directive.rb +70 -0
- data/lib/solargraph/yard_map/directives.rb +35 -0
- data/lib/solargraph/yard_map/helpers.rb +8 -3
- data/lib/solargraph/yard_map/macro.rb +113 -0
- 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 +65 -9
- data/lib/solargraph/yard_map.rb +19 -18
- data/lib/solargraph/yard_tags.rb +2 -2
- data/lib/solargraph/yardoc.rb +7 -4
- data/lib/solargraph.rb +34 -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 +39 -35
- metadata +77 -41
- 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
|
@@ -6,31 +6,38 @@ module Solargraph
|
|
|
6
6
|
class Source
|
|
7
7
|
class Chain
|
|
8
8
|
class Literal < Link
|
|
9
|
-
|
|
10
|
-
@word ||= "<#{@type}>"
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
attr_reader :value
|
|
9
|
+
attr_reader :word, :value
|
|
14
10
|
|
|
15
11
|
# @param type [String]
|
|
16
12
|
# @param node [Parser::AST::Node, Object]
|
|
17
13
|
def initialize type, node
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
super("<#{type}>")
|
|
15
|
+
|
|
16
|
+
# @todo We might be able to do some light inference from literals and
|
|
17
|
+
# tuples as long as literal values are intransitive.
|
|
18
|
+
|
|
19
|
+
# if node.is_a?(::Parser::AST::Node)
|
|
20
|
+
# # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
21
|
+
# if node.type == :true
|
|
22
|
+
# @value = true
|
|
23
|
+
# # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
24
|
+
# elsif node.type == :false
|
|
25
|
+
# @value = false
|
|
26
|
+
# # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
27
|
+
# elsif %i[int sym].include?(node.type)
|
|
28
|
+
# # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
29
|
+
# @value = node.children.first
|
|
30
|
+
# end
|
|
31
|
+
# end
|
|
27
32
|
@type = type
|
|
28
|
-
@literal_type = ComplexType.try_parse(@value.inspect)
|
|
33
|
+
# @literal_type = ComplexType.try_parse(@value.inspect)
|
|
34
|
+
@literal_type = ComplexType::UNDEFINED
|
|
29
35
|
@complex_type = ComplexType.try_parse(type)
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
33
39
|
protected def equality_fields
|
|
40
|
+
# @sg-ignore literal arrays in this module turn into ::Solargraph::Source::Chain::Array
|
|
34
41
|
super + [@value, @type, @literal_type, @complex_type]
|
|
35
42
|
end
|
|
36
43
|
|
|
@@ -4,18 +4,24 @@ module Solargraph
|
|
|
4
4
|
class Source
|
|
5
5
|
class Chain
|
|
6
6
|
class Or < Link
|
|
7
|
-
|
|
8
|
-
'<or>'
|
|
9
|
-
end
|
|
7
|
+
attr_reader :links
|
|
10
8
|
|
|
11
9
|
# @param links [::Array<Chain>]
|
|
12
10
|
def initialize links
|
|
11
|
+
super('<or>')
|
|
12
|
+
|
|
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
|
-
|
|
18
|
+
combined_type = Solargraph::ComplexType.new(types)
|
|
19
|
+
unless types.all?(&:nullable?)
|
|
20
|
+
# @sg-ignore flow sensitive typing should be able to handle redefinition
|
|
21
|
+
combined_type = combined_type.without_nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
[Solargraph::Pin::ProxyType.anonymous(combined_type, source: :chain)]
|
|
19
25
|
end
|
|
20
26
|
end
|
|
21
27
|
end
|
|
@@ -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
|
-
out = maybe_nil(type)
|
|
166
|
-
logger.debug
|
|
171
|
+
out = maybe_nil(type, api_map)
|
|
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
|
|
|
@@ -189,8 +199,38 @@ module Solargraph
|
|
|
189
199
|
@splat
|
|
190
200
|
end
|
|
191
201
|
|
|
192
|
-
|
|
193
|
-
|
|
202
|
+
# Whether this chain's inferred type should have nil added to it
|
|
203
|
+
# because a `&.` earlier in the chain might have short-circuited
|
|
204
|
+
# evaluation to nil.
|
|
205
|
+
#
|
|
206
|
+
# A `&.` only makes the *immediate* call nil-or-normal-result; a
|
|
207
|
+
# later, non-safe-navigated call in the same chain is still
|
|
208
|
+
# invoked on whatever that produced. If receiver is nil at that
|
|
209
|
+
# point, Ruby calls the method on nil itself instead of skipping
|
|
210
|
+
# it - so nil only continues to flow through subsequent links
|
|
211
|
+
# that NilClass defines as returning `self` (e.g., #tap,
|
|
212
|
+
# #itself). Any other subsequent call resolves to a concrete,
|
|
213
|
+
# non-nil-including type (e.g. NilClass#== returns Boolean), and
|
|
214
|
+
# nil no longer needs to be tracked past that point (unless a
|
|
215
|
+
# later `&.` reintroduces it).
|
|
216
|
+
#
|
|
217
|
+
# @param api_map [ApiMap]
|
|
218
|
+
# @return [Boolean]
|
|
219
|
+
def nullable? api_map
|
|
220
|
+
currently_nullable = false
|
|
221
|
+
links.each do |link|
|
|
222
|
+
if link.nullable?
|
|
223
|
+
currently_nullable = true
|
|
224
|
+
next
|
|
225
|
+
end
|
|
226
|
+
next unless currently_nullable
|
|
227
|
+
next unless link.is_a?(Chain::Call)
|
|
228
|
+
|
|
229
|
+
pin = api_map.get_method_stack('NilClass', link.word, scope: :instance).first
|
|
230
|
+
# @sg-ignore Need to add nil check here
|
|
231
|
+
currently_nullable = pin.nil? || pin.return_type.tag == 'self'
|
|
232
|
+
end
|
|
233
|
+
currently_nullable
|
|
194
234
|
end
|
|
195
235
|
|
|
196
236
|
include Logging
|
|
@@ -209,12 +249,12 @@ module Solargraph
|
|
|
209
249
|
private
|
|
210
250
|
|
|
211
251
|
# @param pins [::Array<Pin::Base>]
|
|
212
|
-
# @param
|
|
252
|
+
# @param name_pin [Pin::Base]
|
|
213
253
|
# @param api_map [ApiMap]
|
|
214
254
|
# @param locals [::Enumerable<Pin::LocalVariable>]
|
|
215
|
-
# @return [ComplexType]
|
|
216
|
-
def infer_from_definitions pins,
|
|
217
|
-
# @type [::Array<ComplexType>]
|
|
255
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
256
|
+
def infer_from_definitions pins, name_pin, api_map, locals
|
|
257
|
+
# @type [::Array<ComplexType, ComplexType::UniqueType>]
|
|
218
258
|
types = []
|
|
219
259
|
unresolved_pins = []
|
|
220
260
|
# @todo this param tag shouldn't be needed to probe the type
|
|
@@ -232,7 +272,8 @@ module Solargraph
|
|
|
232
272
|
# @todo even at strong, no typechecking complaint
|
|
233
273
|
# happens when a [Pin::Base,nil] is passed into a method
|
|
234
274
|
# that accepts only [Pin::Namespace] as an argument
|
|
235
|
-
|
|
275
|
+
# @sg-ignore Need to add nil check here
|
|
276
|
+
type = type.resolve_generics(pin.closure, name_pin.binder)
|
|
236
277
|
end
|
|
237
278
|
types << type
|
|
238
279
|
else
|
|
@@ -241,17 +282,13 @@ module Solargraph
|
|
|
241
282
|
end
|
|
242
283
|
|
|
243
284
|
# Limit method inference recursion
|
|
244
|
-
if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
|
|
245
|
-
return ComplexType::UNDEFINED
|
|
246
|
-
end
|
|
285
|
+
return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
|
|
247
286
|
|
|
248
287
|
@@inference_depth += 1
|
|
249
288
|
# @param pin [Pin::Base]
|
|
250
289
|
unresolved_pins.each do |pin|
|
|
251
290
|
# Avoid infinite recursion
|
|
252
|
-
if @@inference_stack.include?(pin.identity)
|
|
253
|
-
next
|
|
254
|
-
end
|
|
291
|
+
next if @@inference_stack.include?(pin.identity)
|
|
255
292
|
|
|
256
293
|
@@inference_stack.push(pin.identity)
|
|
257
294
|
type = pin.probe(api_map)
|
|
@@ -271,21 +308,28 @@ module Solargraph
|
|
|
271
308
|
else
|
|
272
309
|
ComplexType.new(types)
|
|
273
310
|
end
|
|
274
|
-
if
|
|
311
|
+
if name_pin.nil? || name_pin.context.undefined?
|
|
275
312
|
# up to downstream to resolve self type
|
|
276
313
|
return type
|
|
277
314
|
end
|
|
278
|
-
|
|
279
|
-
type.self_to_type(context.return_type)
|
|
315
|
+
type.self_to_type(name_pin.context)
|
|
280
316
|
end
|
|
281
317
|
|
|
282
|
-
# @param type [ComplexType]
|
|
283
|
-
# @
|
|
284
|
-
|
|
318
|
+
# @param type [ComplexType, ComplexType::UniqueType]
|
|
319
|
+
# @param api_map [ApiMap]
|
|
320
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
321
|
+
def maybe_nil type, api_map
|
|
285
322
|
return type if type.undefined? || type.void? || type.nullable?
|
|
286
|
-
return type unless nullable?
|
|
323
|
+
return type unless nullable?(api_map)
|
|
287
324
|
ComplexType.new(type.items + [ComplexType::NIL])
|
|
288
325
|
end
|
|
326
|
+
|
|
327
|
+
protected
|
|
328
|
+
|
|
329
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
330
|
+
def equality_fields
|
|
331
|
+
[links, node]
|
|
332
|
+
end
|
|
289
333
|
end
|
|
290
334
|
end
|
|
291
335
|
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
|