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
|
@@ -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,114 @@ 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] == ':'
|
|
178
|
+
# @sg-ignore Need to add nil check here
|
|
134
179
|
return 'String' if ['"', "'"].include?(name[0])
|
|
135
180
|
return 'Integer' if name.match?(/^-?\d+$/)
|
|
136
181
|
name
|
|
137
182
|
end
|
|
138
183
|
|
|
139
|
-
def eql?
|
|
184
|
+
def eql? other
|
|
140
185
|
self.class == other.class &&
|
|
141
|
-
# @sg-ignore
|
|
186
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
142
187
|
@name == other.name &&
|
|
143
|
-
# @sg-ignore
|
|
188
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
144
189
|
@key_types == other.key_types &&
|
|
145
|
-
# @sg-ignore
|
|
190
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
146
191
|
@subtypes == other.subtypes &&
|
|
147
|
-
# @sg-ignore
|
|
192
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
148
193
|
@rooted == other.rooted? &&
|
|
149
|
-
# @sg-ignore
|
|
194
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
150
195
|
@all_params == other.all_params &&
|
|
151
|
-
# @sg-ignore
|
|
196
|
+
# @sg-ignore flow sensitive typing should support .class == .class
|
|
152
197
|
@parameters_type == other.parameters_type
|
|
153
198
|
end
|
|
154
199
|
|
|
155
|
-
def ==
|
|
200
|
+
def == other
|
|
156
201
|
eql?(other)
|
|
157
202
|
end
|
|
158
203
|
|
|
204
|
+
# https://www.playfulpython.com/type-hinting-covariance-contra-variance/
|
|
205
|
+
|
|
206
|
+
# "[Expected] type variables that are COVARIANT can be substituted with
|
|
207
|
+
# a more specific [inferred] type without causing errors"
|
|
208
|
+
#
|
|
209
|
+
# "[Expected] type variables that are CONTRAVARIANT can be substituted
|
|
210
|
+
# with a more general [inferred] type without causing errors"
|
|
211
|
+
#
|
|
212
|
+
# "[Expected] types where neither is possible are INVARIANT"
|
|
213
|
+
#
|
|
214
|
+
# @param _situation [:method_call, :return_type]
|
|
215
|
+
# @param default [Symbol] The default variance to return if the type is not one of the special cases
|
|
216
|
+
#
|
|
217
|
+
# @return [:invariant, :covariant, :contravariant]
|
|
218
|
+
def parameter_variance _situation, default = :covariant
|
|
219
|
+
# @todo RBS can specify variance - maybe we can use that info
|
|
220
|
+
# and also let folks specify?
|
|
221
|
+
#
|
|
222
|
+
# Array/Set: ideally invariant, since we don't know if user is
|
|
223
|
+
# going to add new stuff into it or read it. But we don't
|
|
224
|
+
# have a way to specify, so we use covariant
|
|
225
|
+
# Enumerable: covariant: can't be changed, so we can pass
|
|
226
|
+
# in more specific subtypes
|
|
227
|
+
# Hash: read-only would be covariant, read-write would be
|
|
228
|
+
# invariant if we could distinguish that - should default to
|
|
229
|
+
# covariant
|
|
230
|
+
# contravariant?: Proc - can be changed, so we can pass
|
|
231
|
+
# in less specific super types
|
|
232
|
+
if %w[Hash Tuple Array Set Enumerable].include?(name) && fixed_parameters?
|
|
233
|
+
:covariant
|
|
234
|
+
else
|
|
235
|
+
default
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Whether this is an RBS interface like _ToAry or _Each.
|
|
240
|
+
def interface?
|
|
241
|
+
name.start_with?('_')
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# @param other [UniqueType]
|
|
245
|
+
def erased_version_of? other
|
|
246
|
+
name == other.name && (all_params.empty? || all_params.all?(&:undefined?))
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# @param api_map [ApiMap]
|
|
250
|
+
# @param expected [ComplexType::UniqueType, ComplexType]
|
|
251
|
+
# @param situation [:method_call, :assignment, :return_type]
|
|
252
|
+
# @param rules [Array<:allow_subtype_skew, :allow_empty_params, :allow_reverse_match, :allow_any_match, :allow_undefined, :allow_unresolved_generic>]
|
|
253
|
+
# @param variance [:invariant, :covariant, :contravariant]
|
|
254
|
+
def conforms_to? api_map, expected, situation, rules = [],
|
|
255
|
+
variance: erased_variance(situation)
|
|
256
|
+
return true if undefined? && rules.include?(:allow_undefined)
|
|
257
|
+
|
|
258
|
+
# @todo teach this to validate duck types as inferred type
|
|
259
|
+
return true if duck_type?
|
|
260
|
+
|
|
261
|
+
# complex types as expectations are unions - we only need to
|
|
262
|
+
# match one of their unique types
|
|
263
|
+
expected.any? do |expected_unique_type|
|
|
264
|
+
# :nocov:
|
|
265
|
+
unless expected_unique_type.instance_of?(UniqueType)
|
|
266
|
+
raise "Expected type must be a UniqueType, got #{expected_unique_type.class} in #{expected.inspect}"
|
|
267
|
+
end
|
|
268
|
+
# :nocov:
|
|
269
|
+
conformance = Conformance.new(api_map, self, expected_unique_type, situation,
|
|
270
|
+
rules, variance: variance)
|
|
271
|
+
conformance.conforms_to_unique_type?
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
159
275
|
def hash
|
|
160
276
|
[self.class, @name, @key_types, @sub_types, @rooted, @all_params, @parameters_type].hash
|
|
161
277
|
end
|
|
162
278
|
|
|
279
|
+
# @return [self]
|
|
280
|
+
def erase_parameters
|
|
281
|
+
UniqueType.new(name, rooted: rooted?, parameters_type: parameters_type)
|
|
282
|
+
end
|
|
283
|
+
|
|
163
284
|
# @return [Array<UniqueType>]
|
|
164
285
|
def items
|
|
165
286
|
[self]
|
|
@@ -181,6 +302,7 @@ module Solargraph
|
|
|
181
302
|
rooted_tags
|
|
182
303
|
end
|
|
183
304
|
|
|
305
|
+
# @sg-ignore Need better if/elseanalysis
|
|
184
306
|
# @return [String]
|
|
185
307
|
def to_rbs
|
|
186
308
|
if duck_type?
|
|
@@ -190,10 +312,10 @@ module Solargraph
|
|
|
190
312
|
elsif name.downcase == 'nil'
|
|
191
313
|
'nil'
|
|
192
314
|
elsif name == GENERIC_TAG_NAME
|
|
193
|
-
all_params.first
|
|
194
|
-
elsif [
|
|
315
|
+
all_params.first&.name
|
|
316
|
+
elsif %w[Class Module].include?(name)
|
|
195
317
|
rbs_name
|
|
196
|
-
elsif [
|
|
318
|
+
elsif %w[Tuple Array].include?(name) && fixed_parameters?
|
|
197
319
|
# tuples don't have a name; they're just [foo, bar, baz].
|
|
198
320
|
if substring == '()'
|
|
199
321
|
# but there are no zero element tuples, so we go with an array
|
|
@@ -218,7 +340,7 @@ module Solargraph
|
|
|
218
340
|
|
|
219
341
|
# @param types [Array<UniqueType, ComplexType>]
|
|
220
342
|
# @return [String]
|
|
221
|
-
def rbs_union
|
|
343
|
+
def rbs_union types
|
|
222
344
|
if types.length == 1
|
|
223
345
|
types.first.to_rbs
|
|
224
346
|
else
|
|
@@ -242,16 +364,13 @@ module Solargraph
|
|
|
242
364
|
name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
|
|
243
365
|
end
|
|
244
366
|
|
|
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
|
|
367
|
+
def nullable?
|
|
368
|
+
nil_type?
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# @yieldreturn [Boolean]
|
|
372
|
+
def all? &block
|
|
373
|
+
block.yield self
|
|
255
374
|
end
|
|
256
375
|
|
|
257
376
|
# @return [UniqueType]
|
|
@@ -260,37 +379,44 @@ module Solargraph
|
|
|
260
379
|
end
|
|
261
380
|
|
|
262
381
|
# @param generics_to_resolve [Enumerable<String>]
|
|
263
|
-
# @param context_type [UniqueType, nil]
|
|
382
|
+
# @param context_type [ComplexType, UniqueType, nil]
|
|
264
383
|
# @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
|
|
265
384
|
# @return [UniqueType, ComplexType]
|
|
266
385
|
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
|
267
386
|
if name == ComplexType::GENERIC_TAG_NAME
|
|
268
387
|
type_param = subtypes.first&.name
|
|
388
|
+
# @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
269
389
|
return self unless generics_to_resolve.include? type_param
|
|
390
|
+
# @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
270
391
|
unless context_type.nil? || !resolved_generic_values[type_param].nil?
|
|
271
392
|
new_binding = true
|
|
393
|
+
# @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
272
394
|
resolved_generic_values[type_param] = context_type
|
|
273
395
|
end
|
|
274
396
|
if new_binding
|
|
275
397
|
resolved_generic_values.transform_values! do |complex_type|
|
|
276
|
-
complex_type.resolve_generics_from_context(generics_to_resolve, nil,
|
|
398
|
+
complex_type.resolve_generics_from_context(generics_to_resolve, nil,
|
|
399
|
+
resolved_generic_values: resolved_generic_values)
|
|
277
400
|
end
|
|
278
401
|
end
|
|
402
|
+
# @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
|
|
279
403
|
return resolved_generic_values[type_param] || self
|
|
280
404
|
end
|
|
281
405
|
|
|
282
406
|
# @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
|
-
|
|
407
|
+
new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values,
|
|
408
|
+
&:key_types)
|
|
409
|
+
new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values,
|
|
410
|
+
&:subtypes)
|
|
285
411
|
recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
|
|
286
412
|
end
|
|
287
413
|
|
|
288
414
|
# @param generics_to_resolve [Enumerable<String>]
|
|
289
|
-
# @param context_type [UniqueType, nil]
|
|
415
|
+
# @param context_type [UniqueType, ComplexType, nil]
|
|
290
416
|
# @param resolved_generic_values [Hash{String => ComplexType}]
|
|
291
417
|
# @yieldreturn [Array<ComplexType>]
|
|
292
418
|
# @return [Array<ComplexType>]
|
|
293
|
-
def resolve_param_generics_from_context
|
|
419
|
+
def resolve_param_generics_from_context generics_to_resolve, context_type, resolved_generic_values
|
|
294
420
|
types = yield self
|
|
295
421
|
types.each_with_index.flat_map do |ct, i|
|
|
296
422
|
ct.items.flat_map do |ut|
|
|
@@ -298,10 +424,12 @@ module Solargraph
|
|
|
298
424
|
if context_params && context_params[i]
|
|
299
425
|
type_arg = context_params[i]
|
|
300
426
|
type_arg.map do |new_unique_context_type|
|
|
301
|
-
ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type,
|
|
427
|
+
ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type,
|
|
428
|
+
resolved_generic_values: resolved_generic_values
|
|
302
429
|
end
|
|
303
430
|
else
|
|
304
|
-
ut.resolve_generics_from_context generics_to_resolve, nil,
|
|
431
|
+
ut.resolve_generics_from_context generics_to_resolve, nil,
|
|
432
|
+
resolved_generic_values: resolved_generic_values
|
|
305
433
|
end
|
|
306
434
|
end
|
|
307
435
|
end
|
|
@@ -323,7 +451,7 @@ module Solargraph
|
|
|
323
451
|
idx = definitions.generics.index(generic_name)
|
|
324
452
|
next t if idx.nil?
|
|
325
453
|
if context_type.parameters_type == :hash
|
|
326
|
-
if idx
|
|
454
|
+
if idx.zero?
|
|
327
455
|
next ComplexType.new(context_type.key_types)
|
|
328
456
|
elsif idx == 1
|
|
329
457
|
next ComplexType.new(context_type.subtypes)
|
|
@@ -331,12 +459,13 @@ module Solargraph
|
|
|
331
459
|
next ComplexType::UNDEFINED
|
|
332
460
|
end
|
|
333
461
|
elsif context_type.all?(&:implicit_union?)
|
|
334
|
-
if idx
|
|
462
|
+
if idx.zero? && !context_type.all_params.empty?
|
|
335
463
|
ComplexType.new(context_type.all_params)
|
|
336
464
|
else
|
|
337
465
|
ComplexType::UNDEFINED
|
|
338
466
|
end
|
|
339
467
|
else
|
|
468
|
+
# @sg-ignore Need to add nil check here
|
|
340
469
|
context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
|
|
341
470
|
end
|
|
342
471
|
else
|
|
@@ -352,6 +481,13 @@ module Solargraph
|
|
|
352
481
|
[block.yield(self)]
|
|
353
482
|
end
|
|
354
483
|
|
|
484
|
+
# @yieldparam t [self]
|
|
485
|
+
# @yieldreturn [self]
|
|
486
|
+
# @return [Enumerable<self>]
|
|
487
|
+
def each &block
|
|
488
|
+
[self].each(&block)
|
|
489
|
+
end
|
|
490
|
+
|
|
355
491
|
# @return [Array<UniqueType>]
|
|
356
492
|
def to_a
|
|
357
493
|
[self]
|
|
@@ -360,16 +496,17 @@ module Solargraph
|
|
|
360
496
|
# @param new_name [String, nil]
|
|
361
497
|
# @param make_rooted [Boolean, nil]
|
|
362
498
|
# @param new_key_types [Array<ComplexType>, nil]
|
|
363
|
-
# @param
|
|
499
|
+
# @param make_rooted [Boolean, nil]
|
|
364
500
|
# @param new_subtypes [Array<ComplexType>, nil]
|
|
365
501
|
# @return [self]
|
|
366
|
-
def recreate
|
|
502
|
+
def recreate new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil
|
|
367
503
|
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
|
368
504
|
|
|
369
505
|
new_name ||= name
|
|
370
506
|
new_key_types ||= @key_types
|
|
371
507
|
new_subtypes ||= @subtypes
|
|
372
508
|
make_rooted = @rooted if make_rooted.nil?
|
|
509
|
+
# @sg-ignore flow sensitive typing needs better handling of ||= on lvars
|
|
373
510
|
UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
|
|
374
511
|
end
|
|
375
512
|
|
|
@@ -396,8 +533,10 @@ module Solargraph
|
|
|
396
533
|
# @yieldparam t [UniqueType]
|
|
397
534
|
# @yieldreturn [self]
|
|
398
535
|
# @return [self]
|
|
399
|
-
def transform
|
|
400
|
-
|
|
536
|
+
def transform new_name = nil, &transform_type
|
|
537
|
+
if new_name&.start_with?('::')
|
|
538
|
+
raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}"
|
|
539
|
+
end
|
|
401
540
|
if name == ComplexType::GENERIC_TAG_NAME
|
|
402
541
|
# doesn't make sense to manipulate the name of the generic
|
|
403
542
|
new_key_types = @key_types
|
|
@@ -406,14 +545,15 @@ module Solargraph
|
|
|
406
545
|
new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
|
407
546
|
new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
|
408
547
|
end
|
|
409
|
-
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
|
|
548
|
+
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
|
|
549
|
+
make_rooted: @rooted)
|
|
410
550
|
yield new_type
|
|
411
551
|
end
|
|
412
552
|
|
|
413
553
|
# Generate a ComplexType that fully qualifies this type's namespaces.
|
|
414
554
|
#
|
|
415
555
|
# @param api_map [ApiMap] The ApiMap that performs qualification
|
|
416
|
-
# @param
|
|
556
|
+
# @param gates [Array<String>] The namespaces from which to resolve names
|
|
417
557
|
# @return [self, ComplexType, UniqueType] The generated ComplexType
|
|
418
558
|
def qualify api_map, *gates
|
|
419
559
|
transform do |t|
|
|
@@ -443,6 +583,22 @@ module Solargraph
|
|
|
443
583
|
end
|
|
444
584
|
end
|
|
445
585
|
|
|
586
|
+
# @yieldreturn [Boolean]
|
|
587
|
+
def any? &block
|
|
588
|
+
block.yield self
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
# @return [ComplexType]
|
|
592
|
+
def reduce_class_type
|
|
593
|
+
new_items = items.flat_map do |type|
|
|
594
|
+
next type unless %w[Module Class].include?(type.name)
|
|
595
|
+
next type if type.all_params.empty?
|
|
596
|
+
|
|
597
|
+
type.all_params
|
|
598
|
+
end
|
|
599
|
+
ComplexType.new(new_items)
|
|
600
|
+
end
|
|
601
|
+
|
|
446
602
|
def all_rooted?
|
|
447
603
|
return true if name == GENERIC_TAG_NAME
|
|
448
604
|
rooted? && all_params.all?(&:rooted?)
|
|
@@ -453,12 +609,12 @@ module Solargraph
|
|
|
453
609
|
end
|
|
454
610
|
|
|
455
611
|
# @param name_to_check [String]
|
|
456
|
-
def can_root_name?
|
|
612
|
+
def can_root_name? name_to_check = name
|
|
457
613
|
self.class.can_root_name?(name_to_check)
|
|
458
614
|
end
|
|
459
615
|
|
|
460
616
|
# @param name [String]
|
|
461
|
-
def self.can_root_name?
|
|
617
|
+
def self.can_root_name? name
|
|
462
618
|
# name is not lowercase
|
|
463
619
|
!name.empty? && name != name.downcase
|
|
464
620
|
end
|
|
@@ -475,8 +631,13 @@ module Solargraph
|
|
|
475
631
|
'::NilClass' => UniqueType::NIL
|
|
476
632
|
}.freeze
|
|
477
633
|
|
|
478
|
-
|
|
479
634
|
include Logging
|
|
635
|
+
|
|
636
|
+
protected
|
|
637
|
+
|
|
638
|
+
def equality_fields
|
|
639
|
+
[@name, @all_params, @subtypes, @key_types]
|
|
640
|
+
end
|
|
480
641
|
end
|
|
481
642
|
end
|
|
482
643
|
end
|