solargraph 0.47.2 → 0.54.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/.github/FUNDING.yml +1 -0
- data/.github/workflows/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +4 -8
- data/.github/workflows/typecheck.yml +34 -0
- data/.yardopts +2 -2
- data/CHANGELOG.md +166 -3
- data/LICENSE +1 -1
- data/README.md +19 -16
- data/SPONSORS.md +2 -9
- data/lib/solargraph/api_map/cache.rb +50 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +68 -15
- data/lib/solargraph/api_map.rb +238 -112
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +77 -0
- data/lib/solargraph/complex_type/type_methods.rb +116 -35
- data/lib/solargraph/complex_type/unique_type.rb +261 -33
- data/lib/solargraph/complex_type.rb +149 -30
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -3
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +23 -8
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +187 -0
- data/lib/solargraph/gem_pins.rb +72 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +22 -5
- data/lib/solargraph/language_server/host/message_worker.rb +4 -0
- data/lib/solargraph/language_server/host/sources.rb +8 -65
- data/lib/solargraph/language_server/host.rb +88 -93
- data/lib/solargraph/language_server/message/base.rb +1 -1
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +27 -0
- data/lib/solargraph/language_server/message/initialized.rb +1 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +4 -1
- data/lib/solargraph/language_server/message/text_document/formatting.rb +5 -4
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
- data/lib/solargraph/language_server/message/text_document.rb +1 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/language_server/message.rb +1 -0
- data/lib/solargraph/language_server/progress.rb +118 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/language_server.rb +1 -0
- data/lib/solargraph/library.rb +231 -104
- data/lib/solargraph/location.rb +1 -0
- data/lib/solargraph/page.rb +6 -0
- data/lib/solargraph/parser/comment_ripper.rb +4 -0
- data/lib/solargraph/parser/node_methods.rb +47 -7
- data/lib/solargraph/parser/node_processor/base.rb +11 -1
- data/lib/solargraph/parser/node_processor.rb +1 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +57 -41
- data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +53 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +14 -4
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +7 -20
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +47 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +7 -5
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +9 -10
- data/lib/solargraph/pin/base.rb +69 -11
- data/lib/solargraph/pin/base_variable.rb +40 -7
- data/lib/solargraph/pin/block.rb +81 -33
- data/lib/solargraph/pin/closure.rb +17 -2
- data/lib/solargraph/pin/common.rb +7 -3
- data/lib/solargraph/pin/conversions.rb +34 -8
- data/lib/solargraph/pin/delegated_method.rb +101 -0
- data/lib/solargraph/pin/documenting.rb +25 -32
- data/lib/solargraph/pin/instance_variable.rb +4 -0
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +273 -17
- data/lib/solargraph/pin/namespace.rb +17 -1
- data/lib/solargraph/pin/parameter.rb +40 -28
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +4 -4
- data/lib/solargraph/pin/signature.rb +143 -0
- data/lib/solargraph/pin.rb +2 -1
- data/lib/solargraph/range.rb +4 -6
- data/lib/solargraph/rbs_map/conversions.rb +607 -0
- data/lib/solargraph/rbs_map/core_fills.rb +50 -0
- data/lib/solargraph/rbs_map/core_map.rb +28 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
- data/lib/solargraph/rbs_map.rb +92 -0
- data/lib/solargraph/shell.rb +85 -59
- data/lib/solargraph/source/chain/array.rb +32 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +125 -61
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +8 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +3 -3
- data/lib/solargraph/source/chain.rb +64 -14
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +2 -0
- data/lib/solargraph/source/source_chainer.rb +8 -5
- data/lib/solargraph/source/updater.rb +1 -0
- data/lib/solargraph/source.rb +18 -63
- data/lib/solargraph/source_map/clip.rb +31 -23
- data/lib/solargraph/source_map/mapper.rb +23 -7
- data/lib/solargraph/source_map.rb +36 -11
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +229 -100
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace/config.rb +15 -11
- data/lib/solargraph/workspace.rb +41 -17
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +23 -7
- data/lib/solargraph/yard_map/mapper.rb +1 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +1 -443
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +8 -6
- data/solargraph.gemspec +19 -8
- metadata +164 -99
- data/.travis.yml +0 -19
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/convention/rspec.rb +0 -30
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/language_server/host/cataloger.rb +0 -56
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/lib/yard-solargraph.rb +0 -33
- data/yardoc/2.2.2.tar.gz +0 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rbs'
|
3
|
+
|
4
|
+
module Solargraph
|
5
|
+
module Cache
|
6
|
+
class << self
|
7
|
+
# The base directory where cached documentation is installed.
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
def base_dir
|
11
|
+
# The directory is not stored in a variable so it can be overridden
|
12
|
+
# in specs.
|
13
|
+
ENV['SOLARGRAPH_CACHE'] ||
|
14
|
+
(ENV['XDG_CACHE_HOME'] ? File.join(ENV['XDG_CACHE_HOME'], 'solargraph') : nil) ||
|
15
|
+
File.join(Dir.home, '.cache', 'solargraph')
|
16
|
+
end
|
17
|
+
|
18
|
+
# The working directory for the current Ruby, RBS, and Solargraph versions.
|
19
|
+
#
|
20
|
+
# @return [String]
|
21
|
+
def work_dir
|
22
|
+
# The directory is not stored in a variable so it can be overridden
|
23
|
+
# in specs.
|
24
|
+
File.join(base_dir, "ruby-#{RUBY_VERSION}", "rbs-#{RBS::VERSION}", "solargraph-#{Solargraph::VERSION}")
|
25
|
+
end
|
26
|
+
|
27
|
+
# Append the given path to the current cache directory (`work_dir`).
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# Cache.join('date-3.4.1.ser')
|
31
|
+
#
|
32
|
+
# @param path [Array<String>]
|
33
|
+
# @return [String]
|
34
|
+
def join *path
|
35
|
+
File.join(work_dir, *path)
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param path [Array<String>]
|
39
|
+
# @return [Array<Solargraph::Pin::Base>, nil]
|
40
|
+
def load *path
|
41
|
+
file = join(*path)
|
42
|
+
return nil unless File.file?(file)
|
43
|
+
Marshal.load(File.read(file, mode: 'rb'))
|
44
|
+
rescue StandardError => e
|
45
|
+
Solargraph.logger.warn "Failed to load cached file #{file}: [#{e.class}] #{e.message}"
|
46
|
+
FileUtils.rm_f file
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def exist? *path
|
51
|
+
File.file? join(*path)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param path [Array<String>]
|
55
|
+
# @param pins [Array<Pin::Base>]
|
56
|
+
# @return [void]
|
57
|
+
def save *path, pins
|
58
|
+
file = File.join(work_dir, *path)
|
59
|
+
base = File.dirname(file)
|
60
|
+
FileUtils.mkdir_p base unless File.directory?(base)
|
61
|
+
ser = Marshal.dump(pins)
|
62
|
+
File.write file, ser, mode: 'wb'
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [void]
|
66
|
+
# @param path [Array<String>]
|
67
|
+
def uncache *path
|
68
|
+
FileUtils.rm_rf File.join(work_dir, *path), secure: true
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [void]
|
72
|
+
def clear
|
73
|
+
FileUtils.rm_rf base_dir, secure: true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -2,20 +2,38 @@
|
|
2
2
|
|
3
3
|
module Solargraph
|
4
4
|
class ComplexType
|
5
|
-
# Methods for accessing type data
|
5
|
+
# Methods for accessing type data available from
|
6
|
+
# both ComplexType and UniqueType.
|
6
7
|
#
|
8
|
+
# @abstract This mixin relies on these -
|
9
|
+
# instance variables:
|
10
|
+
# @name: String
|
11
|
+
# @subtypes: Array<ComplexType>
|
12
|
+
# @rooted: boolish
|
13
|
+
# methods:
|
14
|
+
# transform()
|
7
15
|
module TypeMethods
|
16
|
+
# @!method transform(new_name = nil, &transform_type)
|
17
|
+
# @param new_name [String, nil]
|
18
|
+
# @yieldparam t [UniqueType]
|
19
|
+
# @yieldreturn [UniqueType]
|
20
|
+
# @return [UniqueType, nil]
|
21
|
+
|
8
22
|
# @return [String]
|
9
23
|
attr_reader :name
|
10
24
|
|
11
|
-
# @return [
|
12
|
-
attr_reader :
|
25
|
+
# @return [Array<ComplexType>]
|
26
|
+
attr_reader :subtypes
|
13
27
|
|
14
28
|
# @return [String]
|
15
|
-
|
29
|
+
def tag
|
30
|
+
@tag ||= "#{name}#{substring}"
|
31
|
+
end
|
16
32
|
|
17
|
-
# @return [
|
18
|
-
|
33
|
+
# @return [String]
|
34
|
+
def rooted_tag
|
35
|
+
@rooted_tag ||= rooted_name + rooted_substring
|
36
|
+
end
|
19
37
|
|
20
38
|
# @return [Boolean]
|
21
39
|
def duck_type?
|
@@ -24,8 +42,7 @@ module Solargraph
|
|
24
42
|
|
25
43
|
# @return [Boolean]
|
26
44
|
def nil_type?
|
27
|
-
@nil_type
|
28
|
-
@nil_type
|
45
|
+
@nil_type ||= (name.casecmp('nil') == 0)
|
29
46
|
end
|
30
47
|
|
31
48
|
# @return [Boolean]
|
@@ -33,6 +50,10 @@ module Solargraph
|
|
33
50
|
!substring.empty?
|
34
51
|
end
|
35
52
|
|
53
|
+
def tuple?
|
54
|
+
@tuple_type ||= (name == 'Tuple') || (name == 'Array' && subtypes.length >= 1 && fixed_parameters?)
|
55
|
+
end
|
56
|
+
|
36
57
|
def void?
|
37
58
|
name == 'void'
|
38
59
|
end
|
@@ -45,19 +66,44 @@ module Solargraph
|
|
45
66
|
name == 'undefined'
|
46
67
|
end
|
47
68
|
|
69
|
+
# @param generics_to_erase [Enumerable<String>]
|
70
|
+
# @return [self]
|
71
|
+
def erase_generics(generics_to_erase)
|
72
|
+
transform do |type|
|
73
|
+
if type.name == ComplexType::GENERIC_TAG_NAME
|
74
|
+
if type.all_params.length == 1 && generics_to_erase.include?(type.all_params.first.to_s)
|
75
|
+
ComplexType::UNDEFINED
|
76
|
+
else
|
77
|
+
type
|
78
|
+
end
|
79
|
+
else
|
80
|
+
type
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [Symbol, nil]
|
86
|
+
attr_reader :parameters_type
|
87
|
+
|
88
|
+
PARAMETERS_TYPE_BY_STARTING_TAG = {
|
89
|
+
'{' => :hash,
|
90
|
+
'(' => :fixed,
|
91
|
+
'<' => :list
|
92
|
+
}.freeze
|
93
|
+
|
48
94
|
# @return [Boolean]
|
49
95
|
def list_parameters?
|
50
|
-
|
96
|
+
parameters_type == :list
|
51
97
|
end
|
52
98
|
|
53
99
|
# @return [Boolean]
|
54
100
|
def fixed_parameters?
|
55
|
-
|
101
|
+
parameters_type == :fixed
|
56
102
|
end
|
57
103
|
|
58
104
|
# @return [Boolean]
|
59
105
|
def hash_parameters?
|
60
|
-
|
106
|
+
parameters_type == :hash
|
61
107
|
end
|
62
108
|
|
63
109
|
# @return [Array<ComplexType>]
|
@@ -80,12 +126,52 @@ module Solargraph
|
|
80
126
|
end.call
|
81
127
|
end
|
82
128
|
|
83
|
-
# @return [
|
129
|
+
# @return [String]
|
130
|
+
def rooted_namespace
|
131
|
+
return namespace unless rooted?
|
132
|
+
"::#{namespace}"
|
133
|
+
end
|
134
|
+
|
135
|
+
# @return [String]
|
136
|
+
def rooted_name
|
137
|
+
return name unless rooted?
|
138
|
+
"::#{name}"
|
139
|
+
end
|
140
|
+
|
141
|
+
# @return [String]
|
142
|
+
def substring
|
143
|
+
@substring ||= generate_substring_from(&:tags)
|
144
|
+
end
|
145
|
+
|
146
|
+
# @return [String]
|
147
|
+
def rooted_substring
|
148
|
+
@rooted_substring = generate_substring_from(&:rooted_tags)
|
149
|
+
end
|
150
|
+
|
151
|
+
# @return [String]
|
152
|
+
def generate_substring_from(&to_str)
|
153
|
+
key_types_str = key_types.map(&to_str).join(', ')
|
154
|
+
subtypes_str = subtypes.map(&to_str).join(', ')
|
155
|
+
if key_types.none?(&:defined?) && subtypes.none?(&:defined?)
|
156
|
+
''
|
157
|
+
elsif key_types.empty? && subtypes.empty?
|
158
|
+
''
|
159
|
+
elsif hash_parameters?
|
160
|
+
"{#{key_types_str} => #{subtypes_str}}"
|
161
|
+
elsif fixed_parameters?
|
162
|
+
"(#{subtypes_str})"
|
163
|
+
else
|
164
|
+
"<#{subtypes_str}>"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# @return [::Symbol] :class or :instance
|
84
169
|
def scope
|
85
170
|
@scope ||= :instance if duck_type? || nil_type?
|
86
171
|
@scope ||= (name == 'Class' || name == 'Module') && !subtypes.empty? ? :class : :instance
|
87
172
|
end
|
88
173
|
|
174
|
+
# @param other [Object]
|
89
175
|
def == other
|
90
176
|
return false unless self.class == other.class
|
91
177
|
tag == other.tag
|
@@ -99,32 +185,27 @@ module Solargraph
|
|
99
185
|
#
|
100
186
|
# @param api_map [ApiMap] The ApiMap that performs qualification
|
101
187
|
# @param context [String] The namespace from which to resolve names
|
102
|
-
# @return [ComplexType] The generated ComplexType
|
188
|
+
# @return [self, ComplexType, UniqueType] The generated ComplexType
|
103
189
|
def qualify api_map, context = ''
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
t.
|
114
|
-
end
|
115
|
-
rtypes = value_types.map do |t|
|
116
|
-
t.qualify api_map, context
|
117
|
-
end
|
118
|
-
if list_parameters?
|
119
|
-
Solargraph::ComplexType.parse("#{fqns}<#{rtypes.map(&:tag).join(', ')}>")
|
120
|
-
elsif fixed_parameters?
|
121
|
-
Solargraph::ComplexType.parse("#{fqns}(#{rtypes.map(&:tag).join(', ')})")
|
122
|
-
elsif hash_parameters?
|
123
|
-
Solargraph::ComplexType.parse("#{fqns}{#{ltypes.map(&:tag).join(', ')} => #{rtypes.map(&:tag).join(', ')}}")
|
124
|
-
else
|
125
|
-
Solargraph::ComplexType.parse(fqns)
|
190
|
+
transform do |t|
|
191
|
+
next t if t.name == GENERIC_TAG_NAME
|
192
|
+
next t if t.duck_type? || t.void? || t.undefined?
|
193
|
+
recon = (t.rooted? ? '' : context)
|
194
|
+
fqns = api_map.qualify(t.name, recon)
|
195
|
+
if fqns.nil?
|
196
|
+
next UniqueType::BOOLEAN if t.tag == 'Boolean'
|
197
|
+
next UniqueType::UNDEFINED
|
198
|
+
end
|
199
|
+
t.recreate(new_name: fqns, make_rooted: true)
|
126
200
|
end
|
127
201
|
end
|
202
|
+
|
203
|
+
# @yieldparam [UniqueType]
|
204
|
+
# @return [Enumerator<UniqueType>]
|
205
|
+
def each_unique_type &block
|
206
|
+
return enum_for(__method__) unless block_given?
|
207
|
+
yield self
|
208
|
+
end
|
128
209
|
end
|
129
210
|
end
|
130
211
|
end
|
@@ -8,6 +8,8 @@ module Solargraph
|
|
8
8
|
class UniqueType
|
9
9
|
include TypeMethods
|
10
10
|
|
11
|
+
attr_reader :all_params, :subtypes, :key_types
|
12
|
+
|
11
13
|
# Create a UniqueType with the specified name and an optional substring.
|
12
14
|
# The substring is the parameter section of a parametrized type, e.g.,
|
13
15
|
# for the type `Array<String>`, the name is `Array` and the substring is
|
@@ -15,52 +17,278 @@ module Solargraph
|
|
15
17
|
#
|
16
18
|
# @param name [String] The name of the type
|
17
19
|
# @param substring [String] The substring of the type
|
18
|
-
|
20
|
+
# @param make_rooted [Boolean, nil]
|
21
|
+
# @return [UniqueType]
|
22
|
+
def self.parse name, substring = '', make_rooted: nil
|
23
|
+
if name.start_with?(':::')
|
24
|
+
raise "Illegal prefix: #{name}"
|
25
|
+
end
|
19
26
|
if name.start_with?('::')
|
20
|
-
|
21
|
-
|
27
|
+
name = name[2..-1]
|
28
|
+
rooted = true
|
22
29
|
else
|
23
|
-
|
24
|
-
@rooted = false
|
30
|
+
rooted = false
|
25
31
|
end
|
26
|
-
|
27
|
-
|
28
|
-
@
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
rooted = make_rooted unless make_rooted.nil?
|
33
|
+
|
34
|
+
# @type [Array<ComplexType>]
|
35
|
+
key_types = []
|
36
|
+
# @type [Array<ComplexType>]
|
37
|
+
subtypes = []
|
38
|
+
parameters_type = nil
|
39
|
+
unless substring.empty?
|
34
40
|
subs = ComplexType.parse(substring[1..-2], partial: true)
|
41
|
+
parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
|
42
|
+
if parameters_type == :hash
|
43
|
+
raise ComplexTypeError, "Bad hash type" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
|
44
|
+
# @todo should be able to resolve map; both types have it
|
45
|
+
# with same return type
|
46
|
+
# @sg-ignore
|
47
|
+
key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
|
48
|
+
# @sg-ignore
|
49
|
+
subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
|
50
|
+
else
|
51
|
+
subtypes.concat subs
|
52
|
+
end
|
35
53
|
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
54
|
+
new(name, key_types, subtypes, rooted: rooted, parameters_type: parameters_type)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param name [String]
|
58
|
+
# @param key_types [Array<ComplexType>]
|
59
|
+
# @param subtypes [Array<ComplexType>]
|
60
|
+
# @param rooted [Boolean]
|
61
|
+
# @param parameters_type [Symbol, nil]
|
62
|
+
def initialize(name, key_types = [], subtypes = [], rooted:, parameters_type: nil)
|
63
|
+
if parameters_type.nil?
|
64
|
+
raise "You must supply parameters_type if you provide parameters" unless key_types.empty? && subtypes.empty?
|
42
65
|
end
|
66
|
+
raise "Please remove leading :: and set rooted instead - #{name}" if name.start_with?('::')
|
67
|
+
@name = name
|
68
|
+
@key_types = key_types
|
69
|
+
@subtypes = subtypes
|
70
|
+
@rooted = rooted
|
71
|
+
@all_params = []
|
72
|
+
@all_params.concat key_types
|
73
|
+
@all_params.concat subtypes
|
74
|
+
@parameters_type = parameters_type
|
43
75
|
end
|
44
76
|
|
45
77
|
def to_s
|
46
78
|
tag
|
47
79
|
end
|
48
80
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
81
|
+
# @return [Array<UniqueType>]
|
82
|
+
def items
|
83
|
+
[self]
|
84
|
+
end
|
85
|
+
|
86
|
+
# @return [String]
|
87
|
+
def rbs_name
|
88
|
+
if name == 'undefined'
|
89
|
+
'untyped'
|
90
|
+
else
|
91
|
+
rooted_name
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [String]
|
96
|
+
def to_rbs
|
97
|
+
if duck_type?
|
98
|
+
'untyped'
|
99
|
+
elsif name == 'Boolean'
|
100
|
+
'bool'
|
101
|
+
elsif name.downcase == 'nil'
|
102
|
+
'nil'
|
103
|
+
elsif name == GENERIC_TAG_NAME
|
104
|
+
all_params.first.name
|
105
|
+
elsif ['Class', 'Module'].include?(name)
|
106
|
+
rbs_name
|
107
|
+
elsif ['Tuple', 'Array'].include?(name) && fixed_parameters?
|
108
|
+
# tuples don't have a name; they're just [foo, bar, baz].
|
109
|
+
if substring == '()'
|
110
|
+
# but there are no zero element tuples, so we go with an array
|
111
|
+
'Array[]'
|
112
|
+
else
|
113
|
+
# already generated surrounded by []
|
114
|
+
parameters_as_rbs
|
115
|
+
end
|
116
|
+
else
|
117
|
+
"#{rbs_name}#{parameters_as_rbs}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Boolean]
|
122
|
+
def parameters?
|
123
|
+
!all_params.empty?
|
124
|
+
end
|
125
|
+
|
126
|
+
# @param types [Array<UniqueType, ComplexType>]
|
127
|
+
# @return [String]
|
128
|
+
def rbs_union(types)
|
129
|
+
if types.length == 1
|
130
|
+
types.first.to_rbs
|
131
|
+
else
|
132
|
+
"(#{types.map(&:to_rbs).join(' | ')})"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# @return [String]
|
137
|
+
def parameters_as_rbs
|
138
|
+
return '' unless parameters?
|
139
|
+
|
140
|
+
return "[#{all_params.map(&:to_rbs).join(', ')}]" if key_types.empty?
|
141
|
+
|
142
|
+
# handle, e.g., Hash[K, V] case
|
143
|
+
key_types_str = rbs_union(key_types)
|
144
|
+
subtypes_str = rbs_union(subtypes)
|
145
|
+
"[#{key_types_str}, #{subtypes_str}]"
|
146
|
+
end
|
147
|
+
|
148
|
+
def generic?
|
149
|
+
name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
|
150
|
+
end
|
151
|
+
|
152
|
+
# @param generics_to_resolve [Enumerable<String>]
|
153
|
+
# @param context_type [UniqueType, nil]
|
154
|
+
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
155
|
+
# @return [UniqueType, ComplexType]
|
156
|
+
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
157
|
+
if name == ComplexType::GENERIC_TAG_NAME
|
158
|
+
type_param = subtypes.first&.name
|
159
|
+
return self unless generics_to_resolve.include? type_param
|
160
|
+
unless context_type.nil? || !resolved_generic_values[type_param].nil?
|
161
|
+
new_binding = true
|
162
|
+
resolved_generic_values[type_param] = context_type
|
163
|
+
end
|
164
|
+
if new_binding
|
165
|
+
resolved_generic_values.transform_values! do |complex_type|
|
166
|
+
complex_type.resolve_generics_from_context(generics_to_resolve, nil, resolved_generic_values: resolved_generic_values)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
return resolved_generic_values[type_param] || self
|
170
|
+
end
|
171
|
+
|
172
|
+
# @todo typechecking should complain when the method being called has no @yieldparam tag
|
173
|
+
new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:key_types)
|
174
|
+
new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:subtypes)
|
175
|
+
recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
|
176
|
+
end
|
177
|
+
|
178
|
+
# @param generics_to_resolve [Enumerable<String>]
|
179
|
+
# @param context_type [UniqueType]
|
180
|
+
# @param resolved_generic_values [Hash{String => ComplexType}]
|
181
|
+
# @yieldreturn [Array<ComplexType>]
|
182
|
+
# @return [Array<ComplexType>]
|
183
|
+
def resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values)
|
184
|
+
types = yield self
|
185
|
+
types.each_with_index.flat_map do |ct, i|
|
186
|
+
ct.items.flat_map do |ut|
|
187
|
+
context_params = yield context_type if context_type
|
188
|
+
if context_params && context_params[i]
|
189
|
+
type_arg = context_params[i]
|
190
|
+
type_arg.map do |new_unique_context_type|
|
191
|
+
ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type, resolved_generic_values: resolved_generic_values
|
192
|
+
end
|
193
|
+
else
|
194
|
+
ut.resolve_generics_from_context generics_to_resolve, nil, resolved_generic_values: resolved_generic_values
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Probe the concrete type for each of the generic type
|
201
|
+
# parameters used in this type, and return a new type if
|
202
|
+
# possible.
|
203
|
+
#
|
204
|
+
# @param definitions [Pin::Namespace, Pin::Method] The module/class/method which uses generic types
|
205
|
+
# @param context_type [ComplexType] The receiver type
|
206
|
+
# @return [UniqueType, ComplexType]
|
207
|
+
def resolve_generics definitions, context_type
|
208
|
+
return self if definitions.nil? || definitions.generics.empty?
|
209
|
+
|
210
|
+
transform(name) do |t|
|
211
|
+
if t.name == GENERIC_TAG_NAME
|
212
|
+
idx = definitions.generics.index(t.subtypes.first&.name)
|
213
|
+
next t if idx.nil?
|
214
|
+
context_type.all_params[idx] || ComplexType::UNDEFINED
|
59
215
|
else
|
60
|
-
|
216
|
+
t
|
61
217
|
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# @yieldparam t [self]
|
222
|
+
# @yieldreturn [self]
|
223
|
+
# @return [Array<self>]
|
224
|
+
def map &block
|
225
|
+
[block.yield(self)]
|
226
|
+
end
|
227
|
+
|
228
|
+
# @return [Array<UniqueType>]
|
229
|
+
def to_a
|
230
|
+
[self]
|
231
|
+
end
|
232
|
+
|
233
|
+
# @param new_name [String, nil]
|
234
|
+
# @param make_rooted [Boolean, nil]
|
235
|
+
# @param new_key_types [Array<UniqueType>, nil]
|
236
|
+
# @param rooted [Boolean, nil]
|
237
|
+
# @param new_subtypes [Array<UniqueType>, nil]
|
238
|
+
# @return [self]
|
239
|
+
def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
|
240
|
+
raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
|
241
|
+
new_name ||= name
|
242
|
+
new_key_types ||= @key_types
|
243
|
+
new_subtypes ||= @subtypes
|
244
|
+
make_rooted = @rooted if make_rooted.nil?
|
245
|
+
UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
|
246
|
+
end
|
247
|
+
|
248
|
+
# @return [String]
|
249
|
+
def rooted_tags
|
250
|
+
rooted_tag
|
251
|
+
end
|
252
|
+
|
253
|
+
# @return [String]
|
254
|
+
def tags
|
255
|
+
tag
|
256
|
+
end
|
257
|
+
|
258
|
+
# @return [self]
|
259
|
+
def force_rooted
|
260
|
+
transform do |t|
|
261
|
+
t.recreate(make_rooted: true)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# Apply the given transformation to each subtype and then finally to this type
|
266
|
+
#
|
267
|
+
# @param new_name [String, nil]
|
268
|
+
# @yieldparam t [UniqueType]
|
269
|
+
# @yieldreturn [self]
|
270
|
+
# @return [self]
|
271
|
+
def transform(new_name = nil, &transform_type)
|
272
|
+
raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
|
273
|
+
if name == ComplexType::GENERIC_TAG_NAME
|
274
|
+
# doesn't make sense to manipulate the name of the generic
|
275
|
+
new_key_types = @key_types
|
276
|
+
new_subtypes = @subtypes
|
62
277
|
else
|
63
|
-
|
278
|
+
new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
279
|
+
new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
|
280
|
+
end
|
281
|
+
new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes)
|
282
|
+
yield new_type
|
283
|
+
end
|
284
|
+
|
285
|
+
# Transform references to the 'self' type to the specified concrete namespace
|
286
|
+
# @param dst [String]
|
287
|
+
# @return [UniqueType]
|
288
|
+
def self_to dst
|
289
|
+
transform do |t|
|
290
|
+
next t if t.name != 'self'
|
291
|
+
t.recreate(new_name: dst, new_key_types: [], new_subtypes: [])
|
64
292
|
end
|
65
293
|
end
|
66
294
|
|
@@ -68,8 +296,8 @@ module Solargraph
|
|
68
296
|
@name == 'self' || @key_types.any?(&:selfy?) || @subtypes.any?(&:selfy?)
|
69
297
|
end
|
70
298
|
|
71
|
-
UNDEFINED = UniqueType.new('undefined')
|
72
|
-
BOOLEAN = UniqueType.new('Boolean')
|
299
|
+
UNDEFINED = UniqueType.new('undefined', rooted: false)
|
300
|
+
BOOLEAN = UniqueType.new('Boolean', rooted: true)
|
73
301
|
end
|
74
302
|
end
|
75
303
|
end
|