solargraph 0.58.3 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.envrc +3 -0
- data/.github/workflows/linting.yml +6 -5
- data/.github/workflows/plugins.yml +46 -34
- data/.github/workflows/rspec.yml +15 -28
- data/.github/workflows/typecheck.yml +3 -2
- data/.rubocop.yml +38 -6
- data/.rubocop_todo.yml +53 -966
- data/CHANGELOG.md +12 -0
- data/Gemfile +3 -1
- data/README.md +3 -3
- data/Rakefile +26 -23
- data/bin/solargraph +2 -1
- data/lib/solargraph/api_map/cache.rb +3 -3
- data/lib/solargraph/api_map/constants.rb +12 -3
- data/lib/solargraph/api_map/index.rb +29 -18
- data/lib/solargraph/api_map/source_to_yard.rb +22 -9
- data/lib/solargraph/api_map/store.rb +39 -28
- data/lib/solargraph/api_map.rb +156 -72
- data/lib/solargraph/bench.rb +2 -3
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +30 -18
- data/lib/solargraph/complex_type/unique_type.rb +216 -57
- data/lib/solargraph/complex_type.rb +171 -58
- 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/doc_map.rb +38 -39
- data/lib/solargraph/equality.rb +4 -4
- data/lib/solargraph/gem_pins.rb +6 -6
- 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 +30 -22
- 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/search.rb +1 -1
- data/lib/solargraph/language_server/message/initialize.rb +20 -14
- 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/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/request.rb +4 -2
- data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
- data/lib/solargraph/language_server/uri_helpers.rb +2 -2
- data/lib/solargraph/library.rb +57 -38
- data/lib/solargraph/location.rb +17 -14
- data/lib/solargraph/logging.rb +22 -4
- data/lib/solargraph/page.rb +1 -1
- data/lib/solargraph/parser/comment_ripper.rb +19 -4
- data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
- data/lib/solargraph/parser/node_processor/base.rb +34 -4
- data/lib/solargraph/parser/node_processor.rb +8 -7
- data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +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 +11 -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 +9 -8
- 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 +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 +124 -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 +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 +156 -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/type_alias.rb +16 -0
- data/lib/solargraph/pin/reference.rb +20 -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 +22 -19
- data/lib/solargraph/position.rb +17 -10
- data/lib/solargraph/range.rb +16 -15
- data/lib/solargraph/rbs_map/conversions.rb +358 -229
- data/lib/solargraph/rbs_map/core_fills.rb +18 -11
- data/lib/solargraph/rbs_map/core_map.rb +24 -17
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
- data/lib/solargraph/rbs_map.rb +76 -32
- data/lib/solargraph/server_methods.rb +1 -1
- data/lib/solargraph/shell.rb +258 -66
- data/lib/solargraph/source/chain/array.rb +4 -2
- data/lib/solargraph/source/chain/call.rb +96 -56
- data/lib/solargraph/source/chain/class_variable.rb +1 -1
- data/lib/solargraph/source/chain/constant.rb +5 -1
- data/lib/solargraph/source/chain/global_variable.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +8 -5
- data/lib/solargraph/source/chain/if.rb +12 -10
- data/lib/solargraph/source/chain/instance_variable.rb +24 -1
- data/lib/solargraph/source/chain/link.rb +12 -22
- data/lib/solargraph/source/chain/literal.rb +9 -6
- data/lib/solargraph/source/chain/or.rb +10 -4
- data/lib/solargraph/source/chain/q_call.rb +2 -0
- data/lib/solargraph/source/chain/variable.rb +3 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -3
- data/lib/solargraph/source/chain.rb +51 -38
- data/lib/solargraph/source/change.rb +12 -5
- data/lib/solargraph/source/cursor.rb +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 +69 -42
- data/lib/solargraph/source_map.rb +21 -9
- data/lib/solargraph/type_checker/problem.rb +3 -1
- data/lib/solargraph/type_checker/rules.rb +81 -8
- data/lib/solargraph/type_checker.rb +195 -121
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace/gemspecs.rb +367 -0
- data/lib/solargraph/workspace/require_paths.rb +1 -0
- data/lib/solargraph/workspace.rb +50 -28
- data/lib/solargraph/yard_map/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_map.rb +17 -18
- data/lib/solargraph/yard_tags.rb +2 -2
- data/lib/solargraph/yardoc.rb +7 -4
- data/lib/solargraph.rb +31 -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 +37 -35
- metadata +41 -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
|
@@ -11,11 +11,6 @@ module Solargraph
|
|
|
11
11
|
|
|
12
12
|
attr_reader :all_params, :subtypes, :key_types
|
|
13
13
|
|
|
14
|
-
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
|
15
|
-
protected def equality_fields
|
|
16
|
-
[@name, @all_params, @subtypes, @key_types]
|
|
17
|
-
end
|
|
18
|
-
|
|
19
14
|
# Create a UniqueType with the specified name and an optional substring.
|
|
20
15
|
# The substring is the parameter section of a parametrized type, e.g.,
|
|
21
16
|
# for the type `Array<String>`, the name is `Array` and the substring is
|
|
@@ -26,11 +21,9 @@ module Solargraph
|
|
|
26
21
|
# @param make_rooted [Boolean, nil]
|
|
27
22
|
# @return [UniqueType]
|
|
28
23
|
def self.parse name, substring = '', make_rooted: nil
|
|
29
|
-
if name.start_with?(':::')
|
|
30
|
-
raise ComplexTypeError, "Illegal prefix: #{name}"
|
|
31
|
-
end
|
|
24
|
+
raise ComplexTypeError, "Illegal prefix: #{name}" if name.start_with?(':::')
|
|
32
25
|
if name.start_with?('::')
|
|
33
|
-
name = name[2
|
|
26
|
+
name = name[2..]
|
|
34
27
|
rooted = true
|
|
35
28
|
elsif !can_root_name?(name)
|
|
36
29
|
rooted = true
|
|
@@ -46,15 +39,20 @@ module Solargraph
|
|
|
46
39
|
parameters_type = nil
|
|
47
40
|
unless substring.empty?
|
|
48
41
|
subs = ComplexType.parse(substring[1..-2], partial: true)
|
|
42
|
+
# @sg-ignore Need to add nil check here
|
|
49
43
|
parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
|
|
50
44
|
if parameters_type == :hash
|
|
51
|
-
|
|
45
|
+
unless !subs.is_a?(ComplexType) && (subs.length == 2) && !subs[0].is_a?(UniqueType) && !subs[1].is_a?(UniqueType)
|
|
46
|
+
raise ComplexTypeError,
|
|
47
|
+
"Bad hash type: name=#{name}, substring=#{substring}"
|
|
48
|
+
end
|
|
52
49
|
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
|
53
50
|
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
|
54
51
|
elsif parameters_type == :list && name == 'Hash'
|
|
55
52
|
# Treat Hash<A, B> as Hash{A => B}
|
|
56
53
|
if subs.length != 2
|
|
57
|
-
raise ComplexTypeError,
|
|
54
|
+
raise ComplexTypeError,
|
|
55
|
+
"Bad hash type: name=#{name}, substring=#{substring} - must have exactly two parameters"
|
|
58
56
|
end
|
|
59
57
|
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
|
60
58
|
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
|
@@ -62,6 +60,7 @@ module Solargraph
|
|
|
62
60
|
subtypes.concat subs
|
|
63
61
|
end
|
|
64
62
|
end
|
|
63
|
+
# @sg-ignore Need to add nil check here
|
|
65
64
|
new(name, key_types, subtypes, rooted: rooted, parameters_type: parameters_type)
|
|
66
65
|
end
|
|
67
66
|
|
|
@@ -70,9 +69,9 @@ module Solargraph
|
|
|
70
69
|
# @param subtypes [Array<ComplexType>]
|
|
71
70
|
# @param rooted [Boolean]
|
|
72
71
|
# @param parameters_type [Symbol, nil]
|
|
73
|
-
def initialize
|
|
74
|
-
if parameters_type.nil?
|
|
75
|
-
raise
|
|
72
|
+
def initialize name, key_types = [], subtypes = [], rooted:, parameters_type: nil
|
|
73
|
+
if parameters_type.nil? && !(key_types.empty? && subtypes.empty?)
|
|
74
|
+
raise 'You must supply parameters_type if you provide parameters'
|
|
76
75
|
end
|
|
77
76
|
raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
|
|
78
77
|
@name = name
|
|
@@ -94,7 +93,7 @@ module Solargraph
|
|
|
94
93
|
# @todo use api_map to establish number of generics in type;
|
|
95
94
|
# if only one is allowed but multiple are passed in, treat
|
|
96
95
|
# those as implicit unions
|
|
97
|
-
[
|
|
96
|
+
%w[Hash Array Set _ToAry Enumerable _Each].include?(name) && parameters_type != :fixed
|
|
98
97
|
end
|
|
99
98
|
|
|
100
99
|
def to_s
|
|
@@ -109,6 +108,44 @@ module Solargraph
|
|
|
109
108
|
end
|
|
110
109
|
end
|
|
111
110
|
|
|
111
|
+
# @param exclude_types [ComplexType, nil]
|
|
112
|
+
# @param api_map [ApiMap]
|
|
113
|
+
# @return [ComplexType, self]
|
|
114
|
+
def exclude exclude_types, api_map
|
|
115
|
+
return self if exclude_types.nil?
|
|
116
|
+
|
|
117
|
+
types = items - exclude_types.items
|
|
118
|
+
types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
|
|
119
|
+
ComplexType.new(types)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @see https://en.wikipedia.org/wiki/Intersection_type
|
|
123
|
+
#
|
|
124
|
+
# @param intersection_type [ComplexType, ComplexType::UniqueType, nil]
|
|
125
|
+
# @param api_map [ApiMap]
|
|
126
|
+
# @return [self, ComplexType]
|
|
127
|
+
def intersect_with intersection_type, api_map
|
|
128
|
+
return self if intersection_type.nil?
|
|
129
|
+
return intersection_type if undefined?
|
|
130
|
+
types = []
|
|
131
|
+
# try to find common types via conformance
|
|
132
|
+
items.each do |ut|
|
|
133
|
+
intersection_type.each do |int_type|
|
|
134
|
+
if ut.conforms_to?(api_map, int_type, :assignment)
|
|
135
|
+
types << ut
|
|
136
|
+
elsif int_type.conforms_to?(api_map, ut, :assignment)
|
|
137
|
+
types << int_type
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
|
|
142
|
+
ComplexType.new(types)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def simplifyable_literal?
|
|
146
|
+
literal? && name != 'nil'
|
|
147
|
+
end
|
|
148
|
+
|
|
112
149
|
def literal?
|
|
113
150
|
non_literal_name != name
|
|
114
151
|
end
|
|
@@ -118,6 +155,13 @@ module Solargraph
|
|
|
118
155
|
@non_literal_name ||= determine_non_literal_name
|
|
119
156
|
end
|
|
120
157
|
|
|
158
|
+
# @return [self]
|
|
159
|
+
def without_nil
|
|
160
|
+
return UniqueType::UNDEFINED if nil_type?
|
|
161
|
+
|
|
162
|
+
self
|
|
163
|
+
end
|
|
164
|
+
|
|
121
165
|
# @return [String]
|
|
122
166
|
def determine_non_literal_name
|
|
123
167
|
# https://github.com/ruby/rbs/blob/master/docs/syntax.md
|
|
@@ -129,37 +173,113 @@ module Solargraph
|
|
|
129
173
|
# | `false`
|
|
130
174
|
return name if name.empty?
|
|
131
175
|
return 'NilClass' if name == 'nil'
|
|
132
|
-
return 'Boolean' if [
|
|
176
|
+
return 'Boolean' if %w[true false].include?(name)
|
|
133
177
|
return 'Symbol' if name[0] == ':'
|
|
134
178
|
return 'String' if ['"', "'"].include?(name[0])
|
|
135
179
|
return 'Integer' if name.match?(/^-?\d+$/)
|
|
136
180
|
name
|
|
137
181
|
end
|
|
138
182
|
|
|
139
|
-
def eql?
|
|
183
|
+
def eql? other
|
|
140
184
|
self.class == other.class &&
|
|
141
|
-
# @sg-ignore
|
|
185
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
142
186
|
@name == other.name &&
|
|
143
|
-
# @sg-ignore
|
|
187
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
144
188
|
@key_types == other.key_types &&
|
|
145
|
-
# @sg-ignore
|
|
189
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
146
190
|
@subtypes == other.subtypes &&
|
|
147
|
-
# @sg-ignore
|
|
191
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
148
192
|
@rooted == other.rooted? &&
|
|
149
|
-
# @sg-ignore
|
|
193
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
150
194
|
@all_params == other.all_params &&
|
|
151
|
-
# @sg-ignore
|
|
195
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
152
196
|
@parameters_type == other.parameters_type
|
|
153
197
|
end
|
|
154
198
|
|
|
155
|
-
def ==
|
|
199
|
+
def == other
|
|
156
200
|
eql?(other)
|
|
157
201
|
end
|
|
158
202
|
|
|
203
|
+
# https://www.playfulpython.com/type-hinting-covariance-contra-variance/
|
|
204
|
+
|
|
205
|
+
# "[Expected] type variables that are COVARIANT can be substituted with
|
|
206
|
+
# a more specific [inferred] type without causing errors"
|
|
207
|
+
#
|
|
208
|
+
# "[Expected] type variables that are CONTRAVARIANT can be substituted
|
|
209
|
+
# with a more general [inferred] type without causing errors"
|
|
210
|
+
#
|
|
211
|
+
# "[Expected] types where neither is possible are INVARIANT"
|
|
212
|
+
#
|
|
213
|
+
# @param _situation [:method_call, :return_type]
|
|
214
|
+
# @param default [Symbol] The default variance to return if the type is not one of the special cases
|
|
215
|
+
#
|
|
216
|
+
# @return [:invariant, :covariant, :contravariant]
|
|
217
|
+
def parameter_variance _situation, default = :covariant
|
|
218
|
+
# @todo RBS can specify variance - maybe we can use that info
|
|
219
|
+
# and also let folks specify?
|
|
220
|
+
#
|
|
221
|
+
# Array/Set: ideally invariant, since we don't know if user is
|
|
222
|
+
# going to add new stuff into it or read it. But we don't
|
|
223
|
+
# have a way to specify, so we use covariant
|
|
224
|
+
# Enumerable: covariant: can't be changed, so we can pass
|
|
225
|
+
# in more specific subtypes
|
|
226
|
+
# Hash: read-only would be covariant, read-write would be
|
|
227
|
+
# invariant if we could distinguish that - should default to
|
|
228
|
+
# covariant
|
|
229
|
+
# contravariant?: Proc - can be changed, so we can pass
|
|
230
|
+
# in less specific super types
|
|
231
|
+
if %w[Hash Tuple Array Set Enumerable].include?(name) && fixed_parameters?
|
|
232
|
+
:covariant
|
|
233
|
+
else
|
|
234
|
+
default
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# Whether this is an RBS interface like _ToAry or Hash::_Key.
|
|
239
|
+
def interface?
|
|
240
|
+
name.start_with?('_') || name.include?('::_')
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# @param other [UniqueType]
|
|
244
|
+
def erased_version_of? other
|
|
245
|
+
name == other.name && (all_params.empty? || all_params.all?(&:undefined?))
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# @param api_map [ApiMap]
|
|
249
|
+
# @param expected [ComplexType::UniqueType, ComplexType]
|
|
250
|
+
# @param situation [:method_call, :assignment, :return_type]
|
|
251
|
+
# @param rules [Array<:allow_subtype_skew, :allow_empty_params, :allow_reverse_match, :allow_any_match, :allow_undefined, :allow_unresolved_generic>]
|
|
252
|
+
# @param variance [:invariant, :covariant, :contravariant]
|
|
253
|
+
def conforms_to? api_map, expected, situation, rules = [],
|
|
254
|
+
variance: erased_variance(situation)
|
|
255
|
+
return true if undefined? && rules.include?(:allow_undefined)
|
|
256
|
+
|
|
257
|
+
# @todo teach this to validate duck types as inferred type
|
|
258
|
+
return true if duck_type?
|
|
259
|
+
|
|
260
|
+
# complex types as expectations are unions - we only need to
|
|
261
|
+
# match one of their unique types
|
|
262
|
+
expected.any? do |expected_unique_type|
|
|
263
|
+
# :nocov:
|
|
264
|
+
unless expected_unique_type.instance_of?(UniqueType)
|
|
265
|
+
raise "Expected type must be a UniqueType, got #{expected_unique_type.class} in #{expected.inspect}"
|
|
266
|
+
end
|
|
267
|
+
# :nocov:
|
|
268
|
+
conformance = Conformance.new(api_map, self, expected_unique_type, situation,
|
|
269
|
+
rules, variance: variance)
|
|
270
|
+
conformance.conforms_to_unique_type?
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
159
274
|
def hash
|
|
160
275
|
[self.class, @name, @key_types, @sub_types, @rooted, @all_params, @parameters_type].hash
|
|
161
276
|
end
|
|
162
277
|
|
|
278
|
+
# @return [self]
|
|
279
|
+
def erase_parameters
|
|
280
|
+
UniqueType.new(name, rooted: rooted?, parameters_type: parameters_type)
|
|
281
|
+
end
|
|
282
|
+
|
|
163
283
|
# @return [Array<UniqueType>]
|
|
164
284
|
def items
|
|
165
285
|
[self]
|
|
@@ -181,6 +301,7 @@ module Solargraph
|
|
|
181
301
|
rooted_tags
|
|
182
302
|
end
|
|
183
303
|
|
|
304
|
+
# @sg-ignore Need better if/elseanalysis
|
|
184
305
|
# @return [String]
|
|
185
306
|
def to_rbs
|
|
186
307
|
if duck_type?
|
|
@@ -190,10 +311,10 @@ module Solargraph
|
|
|
190
311
|
elsif name.downcase == 'nil'
|
|
191
312
|
'nil'
|
|
192
313
|
elsif name == GENERIC_TAG_NAME
|
|
193
|
-
all_params.first
|
|
194
|
-
elsif [
|
|
314
|
+
all_params.first&.name
|
|
315
|
+
elsif %w[Class Module].include?(name)
|
|
195
316
|
rbs_name
|
|
196
|
-
elsif [
|
|
317
|
+
elsif %w[Tuple Array].include?(name) && fixed_parameters?
|
|
197
318
|
# tuples don't have a name; they're just [foo, bar, baz].
|
|
198
319
|
if substring == '()'
|
|
199
320
|
# but there are no zero element tuples, so we go with an array
|
|
@@ -218,7 +339,7 @@ module Solargraph
|
|
|
218
339
|
|
|
219
340
|
# @param types [Array<UniqueType, ComplexType>]
|
|
220
341
|
# @return [String]
|
|
221
|
-
def rbs_union
|
|
342
|
+
def rbs_union types
|
|
222
343
|
if types.length == 1
|
|
223
344
|
types.first.to_rbs
|
|
224
345
|
else
|
|
@@ -242,16 +363,13 @@ module Solargraph
|
|
|
242
363
|
name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
|
|
243
364
|
end
|
|
244
365
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
end
|
|
253
|
-
logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect}) => #{out}" }
|
|
254
|
-
out
|
|
366
|
+
def nullable?
|
|
367
|
+
nil_type?
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# @yieldreturn [Boolean]
|
|
371
|
+
def all? &block
|
|
372
|
+
block.yield self
|
|
255
373
|
end
|
|
256
374
|
|
|
257
375
|
# @return [UniqueType]
|
|
@@ -260,37 +378,43 @@ module Solargraph
|
|
|
260
378
|
end
|
|
261
379
|
|
|
262
380
|
# @param generics_to_resolve [Enumerable<String>]
|
|
263
|
-
# @param context_type [UniqueType, nil]
|
|
381
|
+
# @param context_type [ComplexType, UniqueType, nil]
|
|
264
382
|
# @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
|
|
265
383
|
# @return [UniqueType, ComplexType]
|
|
266
384
|
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
|
267
385
|
if name == ComplexType::GENERIC_TAG_NAME
|
|
268
386
|
type_param = subtypes.first&.name
|
|
269
387
|
return self unless generics_to_resolve.include? type_param
|
|
388
|
+
# @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
270
389
|
unless context_type.nil? || !resolved_generic_values[type_param].nil?
|
|
271
390
|
new_binding = true
|
|
391
|
+
# @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
272
392
|
resolved_generic_values[type_param] = context_type
|
|
273
393
|
end
|
|
274
394
|
if new_binding
|
|
275
395
|
resolved_generic_values.transform_values! do |complex_type|
|
|
276
|
-
complex_type.resolve_generics_from_context(generics_to_resolve, nil,
|
|
396
|
+
complex_type.resolve_generics_from_context(generics_to_resolve, nil,
|
|
397
|
+
resolved_generic_values: resolved_generic_values)
|
|
277
398
|
end
|
|
278
399
|
end
|
|
400
|
+
# @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
279
401
|
return resolved_generic_values[type_param] || self
|
|
280
402
|
end
|
|
281
403
|
|
|
282
404
|
# @todo typechecking should complain when the method being called has no @yieldparam tag
|
|
283
|
-
new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values,
|
|
284
|
-
|
|
405
|
+
new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values,
|
|
406
|
+
&:key_types)
|
|
407
|
+
new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values,
|
|
408
|
+
&:subtypes)
|
|
285
409
|
recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
|
|
286
410
|
end
|
|
287
411
|
|
|
288
412
|
# @param generics_to_resolve [Enumerable<String>]
|
|
289
|
-
# @param context_type [UniqueType, nil]
|
|
413
|
+
# @param context_type [UniqueType, ComplexType, nil]
|
|
290
414
|
# @param resolved_generic_values [Hash{String => ComplexType}]
|
|
291
415
|
# @yieldreturn [Array<ComplexType>]
|
|
292
416
|
# @return [Array<ComplexType>]
|
|
293
|
-
def resolve_param_generics_from_context
|
|
417
|
+
def resolve_param_generics_from_context generics_to_resolve, context_type, resolved_generic_values
|
|
294
418
|
types = yield self
|
|
295
419
|
types.each_with_index.flat_map do |ct, i|
|
|
296
420
|
ct.items.flat_map do |ut|
|
|
@@ -298,10 +422,12 @@ module Solargraph
|
|
|
298
422
|
if context_params && context_params[i]
|
|
299
423
|
type_arg = context_params[i]
|
|
300
424
|
type_arg.map do |new_unique_context_type|
|
|
301
|
-
ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type,
|
|
425
|
+
ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type,
|
|
426
|
+
resolved_generic_values: resolved_generic_values
|
|
302
427
|
end
|
|
303
428
|
else
|
|
304
|
-
ut.resolve_generics_from_context generics_to_resolve, nil,
|
|
429
|
+
ut.resolve_generics_from_context generics_to_resolve, nil,
|
|
430
|
+
resolved_generic_values: resolved_generic_values
|
|
305
431
|
end
|
|
306
432
|
end
|
|
307
433
|
end
|
|
@@ -323,7 +449,7 @@ module Solargraph
|
|
|
323
449
|
idx = definitions.generics.index(generic_name)
|
|
324
450
|
next t if idx.nil?
|
|
325
451
|
if context_type.parameters_type == :hash
|
|
326
|
-
if idx
|
|
452
|
+
if idx.zero?
|
|
327
453
|
next ComplexType.new(context_type.key_types)
|
|
328
454
|
elsif idx == 1
|
|
329
455
|
next ComplexType.new(context_type.subtypes)
|
|
@@ -331,12 +457,13 @@ module Solargraph
|
|
|
331
457
|
next ComplexType::UNDEFINED
|
|
332
458
|
end
|
|
333
459
|
elsif context_type.all?(&:implicit_union?)
|
|
334
|
-
if idx
|
|
460
|
+
if idx.zero? && !context_type.all_params.empty?
|
|
335
461
|
ComplexType.new(context_type.all_params)
|
|
336
462
|
else
|
|
337
463
|
ComplexType::UNDEFINED
|
|
338
464
|
end
|
|
339
465
|
else
|
|
466
|
+
# @sg-ignore Need to add nil check here
|
|
340
467
|
context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
|
|
341
468
|
end
|
|
342
469
|
else
|
|
@@ -352,6 +479,13 @@ module Solargraph
|
|
|
352
479
|
[block.yield(self)]
|
|
353
480
|
end
|
|
354
481
|
|
|
482
|
+
# @yieldparam t [self]
|
|
483
|
+
# @yieldreturn [self]
|
|
484
|
+
# @return [Enumerable<self>]
|
|
485
|
+
def each &block
|
|
486
|
+
[self].each(&block)
|
|
487
|
+
end
|
|
488
|
+
|
|
355
489
|
# @return [Array<UniqueType>]
|
|
356
490
|
def to_a
|
|
357
491
|
[self]
|
|
@@ -360,16 +494,17 @@ module Solargraph
|
|
|
360
494
|
# @param new_name [String, nil]
|
|
361
495
|
# @param make_rooted [Boolean, nil]
|
|
362
496
|
# @param new_key_types [Array<ComplexType>, nil]
|
|
363
|
-
# @param
|
|
497
|
+
# @param make_rooted [Boolean, nil]
|
|
364
498
|
# @param new_subtypes [Array<ComplexType>, nil]
|
|
365
499
|
# @return [self]
|
|
366
|
-
def recreate
|
|
500
|
+
def recreate new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil
|
|
367
501
|
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
|
368
502
|
|
|
369
503
|
new_name ||= name
|
|
370
504
|
new_key_types ||= @key_types
|
|
371
505
|
new_subtypes ||= @subtypes
|
|
372
506
|
make_rooted = @rooted if make_rooted.nil?
|
|
507
|
+
# @sg-ignore flow sensitive typing needs better handling of ||= on lvars
|
|
373
508
|
UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
|
|
374
509
|
end
|
|
375
510
|
|
|
@@ -396,8 +531,10 @@ module Solargraph
|
|
|
396
531
|
# @yieldparam t [UniqueType]
|
|
397
532
|
# @yieldreturn [self]
|
|
398
533
|
# @return [self]
|
|
399
|
-
def transform
|
|
400
|
-
|
|
534
|
+
def transform new_name = nil, &transform_type
|
|
535
|
+
if new_name&.start_with?('::')
|
|
536
|
+
raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}"
|
|
537
|
+
end
|
|
401
538
|
if name == ComplexType::GENERIC_TAG_NAME
|
|
402
539
|
# doesn't make sense to manipulate the name of the generic
|
|
403
540
|
new_key_types = @key_types
|
|
@@ -406,14 +543,15 @@ module Solargraph
|
|
|
406
543
|
new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
|
407
544
|
new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
|
408
545
|
end
|
|
409
|
-
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
|
|
546
|
+
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
|
|
547
|
+
make_rooted: @rooted)
|
|
410
548
|
yield new_type
|
|
411
549
|
end
|
|
412
550
|
|
|
413
551
|
# Generate a ComplexType that fully qualifies this type's namespaces.
|
|
414
552
|
#
|
|
415
553
|
# @param api_map [ApiMap] The ApiMap that performs qualification
|
|
416
|
-
# @param
|
|
554
|
+
# @param gates [Array<String>] The namespaces from which to resolve names
|
|
417
555
|
# @return [self, ComplexType, UniqueType] The generated ComplexType
|
|
418
556
|
def qualify api_map, *gates
|
|
419
557
|
transform do |t|
|
|
@@ -443,6 +581,22 @@ module Solargraph
|
|
|
443
581
|
end
|
|
444
582
|
end
|
|
445
583
|
|
|
584
|
+
# @yieldreturn [Boolean]
|
|
585
|
+
def any? &block
|
|
586
|
+
block.yield self
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
# @return [ComplexType]
|
|
590
|
+
def reduce_class_type
|
|
591
|
+
new_items = items.flat_map do |type|
|
|
592
|
+
next type unless %w[Module Class].include?(type.name)
|
|
593
|
+
next type if type.all_params.empty?
|
|
594
|
+
|
|
595
|
+
type.all_params
|
|
596
|
+
end
|
|
597
|
+
ComplexType.new(new_items)
|
|
598
|
+
end
|
|
599
|
+
|
|
446
600
|
def all_rooted?
|
|
447
601
|
return true if name == GENERIC_TAG_NAME
|
|
448
602
|
rooted? && all_params.all?(&:rooted?)
|
|
@@ -453,12 +607,12 @@ module Solargraph
|
|
|
453
607
|
end
|
|
454
608
|
|
|
455
609
|
# @param name_to_check [String]
|
|
456
|
-
def can_root_name?
|
|
610
|
+
def can_root_name? name_to_check = name
|
|
457
611
|
self.class.can_root_name?(name_to_check)
|
|
458
612
|
end
|
|
459
613
|
|
|
460
614
|
# @param name [String]
|
|
461
|
-
def self.can_root_name?
|
|
615
|
+
def self.can_root_name? name
|
|
462
616
|
# name is not lowercase
|
|
463
617
|
!name.empty? && name != name.downcase
|
|
464
618
|
end
|
|
@@ -475,8 +629,13 @@ module Solargraph
|
|
|
475
629
|
'::NilClass' => UniqueType::NIL
|
|
476
630
|
}.freeze
|
|
477
631
|
|
|
478
|
-
|
|
479
632
|
include Logging
|
|
633
|
+
|
|
634
|
+
protected
|
|
635
|
+
|
|
636
|
+
def equality_fields
|
|
637
|
+
[@name, @all_params, @subtypes, @key_types]
|
|
638
|
+
end
|
|
480
639
|
end
|
|
481
640
|
end
|
|
482
641
|
end
|