solargraph 0.58.3 → 0.59.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 +12 -5
- data/.github/workflows/plugins.yml +54 -34
- data/.github/workflows/rspec.yml +15 -28
- data/.github/workflows/typecheck.yml +6 -3
- data/.rubocop.yml +38 -6
- data/.rubocop_todo.yml +53 -966
- data/CHANGELOG.md +24 -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 +40 -30
- data/lib/solargraph/api_map.rb +160 -78
- data/lib/solargraph/bench.rb +2 -3
- data/lib/solargraph/complex_type/conformance.rb +176 -0
- data/lib/solargraph/complex_type/type_methods.rb +31 -18
- data/lib/solargraph/complex_type/unique_type.rb +221 -63
- data/lib/solargraph/complex_type.rb +173 -59
- data/lib/solargraph/convention/active_support_concern.rb +111 -111
- data/lib/solargraph/convention/base.rb +50 -50
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
- data/lib/solargraph/convention/data_definition.rb +5 -2
- data/lib/solargraph/convention/gemfile.rb +1 -1
- data/lib/solargraph/convention/gemspec.rb +1 -1
- data/lib/solargraph/convention/rakefile.rb +1 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
- data/lib/solargraph/convention/struct_definition.rb +8 -4
- data/lib/solargraph/convention.rb +2 -2
- data/lib/solargraph/converters/dd.rb +2 -0
- data/lib/solargraph/converters/dl.rb +2 -0
- data/lib/solargraph/converters/dt.rb +2 -0
- data/lib/solargraph/converters/misc.rb +2 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
- data/lib/solargraph/diagnostics/rubocop.rb +11 -10
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/diagnostics/type_check.rb +11 -10
- data/lib/solargraph/diagnostics/update_errors.rb +4 -8
- data/lib/solargraph/diagnostics.rb +55 -55
- data/lib/solargraph/doc_map.rb +38 -39
- data/lib/solargraph/environ.rb +52 -52
- data/lib/solargraph/equality.rb +4 -4
- data/lib/solargraph/gem_pins.rb +4 -15
- data/lib/solargraph/language_server/error_codes.rb +10 -10
- data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
- data/lib/solargraph/language_server/host/dispatch.rb +3 -3
- data/lib/solargraph/language_server/host/message_worker.rb +4 -3
- data/lib/solargraph/language_server/host/sources.rb +2 -1
- data/lib/solargraph/language_server/host.rb +35 -28
- data/lib/solargraph/language_server/message/base.rb +1 -1
- data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
- data/lib/solargraph/language_server/message/extended/document.rb +1 -0
- data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
- data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
- data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
- data/lib/solargraph/language_server/message/extended/search.rb +1 -1
- data/lib/solargraph/language_server/message/initialize.rb +20 -14
- data/lib/solargraph/language_server/message/initialized.rb +28 -28
- data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
- data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
- data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
- data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
- data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
- data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
- data/lib/solargraph/language_server/message/text_document.rb +28 -28
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
- data/lib/solargraph/language_server/message.rb +1 -1
- data/lib/solargraph/language_server/progress.rb +143 -143
- data/lib/solargraph/language_server/request.rb +4 -2
- data/lib/solargraph/language_server/transport/adapter.rb +68 -68
- data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
- data/lib/solargraph/language_server/uri_helpers.rb +2 -2
- data/lib/solargraph/language_server.rb +20 -20
- data/lib/solargraph/library.rb +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 +51 -25
- data/lib/solargraph/parser/parser_gem/node_methods.rb +181 -73
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/parser_gem.rb +2 -0
- data/lib/solargraph/parser/region.rb +9 -3
- data/lib/solargraph/parser/snippet.rb +3 -1
- data/lib/solargraph/parser.rb +2 -0
- data/lib/solargraph/pin/base.rb +126 -82
- 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 +158 -104
- data/lib/solargraph/pin/method_alias.rb +8 -0
- data/lib/solargraph/pin/namespace.rb +19 -12
- data/lib/solargraph/pin/parameter.rb +102 -36
- data/lib/solargraph/pin/proxy_type.rb +4 -1
- data/lib/solargraph/pin/reference/override.rb +1 -1
- data/lib/solargraph/pin/reference/require.rb +14 -14
- data/lib/solargraph/pin/reference/superclass.rb +2 -0
- data/lib/solargraph/pin/reference/type_alias.rb +16 -0
- data/lib/solargraph/pin/reference.rb +20 -0
- data/lib/solargraph/pin/search.rb +8 -7
- data/lib/solargraph/pin/signature.rb +15 -12
- data/lib/solargraph/pin/singleton.rb +11 -11
- data/lib/solargraph/pin/symbol.rb +2 -1
- data/lib/solargraph/pin/until.rb +2 -4
- data/lib/solargraph/pin/while.rb +2 -4
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin_cache.rb +22 -19
- data/lib/solargraph/position.rb +17 -10
- data/lib/solargraph/range.rb +16 -15
- data/lib/solargraph/rbs_map/conversions.rb +367 -231
- 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 +3 -12
- data/lib/solargraph/source/chain/block_symbol.rb +13 -13
- data/lib/solargraph/source/chain/block_variable.rb +13 -13
- data/lib/solargraph/source/chain/call.rb +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/head.rb +19 -19
- 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 +22 -15
- data/lib/solargraph/source/chain/or.rb +10 -4
- data/lib/solargraph/source/chain/q_call.rb +2 -0
- data/lib/solargraph/source/chain/variable.rb +3 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -3
- data/lib/solargraph/source/chain.rb +51 -38
- data/lib/solargraph/source/change.rb +12 -5
- data/lib/solargraph/source/cursor.rb +33 -18
- data/lib/solargraph/source/encoding_fixes.rb +6 -7
- data/lib/solargraph/source/source_chainer.rb +56 -32
- data/lib/solargraph/source/updater.rb +5 -1
- data/lib/solargraph/source.rb +59 -35
- data/lib/solargraph/source_map/clip.rb +54 -30
- data/lib/solargraph/source_map/data.rb +4 -1
- data/lib/solargraph/source_map/mapper.rb +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 +196 -122
- 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/cache.rb +25 -25
- data/lib/solargraph/yard_map/helpers.rb +8 -3
- data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
- data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
- data/lib/solargraph/yard_map/mapper.rb +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 +33 -10
- data/rbs/fills/rubygems/0/dependency.rbs +193 -0
- data/rbs/shims/ast/0/node.rbs +1 -1
- data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
- data/solargraph.gemspec +37 -35
- metadata +41 -42
- data/lib/solargraph/type_checker/checks.rb +0 -124
- data/lib/solargraph/type_checker/param_def.rb +0 -37
- data/lib/solargraph/yard_map/to_method.rb +0 -89
- data/rbs/fills/tuple/tuple.rbs +0 -149
|
@@ -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,7 +108,46 @@ 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?
|
|
150
|
+
return false
|
|
113
151
|
non_literal_name != name
|
|
114
152
|
end
|
|
115
153
|
|
|
@@ -118,6 +156,13 @@ module Solargraph
|
|
|
118
156
|
@non_literal_name ||= determine_non_literal_name
|
|
119
157
|
end
|
|
120
158
|
|
|
159
|
+
# @return [self]
|
|
160
|
+
def without_nil
|
|
161
|
+
return UniqueType::UNDEFINED if nil_type?
|
|
162
|
+
|
|
163
|
+
self
|
|
164
|
+
end
|
|
165
|
+
|
|
121
166
|
# @return [String]
|
|
122
167
|
def determine_non_literal_name
|
|
123
168
|
# https://github.com/ruby/rbs/blob/master/docs/syntax.md
|
|
@@ -129,37 +174,113 @@ module Solargraph
|
|
|
129
174
|
# | `false`
|
|
130
175
|
return name if name.empty?
|
|
131
176
|
return 'NilClass' if name == 'nil'
|
|
132
|
-
return 'Boolean' if [
|
|
177
|
+
return 'Boolean' if %w[true false].include?(name)
|
|
133
178
|
return 'Symbol' if name[0] == ':'
|
|
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 Hash::_Key.
|
|
240
|
+
def interface?
|
|
241
|
+
name.start_with?('_') || name.include?('::_')
|
|
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,55 +364,59 @@ 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]
|
|
258
377
|
def downcast_to_literal_if_possible
|
|
378
|
+
return self
|
|
259
379
|
SINGLE_SUBTYPE.fetch(rooted_tag, self)
|
|
260
380
|
end
|
|
261
381
|
|
|
262
382
|
# @param generics_to_resolve [Enumerable<String>]
|
|
263
|
-
# @param context_type [UniqueType, nil]
|
|
383
|
+
# @param context_type [ComplexType, UniqueType, nil]
|
|
264
384
|
# @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
|
|
265
385
|
# @return [UniqueType, ComplexType]
|
|
266
386
|
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
|
267
387
|
if name == ComplexType::GENERIC_TAG_NAME
|
|
268
388
|
type_param = subtypes.first&.name
|
|
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,21 +451,19 @@ 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)
|
|
330
458
|
else
|
|
331
459
|
next ComplexType::UNDEFINED
|
|
332
460
|
end
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
ComplexType::UNDEFINED
|
|
338
|
-
end
|
|
461
|
+
# @todo Treating parameterized classes and tuples the same for now
|
|
462
|
+
# elsif context_type.all?(&:implicit_union?) || true
|
|
463
|
+
elsif idx.zero? && !context_type.all_params.empty?
|
|
464
|
+
ComplexType.new(context_type.all_params)
|
|
339
465
|
else
|
|
340
|
-
|
|
466
|
+
ComplexType::UNDEFINED
|
|
341
467
|
end
|
|
342
468
|
else
|
|
343
469
|
t
|
|
@@ -352,6 +478,13 @@ module Solargraph
|
|
|
352
478
|
[block.yield(self)]
|
|
353
479
|
end
|
|
354
480
|
|
|
481
|
+
# @yieldparam t [self]
|
|
482
|
+
# @yieldreturn [self]
|
|
483
|
+
# @return [Enumerable<self>]
|
|
484
|
+
def each(&)
|
|
485
|
+
[self].each(&)
|
|
486
|
+
end
|
|
487
|
+
|
|
355
488
|
# @return [Array<UniqueType>]
|
|
356
489
|
def to_a
|
|
357
490
|
[self]
|
|
@@ -360,16 +493,17 @@ module Solargraph
|
|
|
360
493
|
# @param new_name [String, nil]
|
|
361
494
|
# @param make_rooted [Boolean, nil]
|
|
362
495
|
# @param new_key_types [Array<ComplexType>, nil]
|
|
363
|
-
# @param
|
|
496
|
+
# @param make_rooted [Boolean, nil]
|
|
364
497
|
# @param new_subtypes [Array<ComplexType>, nil]
|
|
365
498
|
# @return [self]
|
|
366
|
-
def recreate
|
|
499
|
+
def recreate new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil
|
|
367
500
|
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
|
368
501
|
|
|
369
502
|
new_name ||= name
|
|
370
503
|
new_key_types ||= @key_types
|
|
371
504
|
new_subtypes ||= @subtypes
|
|
372
505
|
make_rooted = @rooted if make_rooted.nil?
|
|
506
|
+
# @sg-ignore flow sensitive typing needs better handling of ||= on lvars
|
|
373
507
|
UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
|
|
374
508
|
end
|
|
375
509
|
|
|
@@ -396,8 +530,10 @@ module Solargraph
|
|
|
396
530
|
# @yieldparam t [UniqueType]
|
|
397
531
|
# @yieldreturn [self]
|
|
398
532
|
# @return [self]
|
|
399
|
-
def transform
|
|
400
|
-
|
|
533
|
+
def transform new_name = nil, &transform_type
|
|
534
|
+
if new_name&.start_with?('::')
|
|
535
|
+
raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}"
|
|
536
|
+
end
|
|
401
537
|
if name == ComplexType::GENERIC_TAG_NAME
|
|
402
538
|
# doesn't make sense to manipulate the name of the generic
|
|
403
539
|
new_key_types = @key_types
|
|
@@ -406,14 +542,15 @@ module Solargraph
|
|
|
406
542
|
new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
|
407
543
|
new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
|
408
544
|
end
|
|
409
|
-
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
|
|
545
|
+
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
|
|
546
|
+
make_rooted: @rooted)
|
|
410
547
|
yield new_type
|
|
411
548
|
end
|
|
412
549
|
|
|
413
550
|
# Generate a ComplexType that fully qualifies this type's namespaces.
|
|
414
551
|
#
|
|
415
552
|
# @param api_map [ApiMap] The ApiMap that performs qualification
|
|
416
|
-
# @param
|
|
553
|
+
# @param gates [Array<String>] The namespaces from which to resolve names
|
|
417
554
|
# @return [self, ComplexType, UniqueType] The generated ComplexType
|
|
418
555
|
def qualify api_map, *gates
|
|
419
556
|
transform do |t|
|
|
@@ -443,6 +580,22 @@ module Solargraph
|
|
|
443
580
|
end
|
|
444
581
|
end
|
|
445
582
|
|
|
583
|
+
# @yieldreturn [Boolean]
|
|
584
|
+
def any? &block
|
|
585
|
+
block.yield self
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
# @return [ComplexType]
|
|
589
|
+
def reduce_class_type
|
|
590
|
+
new_items = items.flat_map do |type|
|
|
591
|
+
next type unless %w[Module Class].include?(type.name)
|
|
592
|
+
next type if type.all_params.empty?
|
|
593
|
+
|
|
594
|
+
type.all_params
|
|
595
|
+
end
|
|
596
|
+
ComplexType.new(new_items)
|
|
597
|
+
end
|
|
598
|
+
|
|
446
599
|
def all_rooted?
|
|
447
600
|
return true if name == GENERIC_TAG_NAME
|
|
448
601
|
rooted? && all_params.all?(&:rooted?)
|
|
@@ -453,12 +606,12 @@ module Solargraph
|
|
|
453
606
|
end
|
|
454
607
|
|
|
455
608
|
# @param name_to_check [String]
|
|
456
|
-
def can_root_name?
|
|
609
|
+
def can_root_name? name_to_check = name
|
|
457
610
|
self.class.can_root_name?(name_to_check)
|
|
458
611
|
end
|
|
459
612
|
|
|
460
613
|
# @param name [String]
|
|
461
|
-
def self.can_root_name?
|
|
614
|
+
def self.can_root_name? name
|
|
462
615
|
# name is not lowercase
|
|
463
616
|
!name.empty? && name != name.downcase
|
|
464
617
|
end
|
|
@@ -475,8 +628,13 @@ module Solargraph
|
|
|
475
628
|
'::NilClass' => UniqueType::NIL
|
|
476
629
|
}.freeze
|
|
477
630
|
|
|
478
|
-
|
|
479
631
|
include Logging
|
|
632
|
+
|
|
633
|
+
protected
|
|
634
|
+
|
|
635
|
+
def equality_fields
|
|
636
|
+
[@name, @all_params, @subtypes, @key_types]
|
|
637
|
+
end
|
|
480
638
|
end
|
|
481
639
|
end
|
|
482
640
|
end
|