solargraph 0.58.2 → 0.59.0.dev.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 +4 -5
- data/.github/workflows/plugins.yml +41 -34
- data/.github/workflows/rspec.yml +44 -23
- data/.github/workflows/typecheck.yml +2 -2
- data/.rubocop.yml +32 -5
- data/.rubocop_todo.yml +50 -966
- 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 +13 -3
- data/lib/solargraph/api_map/index.rb +23 -18
- data/lib/solargraph/api_map/source_to_yard.rb +22 -9
- data/lib/solargraph/api_map/store.rb +33 -28
- data/lib/solargraph/api_map.rb +150 -82
- data/lib/solargraph/bench.rb +44 -45
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +28 -17
- data/lib/solargraph/complex_type/unique_type.rb +218 -57
- data/lib/solargraph/complex_type.rb +170 -57
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
- 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 +15 -15
- data/lib/solargraph/convention/gemspec.rb +23 -23
- data/lib/solargraph/convention/rakefile.rb +17 -17
- 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 +78 -78
- data/lib/solargraph/converters/dd.rb +19 -17
- data/lib/solargraph/converters/dl.rb +17 -15
- data/lib/solargraph/converters/dt.rb +17 -15
- data/lib/solargraph/converters/misc.rb +3 -1
- 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 +37 -41
- data/lib/solargraph/doc_map.rb +133 -373
- data/lib/solargraph/equality.rb +4 -4
- data/lib/solargraph/gem_pins.rb +21 -20
- data/lib/solargraph/language_server/error_codes.rb +20 -20
- 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 +30 -22
- data/lib/solargraph/language_server/message/base.rb +97 -97
- data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
- 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 +32 -32
- data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
- data/lib/solargraph/language_server/message/extended/search.rb +20 -20
- data/lib/solargraph/language_server/message/initialize.rb +197 -191
- 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 +23 -16
- 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 +18 -11
- data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
- data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
- 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/workspace/did_change_configuration.rb +41 -35
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
- data/lib/solargraph/language_server/message.rb +94 -94
- data/lib/solargraph/language_server/request.rb +29 -27
- data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
- data/lib/solargraph/language_server/uri_helpers.rb +49 -49
- data/lib/solargraph/library.rb +85 -44
- data/lib/solargraph/location.rb +17 -14
- data/lib/solargraph/logging.rb +24 -4
- data/lib/solargraph/page.rb +92 -92
- data/lib/solargraph/parser/comment_ripper.rb +19 -4
- data/lib/solargraph/parser/flow_sensitive_typing.rb +326 -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 +32 -14
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
- data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
- 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 +12 -12
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
- 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/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/until_node.rb +29 -29
- 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 +14 -12
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +3 -1
- data/lib/solargraph/parser.rb +25 -23
- data/lib/solargraph/pin/base.rb +126 -80
- 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 +43 -45
- 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 +153 -104
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +19 -12
- data/lib/solargraph/pin/parameter.rb +100 -36
- data/lib/solargraph/pin/proxy_type.rb +4 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference.rb +19 -0
- data/lib/solargraph/pin/search.rb +3 -2
- data/lib/solargraph/pin/signature.rb +15 -12
- 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 +490 -73
- data/lib/solargraph/position.rb +14 -10
- data/lib/solargraph/range.rb +16 -15
- data/lib/solargraph/rbs_map/conversions.rb +343 -214
- data/lib/solargraph/rbs_map/core_fills.rb +91 -84
- 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 +77 -32
- data/lib/solargraph/server_methods.rb +16 -16
- data/lib/solargraph/shell.rb +128 -73
- data/lib/solargraph/source/chain/array.rb +39 -37
- data/lib/solargraph/source/chain/call.rb +96 -56
- data/lib/solargraph/source/chain/class_variable.rb +13 -13
- data/lib/solargraph/source/chain/constant.rb +5 -1
- data/lib/solargraph/source/chain/global_variable.rb +13 -13
- data/lib/solargraph/source/chain/hash.rb +8 -5
- 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 +99 -109
- data/lib/solargraph/source/chain/literal.rb +9 -6
- data/lib/solargraph/source/chain/or.rb +10 -4
- data/lib/solargraph/source/chain/q_call.rb +13 -11
- data/lib/solargraph/source/chain/variable.rb +15 -13
- data/lib/solargraph/source/chain/z_super.rb +28 -30
- data/lib/solargraph/source/chain.rb +49 -38
- data/lib/solargraph/source/change.rb +12 -5
- data/lib/solargraph/source/cursor.rb +23 -17
- 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 +48 -29
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +71 -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 +195 -120
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +13 -10
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +149 -30
- data/lib/solargraph/yard_map/helpers.rb +8 -3
- 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_tags.rb +20 -20
- data/lib/solargraph/yardoc.rb +33 -23
- data/lib/solargraph.rb +29 -8
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/fills/tuple/tuple.rbs +28 -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 +36 -34
- metadata +38 -33
- 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
|
@@ -6,31 +6,127 @@ module Solargraph
|
|
|
6
6
|
# include Solargraph::Source::NodeMethods
|
|
7
7
|
include Solargraph::Parser::NodeMethods
|
|
8
8
|
|
|
9
|
-
# @return [Parser::AST::Node
|
|
10
|
-
attr_reader :
|
|
9
|
+
# @return [Array<Parser::AST::Node>]
|
|
10
|
+
attr_reader :assignments
|
|
11
11
|
|
|
12
12
|
attr_accessor :mass_assignment
|
|
13
13
|
|
|
14
|
+
# @return [Range, nil]
|
|
15
|
+
attr_reader :presence
|
|
16
|
+
|
|
14
17
|
# @param return_type [ComplexType, nil]
|
|
18
|
+
# @param assignment [Parser::AST::Node, nil] First assignment
|
|
19
|
+
# that was made to this variable
|
|
20
|
+
# @param assignments [Array<Parser::AST::Node>] Possible
|
|
21
|
+
# assignments that may have been made to this variable
|
|
15
22
|
# @param mass_assignment [::Array(Parser::AST::Node, Integer), nil]
|
|
16
|
-
# @param assignment [Parser::AST::Node, nil]
|
|
17
|
-
|
|
23
|
+
# @param assignment [Parser::AST::Node, nil] First assignment
|
|
24
|
+
# that was made to this variable
|
|
25
|
+
# @param assignments [Array<Parser::AST::Node>] Possible
|
|
26
|
+
# assignments that may have been made to this variable
|
|
27
|
+
# @param exclude_return_type [ComplexType, nil] Ensure any
|
|
28
|
+
# return type returned will never include any of these unique
|
|
29
|
+
# types in the unique types of its complex type.
|
|
30
|
+
#
|
|
31
|
+
# Example: If a return type is 'Float | Integer | nil' and the
|
|
32
|
+
# exclude_return_type is 'Integer', the resulting return
|
|
33
|
+
# type will be 'Float | nil' because Integer is excluded.
|
|
34
|
+
# @param intersection_return_type [ComplexType, nil] Ensure each unique
|
|
35
|
+
# return type is compatible with at least one element of this
|
|
36
|
+
# complex type. If a ComplexType used as a return type is an
|
|
37
|
+
# union type - we can return any of these - these are
|
|
38
|
+
# intersection types - everything we return needs to meet at least
|
|
39
|
+
# one of these unique types.
|
|
40
|
+
#
|
|
41
|
+
# Example: If a return type is 'Numeric | nil' and the
|
|
42
|
+
# intersection_return_type is 'Float | nil', the resulting return
|
|
43
|
+
# type will be 'Float | nil' because Float is compatible
|
|
44
|
+
# with Numeric and nil is compatible with nil.
|
|
45
|
+
# @see https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types
|
|
46
|
+
# @see https://en.wikipedia.org/wiki/Intersection_type#TypeScript_example
|
|
47
|
+
# @param presence [Range, nil]
|
|
48
|
+
# @param [Hash{Symbol => Object}] splat
|
|
49
|
+
def initialize assignment: nil, assignments: [], mass_assignment: nil,
|
|
50
|
+
presence: nil, return_type: nil,
|
|
51
|
+
intersection_return_type: nil, exclude_return_type: nil,
|
|
52
|
+
**splat
|
|
18
53
|
super(**splat)
|
|
19
|
-
@
|
|
54
|
+
@assignments = (assignment.nil? ? [] : [assignment]) + assignments
|
|
20
55
|
# @type [nil, ::Array(Parser::AST::Node, Integer)]
|
|
21
|
-
@mass_assignment =
|
|
56
|
+
@mass_assignment = mass_assignment
|
|
22
57
|
@return_type = return_type
|
|
58
|
+
@intersection_return_type = intersection_return_type
|
|
59
|
+
@exclude_return_type = exclude_return_type
|
|
60
|
+
@presence = presence
|
|
23
61
|
end
|
|
24
62
|
|
|
25
|
-
|
|
63
|
+
# @param presence [Range]
|
|
64
|
+
# @param exclude_return_type [ComplexType, nil]
|
|
65
|
+
# @param intersection_return_type [ComplexType, nil]
|
|
66
|
+
# @param source [::Symbol]
|
|
67
|
+
#
|
|
68
|
+
# @return [self]
|
|
69
|
+
def downcast presence:, exclude_return_type: nil, intersection_return_type: nil,
|
|
70
|
+
source: self.source
|
|
71
|
+
result = dup
|
|
72
|
+
result.exclude_return_type = exclude_return_type
|
|
73
|
+
result.intersection_return_type = intersection_return_type
|
|
74
|
+
result.source = source
|
|
75
|
+
result.presence = presence
|
|
76
|
+
result.reset_generated!
|
|
77
|
+
result
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def reset_generated!
|
|
81
|
+
@assignment = nil
|
|
82
|
+
super
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def combine_with other, attrs = {}
|
|
86
|
+
new_assignments = combine_assignments(other)
|
|
26
87
|
new_attrs = attrs.merge({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
88
|
+
# default values don't exist in RBS parameters; it just
|
|
89
|
+
# tells you if the arg is optional or not. Prefer a
|
|
90
|
+
# provided value if we have one here since we can't rely on
|
|
91
|
+
# it from RBS so we can infer from it and typecheck on it.
|
|
92
|
+
assignment: choose(other, :assignment),
|
|
93
|
+
assignments: new_assignments,
|
|
94
|
+
mass_assignment: combine_mass_assignment(other),
|
|
95
|
+
return_type: combine_return_type(other),
|
|
96
|
+
intersection_return_type: combine_types(other, :intersection_return_type),
|
|
97
|
+
exclude_return_type: combine_types(other, :exclude_return_type),
|
|
98
|
+
presence: combine_presence(other)
|
|
99
|
+
})
|
|
31
100
|
super(other, new_attrs)
|
|
32
101
|
end
|
|
33
102
|
|
|
103
|
+
# @param other [self]
|
|
104
|
+
#
|
|
105
|
+
# @return [Array(AST::Node, Integer), nil]
|
|
106
|
+
def combine_mass_assignment other
|
|
107
|
+
# @todo pick first non-nil arbitrarily - we don't yet support
|
|
108
|
+
# mass assignment merging
|
|
109
|
+
mass_assignment || other.mass_assignment
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @return [Parser::AST::Node, nil]
|
|
113
|
+
def assignment
|
|
114
|
+
@assignment ||= assignments.last
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @param other [self]
|
|
118
|
+
#
|
|
119
|
+
# @return [::Array<Parser::AST::Node>]
|
|
120
|
+
def combine_assignments other
|
|
121
|
+
(other.assignments + assignments).uniq
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def inner_desc
|
|
125
|
+
super + ", presence=#{presence.inspect}, assignments=#{assignments}, " \
|
|
126
|
+
"intersection_return_type=#{intersection_return_type&.rooted_tags.inspect}, " \
|
|
127
|
+
"exclude_return_type=#{exclude_return_type&.rooted_tags.inspect}"
|
|
128
|
+
end
|
|
129
|
+
|
|
34
130
|
def completion_item_kind
|
|
35
131
|
Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
|
|
36
132
|
end
|
|
@@ -40,10 +136,6 @@ module Solargraph
|
|
|
40
136
|
Solargraph::LanguageServer::SymbolKinds::VARIABLE
|
|
41
137
|
end
|
|
42
138
|
|
|
43
|
-
def return_type
|
|
44
|
-
@return_type ||= generate_complex_type
|
|
45
|
-
end
|
|
46
|
-
|
|
47
139
|
def nil_assignment?
|
|
48
140
|
# this will always be false - should it be return_type ==
|
|
49
141
|
# ComplexType::NIL or somesuch?
|
|
@@ -57,7 +149,7 @@ module Solargraph
|
|
|
57
149
|
# @param parent_node [Parser::AST::Node]
|
|
58
150
|
# @param api_map [ApiMap]
|
|
59
151
|
# @return [::Array<ComplexType>]
|
|
60
|
-
def return_types_from_node
|
|
152
|
+
def return_types_from_node parent_node, api_map
|
|
61
153
|
types = []
|
|
62
154
|
value_position_nodes_only(parent_node).each do |node|
|
|
63
155
|
# Nil nodes may not have a location
|
|
@@ -67,10 +159,12 @@ module Solargraph
|
|
|
67
159
|
rng = Range.from_node(node)
|
|
68
160
|
next if rng.nil?
|
|
69
161
|
pos = rng.ending
|
|
162
|
+
# @sg-ignore Need to add nil check here
|
|
70
163
|
clip = api_map.clip_at(location.filename, pos)
|
|
71
164
|
# Use the return node for inference. The clip might infer from the
|
|
72
165
|
# first node in a method call instead of the entire call.
|
|
73
166
|
chain = Parser.chain(node, nil, nil)
|
|
167
|
+
# @sg-ignore Need to add nil check here
|
|
74
168
|
result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
|
|
75
169
|
types.push result unless result.undefined?
|
|
76
170
|
end
|
|
@@ -79,13 +173,15 @@ module Solargraph
|
|
|
79
173
|
end
|
|
80
174
|
|
|
81
175
|
# @param api_map [ApiMap]
|
|
82
|
-
# @return [ComplexType]
|
|
176
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
83
177
|
def probe api_map
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
end
|
|
178
|
+
assignment_types = assignments.flat_map { |node| return_types_from_node(node, api_map) }
|
|
179
|
+
type_from_assignment = ComplexType.new(assignment_types.flat_map(&:items).uniq) unless assignment_types.empty?
|
|
180
|
+
return adjust_type api_map, type_from_assignment unless type_from_assignment.nil?
|
|
88
181
|
|
|
182
|
+
# @todo should handle merging types from mass assignments as
|
|
183
|
+
# well so that we can do better flow sensitive typing with
|
|
184
|
+
# multiple assignments
|
|
89
185
|
unless @mass_assignment.nil?
|
|
90
186
|
mass_node, index = @mass_assignment
|
|
91
187
|
types = return_types_from_node(mass_node, api_map)
|
|
@@ -96,7 +192,10 @@ module Solargraph
|
|
|
96
192
|
type.all_params.first
|
|
97
193
|
end
|
|
98
194
|
end.compact!
|
|
99
|
-
|
|
195
|
+
|
|
196
|
+
return ComplexType::UNDEFINED if types.empty?
|
|
197
|
+
|
|
198
|
+
return adjust_type api_map, ComplexType.new(types.uniq).qualify(api_map, *gates)
|
|
100
199
|
end
|
|
101
200
|
|
|
102
201
|
ComplexType::UNDEFINED
|
|
@@ -113,13 +212,163 @@ module Solargraph
|
|
|
113
212
|
"#{super} = #{assignment&.type.inspect}"
|
|
114
213
|
end
|
|
115
214
|
|
|
215
|
+
# @return [ComplexType, nil]
|
|
216
|
+
def return_type
|
|
217
|
+
generate_complex_type || @return_type || intersection_return_type || ComplexType::UNDEFINED
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def typify api_map
|
|
221
|
+
raw_return_type = super
|
|
222
|
+
|
|
223
|
+
adjust_type(api_map, raw_return_type)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# @sg-ignore need boolish support for ? methods
|
|
227
|
+
def presence_certain?
|
|
228
|
+
exclude_return_type || intersection_return_type
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# @param other_loc [Location]
|
|
232
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
233
|
+
def starts_at? other_loc
|
|
234
|
+
location&.filename == other_loc.filename &&
|
|
235
|
+
presence &&
|
|
236
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
237
|
+
presence.start == other_loc.range.start
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Narrow the presence range to the intersection of both.
|
|
241
|
+
#
|
|
242
|
+
# @param other [self]
|
|
243
|
+
#
|
|
244
|
+
# @return [Range, nil]
|
|
245
|
+
def combine_presence other
|
|
246
|
+
return presence || other.presence if presence.nil? || other.presence.nil?
|
|
247
|
+
|
|
248
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
249
|
+
Range.new([presence.start, other.presence.start].max, [presence.ending, other.presence.ending].min)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# @param other [self]
|
|
253
|
+
# @return [Pin::Closure, nil]
|
|
254
|
+
def combine_closure other
|
|
255
|
+
return closure if closure == other.closure
|
|
256
|
+
|
|
257
|
+
# choose first defined, as that establishes the scope of the variable
|
|
258
|
+
if closure.nil? || other.closure.nil?
|
|
259
|
+
Solargraph.assert_or_log(:varible_closure_missing) do
|
|
260
|
+
'One of the local variables being combined is missing a closure: ' \
|
|
261
|
+
"#{inspect} vs #{other.inspect}"
|
|
262
|
+
end
|
|
263
|
+
return closure || other.closure
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
267
|
+
if closure.location.nil? || other.closure.location.nil?
|
|
268
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
269
|
+
return closure.location.nil? ? other.closure : closure
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# if filenames are different, this will just pick one
|
|
273
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
274
|
+
return closure if closure.location <= other.closure.location
|
|
275
|
+
|
|
276
|
+
other.closure
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# @param other_closure [Pin::Closure]
|
|
280
|
+
# @param other_loc [Location]
|
|
281
|
+
def visible_at? other_closure, other_loc
|
|
282
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
283
|
+
location.filename == other_loc.filename &&
|
|
284
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
285
|
+
(!presence || presence.include?(other_loc.range.start)) &&
|
|
286
|
+
visible_in_closure?(other_closure)
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
protected
|
|
290
|
+
|
|
291
|
+
attr_accessor :exclude_return_type, :intersection_return_type
|
|
292
|
+
|
|
293
|
+
# @return [Range]
|
|
294
|
+
attr_writer :presence
|
|
295
|
+
|
|
116
296
|
private
|
|
117
297
|
|
|
118
|
-
# @
|
|
298
|
+
# @param api_map [ApiMap]
|
|
299
|
+
# @param raw_return_type [ComplexType, ComplexType::UniqueType]
|
|
300
|
+
#
|
|
301
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
302
|
+
def adjust_type api_map, raw_return_type
|
|
303
|
+
qualified_exclude = exclude_return_type&.qualify(api_map, *(closure&.gates || ['']))
|
|
304
|
+
minus_exclusions = raw_return_type.exclude qualified_exclude, api_map
|
|
305
|
+
qualified_intersection = intersection_return_type&.qualify(api_map, *(closure&.gates || ['']))
|
|
306
|
+
minus_exclusions.intersect_with qualified_intersection, api_map
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# See if this variable is visible within 'viewing_closure'
|
|
310
|
+
#
|
|
311
|
+
# @param viewing_closure [Pin::Closure]
|
|
312
|
+
# @return [Boolean]
|
|
313
|
+
def visible_in_closure? viewing_closure
|
|
314
|
+
return false if closure.nil?
|
|
315
|
+
|
|
316
|
+
# if we're declared at top level, we can't be seen from within
|
|
317
|
+
# methods declared tere
|
|
318
|
+
|
|
319
|
+
# @sg-ignore Need to add nil check here
|
|
320
|
+
return false if viewing_closure.is_a?(Pin::Method) && closure.context.tags == 'Class<>'
|
|
321
|
+
|
|
322
|
+
# @sg-ignore Need to add nil check here
|
|
323
|
+
return true if viewing_closure.binder.namespace == closure.binder.namespace
|
|
324
|
+
|
|
325
|
+
# @sg-ignore Need to add nil check here
|
|
326
|
+
return true if viewing_closure.return_type == closure.context
|
|
327
|
+
|
|
328
|
+
# classes and modules can't see local variables declared
|
|
329
|
+
# in their parent closure, so stop here
|
|
330
|
+
return false if scope == :instance && viewing_closure.is_a?(Pin::Namespace)
|
|
331
|
+
|
|
332
|
+
parent_of_viewing_closure = viewing_closure.closure
|
|
333
|
+
|
|
334
|
+
return false if parent_of_viewing_closure.nil?
|
|
335
|
+
|
|
336
|
+
visible_in_closure?(parent_of_viewing_closure)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# @param other [self]
|
|
340
|
+
# @return [ComplexType, nil]
|
|
341
|
+
def combine_return_type other
|
|
342
|
+
combine_types(other, :return_type)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# @param other [self]
|
|
346
|
+
# @param attr [::Symbol]
|
|
347
|
+
#
|
|
348
|
+
# @return [ComplexType, nil]
|
|
349
|
+
def combine_types other, attr
|
|
350
|
+
# @type [ComplexType, nil]
|
|
351
|
+
type1 = send(attr)
|
|
352
|
+
# @type [ComplexType, nil]
|
|
353
|
+
type2 = other.send(attr)
|
|
354
|
+
if type1 && type2
|
|
355
|
+
types = (type1.items + type2.items).uniq
|
|
356
|
+
ComplexType.new(types)
|
|
357
|
+
else
|
|
358
|
+
type1 || type2
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# @return [::Symbol]
|
|
363
|
+
def scope
|
|
364
|
+
:instance
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# @return [ComplexType, nil]
|
|
119
368
|
def generate_complex_type
|
|
120
369
|
tag = docstring.tag(:type)
|
|
121
370
|
return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
|
|
122
|
-
|
|
371
|
+
nil
|
|
123
372
|
end
|
|
124
373
|
end
|
|
125
374
|
end
|
data/lib/solargraph/pin/block.rb
CHANGED
|
@@ -15,12 +15,14 @@ module Solargraph
|
|
|
15
15
|
# @param node [Parser::AST::Node, nil]
|
|
16
16
|
# @param context [ComplexType, nil]
|
|
17
17
|
# @param args [::Array<Parameter>]
|
|
18
|
+
# @param [Hash{Symbol => Object}] splat
|
|
18
19
|
def initialize receiver: nil, args: [], context: nil, node: nil, **splat
|
|
19
20
|
super(**splat, parameters: args)
|
|
20
21
|
@receiver = receiver
|
|
21
22
|
@context = context
|
|
22
23
|
@return_type = ComplexType.parse('::Proc')
|
|
23
24
|
@node = node
|
|
25
|
+
@name = '<block>'
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
# @param api_map [ApiMap]
|
|
@@ -30,14 +32,20 @@ module Solargraph
|
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def binder
|
|
33
|
-
@rebind
|
|
35
|
+
out = @rebind if @rebind&.defined?
|
|
36
|
+
out ||= super
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def context
|
|
40
|
+
@context = @rebind if @rebind&.defined?
|
|
41
|
+
super
|
|
34
42
|
end
|
|
35
43
|
|
|
36
44
|
# @param yield_types [::Array<ComplexType>]
|
|
37
45
|
# @param parameters [::Array<Parameter>]
|
|
38
46
|
#
|
|
39
47
|
# @return [::Array<ComplexType>]
|
|
40
|
-
def destructure_yield_types
|
|
48
|
+
def destructure_yield_types yield_types, parameters
|
|
41
49
|
# yielding a tuple into a block will destructure the tuple
|
|
42
50
|
if yield_types.length == 1
|
|
43
51
|
yield_type = yield_types.first
|
|
@@ -48,16 +56,19 @@ module Solargraph
|
|
|
48
56
|
|
|
49
57
|
# @param api_map [ApiMap]
|
|
50
58
|
# @return [::Array<ComplexType>]
|
|
51
|
-
def typify_parameters
|
|
59
|
+
def typify_parameters api_map
|
|
52
60
|
chain = Parser.chain(receiver, filename, node)
|
|
61
|
+
# @sg-ignore Need to add nil check here
|
|
53
62
|
clip = api_map.clip_at(location.filename, location.range.start)
|
|
54
63
|
locals = clip.locals - [self]
|
|
64
|
+
# @sg-ignore Need to add nil check here
|
|
55
65
|
meths = chain.define(api_map, closure, locals)
|
|
56
66
|
# @todo Convert logic to use signatures
|
|
57
67
|
# @param meth [Pin::Method]
|
|
58
68
|
meths.each do |meth|
|
|
59
69
|
next if meth.block.nil?
|
|
60
70
|
|
|
71
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
61
72
|
yield_types = meth.block.parameters.map(&:return_type)
|
|
62
73
|
# 'arguments' is what the method says it will yield to the
|
|
63
74
|
# block; 'parameters' is what the block accepts
|
|
@@ -67,6 +78,7 @@ module Solargraph
|
|
|
67
78
|
param_type = chain.base.infer(api_map, param, locals)
|
|
68
79
|
unless arg_type.nil?
|
|
69
80
|
if arg_type.generic? && param_type.defined?
|
|
81
|
+
# @sg-ignore Need to add nil check here
|
|
70
82
|
namespace_pin = api_map.get_namespace_pins(meth.namespace, closure.namespace).first
|
|
71
83
|
arg_type.resolve_generics(namespace_pin, param_type)
|
|
72
84
|
else
|
|
@@ -86,16 +98,27 @@ module Solargraph
|
|
|
86
98
|
def maybe_rebind api_map
|
|
87
99
|
return ComplexType::UNDEFINED unless receiver
|
|
88
100
|
|
|
89
|
-
|
|
101
|
+
# @sg-ignore Need to add nil check here
|
|
102
|
+
chain = Parser.chain(receiver, location.filename, node)
|
|
103
|
+
# @sg-ignore Need to add nil check here
|
|
90
104
|
locals = api_map.source_map(location.filename).locals_at(location)
|
|
105
|
+
# @sg-ignore Need to add nil check here
|
|
91
106
|
receiver_pin = chain.define(api_map, closure, locals).first
|
|
92
107
|
return ComplexType::UNDEFINED unless receiver_pin
|
|
93
108
|
|
|
94
109
|
types = receiver_pin.docstring.tag(:yieldreceiver)&.types
|
|
95
110
|
return ComplexType::UNDEFINED unless types&.any?
|
|
96
111
|
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
name_pin = self
|
|
113
|
+
# if we have Foo.bar { |x| ... }, and the bar method references self...
|
|
114
|
+
target = if chain.base.defined?
|
|
115
|
+
# figure out Foo
|
|
116
|
+
chain.base.infer(api_map, name_pin, locals)
|
|
117
|
+
else
|
|
118
|
+
# if not, any self there must be the context of our closure
|
|
119
|
+
# @sg-ignore Need to add nil check here
|
|
120
|
+
closure.full_context
|
|
121
|
+
end
|
|
99
122
|
|
|
100
123
|
ComplexType.try_parse(*types).qualify(api_map, *receiver_pin.gates).self_to_type(target)
|
|
101
124
|
end
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Solargraph
|
|
2
4
|
module Pin
|
|
3
|
-
# Mix-in for pins which enclose code which the 'break' statement
|
|
5
|
+
# Mix-in for pins which enclose code which the 'break' statement
|
|
6
|
+
# works with-in - e.g., blocks, when, until, ...
|
|
4
7
|
module Breakable
|
|
5
8
|
# @return [Parser::AST::Node]
|
|
6
9
|
attr_reader :node
|
|
10
|
+
|
|
11
|
+
# @return [Location, nil]
|
|
12
|
+
attr_reader :location
|
|
7
13
|
end
|
|
8
14
|
end
|
|
9
15
|
end
|