solargraph 0.58.1 → 0.59.0.dev.1
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 +40 -36
- data/.github/workflows/rspec.yml +45 -13
- data/.github/workflows/typecheck.yml +2 -2
- data/.rubocop_todo.yml +27 -49
- data/README.md +3 -3
- data/Rakefile +1 -0
- data/lib/solargraph/api_map/cache.rb +110 -110
- data/lib/solargraph/api_map/constants.rb +289 -279
- data/lib/solargraph/api_map/index.rb +204 -193
- data/lib/solargraph/api_map/source_to_yard.rb +109 -97
- data/lib/solargraph/api_map/store.rb +387 -384
- data/lib/solargraph/api_map.rb +1000 -945
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +242 -228
- data/lib/solargraph/complex_type/unique_type.rb +632 -482
- data/lib/solargraph/complex_type.rb +549 -444
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
- data/lib/solargraph/convention/data_definition.rb +108 -105
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
- data/lib/solargraph/convention/struct_definition.rb +168 -164
- data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
- data/lib/solargraph/diagnostics/rubocop.rb +119 -118
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
- data/lib/solargraph/diagnostics/type_check.rb +56 -55
- data/lib/solargraph/doc_map.rb +200 -439
- data/lib/solargraph/equality.rb +34 -34
- data/lib/solargraph/gem_pins.rb +97 -98
- data/lib/solargraph/language_server/host/dispatch.rb +131 -130
- data/lib/solargraph/language_server/host/message_worker.rb +113 -112
- data/lib/solargraph/language_server/host/sources.rb +100 -99
- data/lib/solargraph/language_server/host.rb +883 -878
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +109 -114
- data/lib/solargraph/language_server/message/extended/document.rb +24 -23
- data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
- data/lib/solargraph/language_server/message/text_document/definition.rb +42 -40
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +28 -26
- data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
- data/lib/solargraph/language_server/message/text_document/hover.rb +60 -58
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +27 -25
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +25 -23
- data/lib/solargraph/library.rb +729 -683
- data/lib/solargraph/location.rb +87 -82
- data/lib/solargraph/logging.rb +57 -37
- data/lib/solargraph/parser/comment_ripper.rb +76 -69
- data/lib/solargraph/parser/flow_sensitive_typing.rb +483 -255
- data/lib/solargraph/parser/node_processor/base.rb +122 -92
- data/lib/solargraph/parser/node_processor.rb +63 -62
- data/lib/solargraph/parser/parser_gem/class_methods.rb +167 -149
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
- data/lib/solargraph/parser/parser_gem/node_methods.rb +506 -486
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +41 -40
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +53 -52
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +296 -291
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
- data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
- data/lib/solargraph/parser/region.rb +75 -69
- data/lib/solargraph/parser/snippet.rb +17 -17
- data/lib/solargraph/pin/base.rb +761 -729
- data/lib/solargraph/pin/base_variable.rb +418 -126
- data/lib/solargraph/pin/block.rb +126 -104
- data/lib/solargraph/pin/breakable.rb +13 -9
- data/lib/solargraph/pin/callable.rb +278 -231
- data/lib/solargraph/pin/closure.rb +68 -72
- data/lib/solargraph/pin/common.rb +94 -79
- data/lib/solargraph/pin/compound_statement.rb +55 -0
- data/lib/solargraph/pin/conversions.rb +124 -123
- data/lib/solargraph/pin/delegated_method.rb +131 -120
- data/lib/solargraph/pin/documenting.rb +115 -114
- data/lib/solargraph/pin/instance_variable.rb +38 -34
- data/lib/solargraph/pin/keyword.rb +16 -20
- data/lib/solargraph/pin/local_variable.rb +31 -75
- data/lib/solargraph/pin/method.rb +720 -672
- data/lib/solargraph/pin/method_alias.rb +42 -34
- data/lib/solargraph/pin/namespace.rb +121 -115
- data/lib/solargraph/pin/parameter.rb +338 -275
- data/lib/solargraph/pin/proxy_type.rb +40 -39
- data/lib/solargraph/pin/reference/override.rb +47 -47
- data/lib/solargraph/pin/reference/superclass.rb +17 -15
- data/lib/solargraph/pin/reference.rb +41 -39
- data/lib/solargraph/pin/search.rb +62 -61
- data/lib/solargraph/pin/signature.rb +69 -61
- data/lib/solargraph/pin/symbol.rb +53 -53
- data/lib/solargraph/pin/until.rb +18 -18
- data/lib/solargraph/pin/while.rb +18 -18
- data/lib/solargraph/pin.rb +46 -44
- data/lib/solargraph/pin_cache.rb +665 -245
- data/lib/solargraph/position.rb +118 -119
- data/lib/solargraph/range.rb +112 -112
- data/lib/solargraph/rbs_map/conversions.rb +846 -823
- data/lib/solargraph/rbs_map/core_map.rb +65 -58
- data/lib/solargraph/rbs_map/stdlib_map.rb +72 -43
- data/lib/solargraph/rbs_map.rb +217 -163
- data/lib/solargraph/shell.rb +397 -352
- data/lib/solargraph/source/chain/call.rb +372 -337
- data/lib/solargraph/source/chain/constant.rb +28 -26
- data/lib/solargraph/source/chain/hash.rb +35 -34
- data/lib/solargraph/source/chain/if.rb +29 -28
- data/lib/solargraph/source/chain/instance_variable.rb +34 -13
- data/lib/solargraph/source/chain/literal.rb +53 -48
- data/lib/solargraph/source/chain/or.rb +31 -23
- data/lib/solargraph/source/chain.rb +294 -291
- data/lib/solargraph/source/change.rb +89 -82
- data/lib/solargraph/source/cursor.rb +172 -166
- data/lib/solargraph/source/source_chainer.rb +204 -194
- data/lib/solargraph/source/updater.rb +59 -55
- data/lib/solargraph/source.rb +524 -498
- data/lib/solargraph/source_map/clip.rb +237 -226
- data/lib/solargraph/source_map/data.rb +37 -34
- data/lib/solargraph/source_map/mapper.rb +282 -259
- data/lib/solargraph/source_map.rb +220 -212
- data/lib/solargraph/type_checker/problem.rb +34 -32
- data/lib/solargraph/type_checker/rules.rb +157 -84
- data/lib/solargraph/type_checker.rb +895 -814
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +257 -255
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +98 -97
- data/lib/solargraph/workspace.rb +362 -220
- data/lib/solargraph/yard_map/helpers.rb +45 -44
- data/lib/solargraph/yard_map/mapper/to_method.rb +134 -130
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
- data/lib/solargraph/yard_map/mapper.rb +84 -79
- data/lib/solargraph/yardoc.rb +97 -87
- data/lib/solargraph.rb +126 -105
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/fills/tuple/tuple.rbs +28 -0
- data/rbs/shims/ast/0/node.rbs +5 -0
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/rbs_collection.yaml +1 -1
- data/solargraph.gemspec +2 -1
- metadata +22 -17
- 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/sig/shims/ast/0/node.rbs +0 -5
- /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
- /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
- /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
- /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
- /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
- /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
|
@@ -1,126 +1,418 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Solargraph
|
|
4
|
-
module Pin
|
|
5
|
-
class BaseVariable < Base
|
|
6
|
-
# include Solargraph::Source::NodeMethods
|
|
7
|
-
include Solargraph::Parser::NodeMethods
|
|
8
|
-
|
|
9
|
-
# @return [Parser::AST::Node
|
|
10
|
-
attr_reader :
|
|
11
|
-
|
|
12
|
-
attr_accessor :mass_assignment
|
|
13
|
-
|
|
14
|
-
# @
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# @param other [
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
#
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Pin
|
|
5
|
+
class BaseVariable < Base
|
|
6
|
+
# include Solargraph::Source::NodeMethods
|
|
7
|
+
include Solargraph::Parser::NodeMethods
|
|
8
|
+
|
|
9
|
+
# @return [Array<Parser::AST::Node>]
|
|
10
|
+
attr_reader :assignments
|
|
11
|
+
|
|
12
|
+
attr_accessor :mass_assignment
|
|
13
|
+
|
|
14
|
+
# @return [Range, nil]
|
|
15
|
+
attr_reader :presence
|
|
16
|
+
|
|
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
|
|
22
|
+
# @param mass_assignment [::Array(Parser::AST::Node, Integer), nil]
|
|
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 presence_certain [Boolean]
|
|
49
|
+
def initialize assignment: nil, assignments: [], mass_assignment: nil,
|
|
50
|
+
presence: nil, presence_certain: false, return_type: nil,
|
|
51
|
+
intersection_return_type: nil, exclude_return_type: nil,
|
|
52
|
+
**splat
|
|
53
|
+
super(**splat)
|
|
54
|
+
@assignments = (assignment.nil? ? [] : [assignment]) + assignments
|
|
55
|
+
# @type [nil, ::Array(Parser::AST::Node, Integer)]
|
|
56
|
+
@mass_assignment = mass_assignment
|
|
57
|
+
@return_type = return_type
|
|
58
|
+
@intersection_return_type = intersection_return_type
|
|
59
|
+
@exclude_return_type = exclude_return_type
|
|
60
|
+
@presence = presence
|
|
61
|
+
@presence_certain = presence_certain
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @param presence [Range]
|
|
65
|
+
# @param exclude_return_type [ComplexType, nil]
|
|
66
|
+
# @param intersection_return_type [ComplexType, nil]
|
|
67
|
+
# @param source [::Symbol]
|
|
68
|
+
#
|
|
69
|
+
# @return [self]
|
|
70
|
+
def downcast presence:, exclude_return_type: nil, intersection_return_type: nil,
|
|
71
|
+
source: self.source
|
|
72
|
+
result = dup
|
|
73
|
+
result.exclude_return_type = exclude_return_type
|
|
74
|
+
result.intersection_return_type = intersection_return_type
|
|
75
|
+
result.source = source
|
|
76
|
+
result.presence = presence
|
|
77
|
+
result.reset_generated!
|
|
78
|
+
result
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def reset_generated!
|
|
82
|
+
@assignment = nil
|
|
83
|
+
super
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def combine_with(other, attrs={})
|
|
87
|
+
new_assignments = combine_assignments(other)
|
|
88
|
+
new_attrs = attrs.merge({
|
|
89
|
+
# default values don't exist in RBS parameters; it just
|
|
90
|
+
# tells you if the arg is optional or not. Prefer a
|
|
91
|
+
# provided value if we have one here since we can't rely on
|
|
92
|
+
# it from RBS so we can infer from it and typecheck on it.
|
|
93
|
+
assignment: choose(other, :assignment),
|
|
94
|
+
assignments: new_assignments,
|
|
95
|
+
mass_assignment: combine_mass_assignment(other),
|
|
96
|
+
return_type: combine_return_type(other),
|
|
97
|
+
intersection_return_type: combine_types(other, :intersection_return_type),
|
|
98
|
+
exclude_return_type: combine_types(other, :exclude_return_type),
|
|
99
|
+
presence: combine_presence(other),
|
|
100
|
+
presence_certain: combine_presence_certain(other)
|
|
101
|
+
})
|
|
102
|
+
super(other, new_attrs)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# @param other [self]
|
|
106
|
+
#
|
|
107
|
+
# @return [Array(AST::Node, Integer), nil]
|
|
108
|
+
def combine_mass_assignment(other)
|
|
109
|
+
# @todo pick first non-nil arbitrarily - we don't yet support
|
|
110
|
+
# mass assignment merging
|
|
111
|
+
mass_assignment || other.mass_assignment
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# If a certain pin is being combined with an uncertain pin, we
|
|
115
|
+
# end up with a certain result
|
|
116
|
+
#
|
|
117
|
+
# @param other [self]
|
|
118
|
+
#
|
|
119
|
+
# @return [Boolean]
|
|
120
|
+
def combine_presence_certain(other)
|
|
121
|
+
presence_certain? || other.presence_certain?
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @return [Parser::AST::Node, nil]
|
|
125
|
+
def assignment
|
|
126
|
+
@assignment ||= assignments.last
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# @param other [self]
|
|
130
|
+
#
|
|
131
|
+
# @return [::Array<Parser::AST::Node>]
|
|
132
|
+
def combine_assignments(other)
|
|
133
|
+
(other.assignments + assignments).uniq
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def inner_desc
|
|
137
|
+
super + ", presence=#{presence.inspect}, assignments=#{assignments}, " \
|
|
138
|
+
"intersection_return_type=#{intersection_return_type&.rooted_tags.inspect}, " \
|
|
139
|
+
"exclude_return_type=#{exclude_return_type&.rooted_tags.inspect}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def completion_item_kind
|
|
143
|
+
Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# @return [Integer]
|
|
147
|
+
def symbol_kind
|
|
148
|
+
Solargraph::LanguageServer::SymbolKinds::VARIABLE
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def nil_assignment?
|
|
152
|
+
# this will always be false - should it be return_type ==
|
|
153
|
+
# ComplexType::NIL or somesuch?
|
|
154
|
+
return_type.nil?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def variable?
|
|
158
|
+
true
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# @param parent_node [Parser::AST::Node]
|
|
162
|
+
# @param api_map [ApiMap]
|
|
163
|
+
# @return [::Array<ComplexType>]
|
|
164
|
+
def return_types_from_node(parent_node, api_map)
|
|
165
|
+
types = []
|
|
166
|
+
value_position_nodes_only(parent_node).each do |node|
|
|
167
|
+
# Nil nodes may not have a location
|
|
168
|
+
if node.nil? || node.type == :NIL || node.type == :nil
|
|
169
|
+
types.push ComplexType::NIL
|
|
170
|
+
else
|
|
171
|
+
rng = Range.from_node(node)
|
|
172
|
+
next if rng.nil?
|
|
173
|
+
pos = rng.ending
|
|
174
|
+
# @sg-ignore Need to add nil check here
|
|
175
|
+
clip = api_map.clip_at(location.filename, pos)
|
|
176
|
+
# Use the return node for inference. The clip might infer from the
|
|
177
|
+
# first node in a method call instead of the entire call.
|
|
178
|
+
chain = Parser.chain(node, nil, nil)
|
|
179
|
+
# @sg-ignore Need to add nil check here
|
|
180
|
+
result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
|
|
181
|
+
types.push result unless result.undefined?
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
types
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# @param api_map [ApiMap]
|
|
188
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
189
|
+
def probe api_map
|
|
190
|
+
assignment_types = assignments.flat_map { |node| return_types_from_node(node, api_map) }
|
|
191
|
+
type_from_assignment = ComplexType.new(assignment_types.flat_map(&:items).uniq) unless assignment_types.empty?
|
|
192
|
+
return adjust_type api_map, type_from_assignment unless type_from_assignment.nil?
|
|
193
|
+
|
|
194
|
+
# @todo should handle merging types from mass assignments as
|
|
195
|
+
# well so that we can do better flow sensitive typing with
|
|
196
|
+
# multiple assignments
|
|
197
|
+
unless @mass_assignment.nil?
|
|
198
|
+
mass_node, index = @mass_assignment
|
|
199
|
+
types = return_types_from_node(mass_node, api_map)
|
|
200
|
+
types.map! do |type|
|
|
201
|
+
if type.tuple?
|
|
202
|
+
type.all_params[index]
|
|
203
|
+
elsif ['::Array', '::Set', '::Enumerable'].include?(type.rooted_name)
|
|
204
|
+
type.all_params.first
|
|
205
|
+
end
|
|
206
|
+
end.compact!
|
|
207
|
+
|
|
208
|
+
return ComplexType::UNDEFINED if types.empty?
|
|
209
|
+
|
|
210
|
+
return adjust_type api_map, ComplexType.new(types.uniq).qualify(api_map, *gates)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
ComplexType::UNDEFINED
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# @param other [Object]
|
|
217
|
+
def == other
|
|
218
|
+
return false unless super
|
|
219
|
+
# @sg-ignore Should add type check on other
|
|
220
|
+
assignment == other.assignment
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def type_desc
|
|
224
|
+
"#{super} = #{assignment&.type.inspect}"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# @return [ComplexType, nil]
|
|
228
|
+
def return_type
|
|
229
|
+
generate_complex_type || @return_type || intersection_return_type || ComplexType::UNDEFINED
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def typify api_map
|
|
233
|
+
raw_return_type = super
|
|
234
|
+
|
|
235
|
+
adjust_type(api_map, raw_return_type)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# @sg-ignore need boolish support for ? methods
|
|
239
|
+
def presence_certain?
|
|
240
|
+
exclude_return_type || intersection_return_type
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# @param other_loc [Location]
|
|
244
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
245
|
+
def starts_at?(other_loc)
|
|
246
|
+
location&.filename == other_loc.filename &&
|
|
247
|
+
presence &&
|
|
248
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
249
|
+
presence.start == other_loc.range.start
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Narrow the presence range to the intersection of both.
|
|
253
|
+
#
|
|
254
|
+
# @param other [self]
|
|
255
|
+
#
|
|
256
|
+
# @return [Range, nil]
|
|
257
|
+
def combine_presence(other)
|
|
258
|
+
return presence || other.presence if presence.nil? || other.presence.nil?
|
|
259
|
+
|
|
260
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
261
|
+
Range.new([presence.start, other.presence.start].max, [presence.ending, other.presence.ending].min)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
# @param other [self]
|
|
265
|
+
# @return [Pin::Closure, nil]
|
|
266
|
+
def combine_closure(other)
|
|
267
|
+
return closure if self.closure == other.closure
|
|
268
|
+
|
|
269
|
+
# choose first defined, as that establishes the scope of the variable
|
|
270
|
+
if closure.nil? || other.closure.nil?
|
|
271
|
+
Solargraph.assert_or_log(:varible_closure_missing) do
|
|
272
|
+
"One of the local variables being combined is missing a closure: " \
|
|
273
|
+
"#{self.inspect} vs #{other.inspect}"
|
|
274
|
+
end
|
|
275
|
+
return closure || other.closure
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
279
|
+
if closure.location.nil? || other.closure.location.nil?
|
|
280
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
281
|
+
return closure.location.nil? ? other.closure : closure
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# if filenames are different, this will just pick one
|
|
285
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
286
|
+
return closure if closure.location <= other.closure.location
|
|
287
|
+
|
|
288
|
+
other.closure
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# @param other_closure [Pin::Closure]
|
|
292
|
+
# @param other_loc [Location]
|
|
293
|
+
def visible_at?(other_closure, other_loc)
|
|
294
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
295
|
+
location.filename == other_loc.filename &&
|
|
296
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
297
|
+
(!presence || presence.include?(other_loc.range.start)) &&
|
|
298
|
+
visible_in_closure?(other_closure)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def presence_certain?
|
|
302
|
+
@presence_certain
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
protected
|
|
306
|
+
|
|
307
|
+
attr_accessor :exclude_return_type, :intersection_return_type
|
|
308
|
+
|
|
309
|
+
# @return [Range]
|
|
310
|
+
attr_writer :presence
|
|
311
|
+
|
|
312
|
+
private
|
|
313
|
+
|
|
314
|
+
# @param api_map [ApiMap]
|
|
315
|
+
# @param raw_return_type [ComplexType, ComplexType::UniqueType]
|
|
316
|
+
#
|
|
317
|
+
# @return [ComplexType, ComplexType::UniqueType]
|
|
318
|
+
def adjust_type(api_map, raw_return_type)
|
|
319
|
+
qualified_exclude = exclude_return_type&.qualify(api_map, *(closure&.gates || ['']))
|
|
320
|
+
minus_exclusions = raw_return_type.exclude qualified_exclude, api_map
|
|
321
|
+
qualified_intersection = intersection_return_type&.qualify(api_map, *(closure&.gates || ['']))
|
|
322
|
+
minus_exclusions.intersect_with qualified_intersection, api_map
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# @param other [self]
|
|
326
|
+
# @return [Pin::Closure, nil]
|
|
327
|
+
def combine_closure(other)
|
|
328
|
+
return closure if self.closure == other.closure
|
|
329
|
+
|
|
330
|
+
# choose first defined, as that establishes the scope of the variable
|
|
331
|
+
if closure.nil? || other.closure.nil?
|
|
332
|
+
Solargraph.assert_or_log(:varible_closure_missing) do
|
|
333
|
+
"One of the local variables being combined is missing a closure: " \
|
|
334
|
+
"#{self.inspect} vs #{other.inspect}"
|
|
335
|
+
end
|
|
336
|
+
return closure || other.closure
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# @sg-ignore Need to add nil check here
|
|
340
|
+
if closure.location.nil? || other.closure.location.nil?
|
|
341
|
+
# @sg-ignore Need to add nil check here
|
|
342
|
+
return closure.location.nil? ? other.closure : closure
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# if filenames are different, this will just pick one
|
|
346
|
+
# @sg-ignore flow sensitive typing needs to handle attrs
|
|
347
|
+
return closure if closure.location <= other.closure.location
|
|
348
|
+
|
|
349
|
+
other.closure
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# See if this variable is visible within 'viewing_closure'
|
|
353
|
+
#
|
|
354
|
+
# @param viewing_closure [Pin::Closure]
|
|
355
|
+
# @return [Boolean]
|
|
356
|
+
def visible_in_closure? viewing_closure
|
|
357
|
+
return false if closure.nil?
|
|
358
|
+
|
|
359
|
+
# if we're declared at top level, we can't be seen from within
|
|
360
|
+
# methods declared tere
|
|
361
|
+
|
|
362
|
+
# @sg-ignore Need to add nil check here
|
|
363
|
+
return false if viewing_closure.is_a?(Pin::Method) && closure.context.tags == 'Class<>'
|
|
364
|
+
|
|
365
|
+
# @sg-ignore Need to add nil check here
|
|
366
|
+
return true if viewing_closure.binder.namespace == closure.binder.namespace
|
|
367
|
+
|
|
368
|
+
# @sg-ignore Need to add nil check here
|
|
369
|
+
return true if viewing_closure.return_type == closure.context
|
|
370
|
+
|
|
371
|
+
# classes and modules can't see local variables declared
|
|
372
|
+
# in their parent closure, so stop here
|
|
373
|
+
return false if scope == :instance && viewing_closure.is_a?(Pin::Namespace)
|
|
374
|
+
|
|
375
|
+
parent_of_viewing_closure = viewing_closure.closure
|
|
376
|
+
|
|
377
|
+
return false if parent_of_viewing_closure.nil?
|
|
378
|
+
|
|
379
|
+
visible_in_closure?(parent_of_viewing_closure)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# @param other [self]
|
|
383
|
+
# @return [ComplexType, nil]
|
|
384
|
+
def combine_return_type(other)
|
|
385
|
+
combine_types(other, :return_type)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# @param other [self]
|
|
389
|
+
# @param attr [::Symbol]
|
|
390
|
+
#
|
|
391
|
+
# @return [ComplexType, nil]
|
|
392
|
+
def combine_types(other, attr)
|
|
393
|
+
# @type [ComplexType, nil]
|
|
394
|
+
type1 = send(attr)
|
|
395
|
+
# @type [ComplexType, nil]
|
|
396
|
+
type2 = other.send(attr)
|
|
397
|
+
if type1 && type2
|
|
398
|
+
types = (type1.items + type2.items).uniq
|
|
399
|
+
ComplexType.new(types)
|
|
400
|
+
else
|
|
401
|
+
type1 || type2
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# @return [::Symbol]
|
|
406
|
+
def scope
|
|
407
|
+
:instance
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# @return [ComplexType, nil]
|
|
411
|
+
def generate_complex_type
|
|
412
|
+
tag = docstring.tag(:type)
|
|
413
|
+
return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
|
|
414
|
+
nil
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
end
|