solargraph 0.47.2 → 0.53.3
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 +137 -3
- data/LICENSE +1 -1
- data/README.md +19 -16
- data/SPONSORS.md +2 -9
- data/lib/solargraph/api_map/cache.rb +60 -20
- data/lib/solargraph/api_map/source_to_yard.rb +17 -10
- data/lib/solargraph/api_map/store.rb +60 -12
- data/lib/solargraph/api_map.rb +171 -99
- data/lib/solargraph/bench.rb +3 -2
- data/lib/solargraph/cache.rb +77 -0
- data/lib/solargraph/complex_type/type_methods.rb +61 -12
- data/lib/solargraph/complex_type/unique_type.rb +193 -16
- data/lib/solargraph/complex_type.rb +113 -10
- 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 +171 -0
- data/lib/solargraph/gem_pins.rb +64 -0
- data/lib/solargraph/language_server/host/cataloger.rb +2 -1
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +15 -5
- data/lib/solargraph/language_server/host/message_worker.rb +4 -0
- data/lib/solargraph/language_server/host/sources.rb +7 -4
- data/lib/solargraph/language_server/host.rb +50 -26
- 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 +13 -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 +4 -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/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/library.rb +124 -37
- 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 +9 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -5
- 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 +499 -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/{legacy → 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/{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 +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -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 +8 -4
- data/lib/solargraph/pin/block.rb +21 -28
- 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 +97 -0
- data/lib/solargraph/pin/documenting.rb +25 -34
- data/lib/solargraph/pin/instance_variable.rb +4 -0
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +270 -16
- data/lib/solargraph/pin/namespace.rb +17 -1
- data/lib/solargraph/pin/parameter.rb +52 -17
- 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 +601 -0
- data/lib/solargraph/rbs_map/core_fills.rb +47 -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 +84 -0
- data/lib/solargraph/shell.rb +69 -48
- 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 +44 -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.rb +18 -19
- data/lib/solargraph/source_map/clip.rb +30 -23
- data/lib/solargraph/source_map/mapper.rb +20 -5
- data/lib/solargraph/source_map.rb +28 -13
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +201 -98
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace/config.rb +14 -11
- data/lib/solargraph/workspace.rb +28 -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 +18 -5
- 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 +162 -98
- 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/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/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/cvasgn_node.rb +0 -23
- 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
@@ -2,9 +2,23 @@
|
|
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
|
|
@@ -24,8 +38,7 @@ module Solargraph
|
|
24
38
|
|
25
39
|
# @return [Boolean]
|
26
40
|
def nil_type?
|
27
|
-
@nil_type
|
28
|
-
@nil_type
|
41
|
+
@nil_type ||= (name.casecmp('nil') == 0)
|
29
42
|
end
|
30
43
|
|
31
44
|
# @return [Boolean]
|
@@ -45,6 +58,22 @@ module Solargraph
|
|
45
58
|
name == 'undefined'
|
46
59
|
end
|
47
60
|
|
61
|
+
# @param generics_to_erase [Enumerable<String>]
|
62
|
+
# @return [self]
|
63
|
+
def erase_generics(generics_to_erase)
|
64
|
+
transform do |type|
|
65
|
+
if type.name == ComplexType::GENERIC_TAG_NAME
|
66
|
+
if type.all_params.length == 1 && generics_to_erase.include?(type.all_params.first.to_s)
|
67
|
+
ComplexType::UNDEFINED
|
68
|
+
else
|
69
|
+
type
|
70
|
+
end
|
71
|
+
else
|
72
|
+
type
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
48
77
|
# @return [Boolean]
|
49
78
|
def list_parameters?
|
50
79
|
substring.start_with?('<')
|
@@ -80,12 +109,25 @@ module Solargraph
|
|
80
109
|
end.call
|
81
110
|
end
|
82
111
|
|
83
|
-
# @return [
|
112
|
+
# @return [String]
|
113
|
+
def rooted_namespace
|
114
|
+
return namespace unless rooted?
|
115
|
+
"::#{namespace}"
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [String]
|
119
|
+
def rooted_name
|
120
|
+
return name unless rooted?
|
121
|
+
"::#{name}"
|
122
|
+
end
|
123
|
+
|
124
|
+
# @return [::Symbol] :class or :instance
|
84
125
|
def scope
|
85
126
|
@scope ||= :instance if duck_type? || nil_type?
|
86
127
|
@scope ||= (name == 'Class' || name == 'Module') && !subtypes.empty? ? :class : :instance
|
87
128
|
end
|
88
129
|
|
130
|
+
# @param other [Object]
|
89
131
|
def == other
|
90
132
|
return false unless self.class == other.class
|
91
133
|
tag == other.tag
|
@@ -99,8 +141,9 @@ module Solargraph
|
|
99
141
|
#
|
100
142
|
# @param api_map [ApiMap] The ApiMap that performs qualification
|
101
143
|
# @param context [String] The namespace from which to resolve names
|
102
|
-
# @return [ComplexType] The generated ComplexType
|
144
|
+
# @return [self, ComplexType, UniqueType] The generated ComplexType
|
103
145
|
def qualify api_map, context = ''
|
146
|
+
return self if name == GENERIC_TAG_NAME
|
104
147
|
return ComplexType.new([self]) if duck_type? || void? || undefined?
|
105
148
|
recon = (rooted? ? '' : context)
|
106
149
|
fqns = api_map.qualify(name, recon)
|
@@ -109,22 +152,28 @@ module Solargraph
|
|
109
152
|
return UniqueType::UNDEFINED
|
110
153
|
end
|
111
154
|
fqns = "::#{fqns}" # Ensure the resulting complex type is rooted
|
112
|
-
|
113
|
-
|
114
|
-
end
|
115
|
-
rtypes = value_types.map do |t|
|
116
|
-
t.qualify api_map, context
|
117
|
-
end
|
155
|
+
all_ltypes = key_types.map { |t| t.qualify api_map, context }.uniq
|
156
|
+
all_rtypes = value_types.map { |t| t.qualify api_map, context }
|
118
157
|
if list_parameters?
|
158
|
+
rtypes = all_rtypes.uniq
|
119
159
|
Solargraph::ComplexType.parse("#{fqns}<#{rtypes.map(&:tag).join(', ')}>")
|
120
160
|
elsif fixed_parameters?
|
121
|
-
Solargraph::ComplexType.parse("#{fqns}(#{
|
161
|
+
Solargraph::ComplexType.parse("#{fqns}(#{all_rtypes.map(&:tag).join(', ')})")
|
122
162
|
elsif hash_parameters?
|
163
|
+
ltypes = all_ltypes.uniq
|
164
|
+
rtypes = all_rtypes.uniq
|
123
165
|
Solargraph::ComplexType.parse("#{fqns}{#{ltypes.map(&:tag).join(', ')} => #{rtypes.map(&:tag).join(', ')}}")
|
124
166
|
else
|
125
167
|
Solargraph::ComplexType.parse(fqns)
|
126
168
|
end
|
127
169
|
end
|
170
|
+
|
171
|
+
# @yieldparam [UniqueType]
|
172
|
+
# @return [Enumerator<UniqueType>]
|
173
|
+
def each_unique_type &block
|
174
|
+
return enum_for(__method__) unless block_given?
|
175
|
+
yield self
|
176
|
+
end
|
128
177
|
end
|
129
178
|
end
|
130
179
|
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
|
@@ -25,42 +27,217 @@ module Solargraph
|
|
25
27
|
end
|
26
28
|
@substring = substring
|
27
29
|
@tag = @name + substring
|
30
|
+
# @type [Array<ComplexType>]
|
28
31
|
@key_types = []
|
32
|
+
# @type [Array<ComplexType>]
|
29
33
|
@subtypes = []
|
34
|
+
# @type [Array<ComplexType>]
|
35
|
+
@all_params = []
|
30
36
|
return unless parameters?
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
37
|
+
# @todo we should be able to probe the type of 'subs' without
|
38
|
+
# hoisting the definition outside of the if statement
|
39
|
+
subs = if @substring.start_with?('<(') && @substring.end_with?(')>')
|
40
|
+
ComplexType.parse(substring[2..-3], partial: true)
|
41
|
+
else
|
42
|
+
ComplexType.parse(substring[1..-2], partial: true)
|
43
|
+
end
|
36
44
|
if hash_parameters?
|
37
45
|
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)
|
46
|
+
# @todo should be able to resolve map; both types have it
|
47
|
+
# with same return type
|
48
|
+
# @sg-ignore
|
38
49
|
@key_types.concat subs[0].map { |u| ComplexType.new([u]) }
|
50
|
+
# @sg-ignore
|
39
51
|
@subtypes.concat subs[1].map { |u| ComplexType.new([u]) }
|
40
52
|
else
|
41
53
|
@subtypes.concat subs
|
42
54
|
end
|
55
|
+
@all_params.concat @key_types
|
56
|
+
@all_params.concat @subtypes
|
43
57
|
end
|
44
58
|
|
45
59
|
def to_s
|
46
60
|
tag
|
47
61
|
end
|
48
62
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
# @return [Array<UniqueType>]
|
64
|
+
def items
|
65
|
+
[self]
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [String]
|
69
|
+
def rbs_name
|
70
|
+
if name == 'undefined'
|
71
|
+
'untyped'
|
72
|
+
else
|
73
|
+
rooted_name
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String]
|
78
|
+
def to_rbs
|
79
|
+
if ['Tuple', 'Array'].include?(name) && fixed_parameters?
|
80
|
+
# tuples don't have a name; they're just [foo, bar, baz].
|
81
|
+
if substring == '()'
|
82
|
+
# but there are no zero element tuples, so we go with an array
|
83
|
+
'Array[]'
|
59
84
|
else
|
60
|
-
|
85
|
+
# already generated surrounded by []
|
86
|
+
parameters_as_rbs
|
61
87
|
end
|
62
88
|
else
|
89
|
+
"#{rbs_name}#{parameters_as_rbs}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [String]
|
94
|
+
def parameters_as_rbs
|
95
|
+
parameters? ? "[#{all_params.map { |s| s.to_rbs }.join(', ')}]" : ''
|
96
|
+
end
|
97
|
+
|
98
|
+
def generic?
|
99
|
+
name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
# @param generics_to_resolve [Enumerable<String>]
|
104
|
+
# @param context_type [UniqueType, nil]
|
105
|
+
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
106
|
+
# @return [UniqueType, ComplexType]
|
107
|
+
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
108
|
+
if name == ComplexType::GENERIC_TAG_NAME
|
109
|
+
type_param = subtypes.first&.name
|
110
|
+
return self unless generics_to_resolve.include? type_param
|
111
|
+
unless context_type.nil? || !resolved_generic_values[type_param].nil?
|
112
|
+
new_binding = true
|
113
|
+
resolved_generic_values[type_param] = context_type
|
114
|
+
end
|
115
|
+
if new_binding
|
116
|
+
resolved_generic_values.transform_values! do |complex_type|
|
117
|
+
complex_type.resolve_generics_from_context(generics_to_resolve, nil, resolved_generic_values: resolved_generic_values)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return resolved_generic_values[type_param] || self
|
121
|
+
end
|
122
|
+
|
123
|
+
# @todo typechecking should complain when the method being called has no @yieldparam tag
|
124
|
+
new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:key_types)
|
125
|
+
new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:subtypes)
|
126
|
+
recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
|
127
|
+
end
|
128
|
+
|
129
|
+
# @param generics_to_resolve [Enumerable<String>]
|
130
|
+
# @param context_type [UniqueType]
|
131
|
+
# @param resolved_generic_values [Hash{String => ComplexType}]
|
132
|
+
# @yieldreturn [Array<ComplexType>]
|
133
|
+
# @return [Array<ComplexType>]
|
134
|
+
def resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values)
|
135
|
+
types = yield self
|
136
|
+
types.each_with_index.flat_map do |ct, i|
|
137
|
+
ct.items.flat_map do |ut|
|
138
|
+
context_params = yield context_type if context_type
|
139
|
+
if context_params && context_params[i]
|
140
|
+
type_arg = context_params[i]
|
141
|
+
type_arg.map do |new_unique_context_type|
|
142
|
+
ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type, resolved_generic_values: resolved_generic_values
|
143
|
+
end
|
144
|
+
else
|
145
|
+
ut.resolve_generics_from_context generics_to_resolve, nil, resolved_generic_values: resolved_generic_values
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Probe the concrete type for each of the generic type
|
152
|
+
# parameters used in this type, and return a new type if
|
153
|
+
# possible.
|
154
|
+
#
|
155
|
+
# @param definitions [Pin::Namespace, Pin::Method] The module/class/method which uses generic types
|
156
|
+
# @param context_type [ComplexType] The receiver type
|
157
|
+
# @return [UniqueType, ComplexType]
|
158
|
+
def resolve_generics definitions, context_type
|
159
|
+
return self if definitions.nil? || definitions.generics.empty?
|
160
|
+
|
161
|
+
transform(name) do |t|
|
162
|
+
if t.name == GENERIC_TAG_NAME
|
163
|
+
idx = definitions.generics.index(t.subtypes.first&.name)
|
164
|
+
next t if idx.nil?
|
165
|
+
context_type.all_params[idx] || ComplexType::UNDEFINED
|
166
|
+
else
|
167
|
+
t
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# @yieldparam t [self]
|
173
|
+
# @yieldreturn [self]
|
174
|
+
# @return [Array<self>]
|
175
|
+
def map &block
|
176
|
+
[block.yield(self)]
|
177
|
+
end
|
178
|
+
|
179
|
+
# @return [Array<UniqueType>]
|
180
|
+
def to_a
|
181
|
+
[self]
|
182
|
+
end
|
183
|
+
|
184
|
+
# @param new_name [String, nil]
|
185
|
+
# @param new_key_types [Array<UniqueType>, nil]
|
186
|
+
# @param new_subtypes [Array<UniqueType>, nil]
|
187
|
+
# @return [self]
|
188
|
+
def recreate(new_name: nil, new_key_types: nil, new_subtypes: nil)
|
189
|
+
new_name ||= name
|
190
|
+
new_key_types ||= @key_types
|
191
|
+
new_subtypes ||= @subtypes
|
192
|
+
if new_key_types.none?(&:defined?) && new_subtypes.none?(&:defined?)
|
193
|
+
# if all subtypes are undefined, erase down to the non-parametric type
|
194
|
+
UniqueType.new(new_name)
|
195
|
+
elsif new_key_types.empty? && new_subtypes.empty?
|
63
196
|
UniqueType.new(new_name)
|
197
|
+
elsif hash_parameters?
|
198
|
+
UniqueType.new(new_name, "{#{new_key_types.join(', ')} => #{new_subtypes.join(', ')}}")
|
199
|
+
elsif @substring.start_with?('<(')
|
200
|
+
# @todo This clause is probably wrong, and if so, fixing it
|
201
|
+
# will be some level of breaking change. Probably best
|
202
|
+
# handled before real tuple support is rolled out and
|
203
|
+
# folks start relying on it more.
|
204
|
+
#
|
205
|
+
# (String) is a one element tuple in https://yardoc.org/types
|
206
|
+
# <String> is an array of zero or more Strings in https://yardoc.org/types
|
207
|
+
# Array<(String)> could be an Array of one-element tuples or a
|
208
|
+
# one element tuple. https://yardoc.org/types treats it
|
209
|
+
# as the former.
|
210
|
+
# Array<(String), Integer> is not ambiguous if we accept
|
211
|
+
# (String) as a tuple type, but not currently understood
|
212
|
+
# by Solargraph.
|
213
|
+
UniqueType.new(new_name, "<(#{new_subtypes.join(', ')})>")
|
214
|
+
elsif fixed_parameters?
|
215
|
+
UniqueType.new(new_name, "(#{new_subtypes.join(', ')})")
|
216
|
+
else
|
217
|
+
UniqueType.new(new_name, "<#{new_subtypes.join(', ')}>")
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Apply the given transformation to each subtype and then finally to this type
|
222
|
+
#
|
223
|
+
# @param new_name [String, nil]
|
224
|
+
# @yieldparam t [UniqueType]
|
225
|
+
# @yieldreturn [self]
|
226
|
+
# @return [self]
|
227
|
+
def transform(new_name = nil, &transform_type)
|
228
|
+
new_key_types = @key_types.flat_map { |ct| ct.map { |ut| ut.transform(&transform_type) } }.compact
|
229
|
+
new_subtypes = @subtypes.flat_map { |ct| ct.map { |ut| ut.transform(&transform_type) } }.compact
|
230
|
+
new_type = recreate(new_name: new_name || rooted_name, new_key_types: new_key_types, new_subtypes: new_subtypes)
|
231
|
+
yield new_type
|
232
|
+
end
|
233
|
+
|
234
|
+
# Transform references to the 'self' type to the specified concrete namespace
|
235
|
+
# @param dst [String]
|
236
|
+
# @return [UniqueType]
|
237
|
+
def self_to dst
|
238
|
+
transform do |t|
|
239
|
+
next t if t.name != 'self'
|
240
|
+
t.recreate(new_name: dst, new_key_types: [], new_subtypes: [])
|
64
241
|
end
|
65
242
|
end
|
66
243
|
|
@@ -4,64 +4,120 @@ module Solargraph
|
|
4
4
|
# A container for type data based on YARD type tags.
|
5
5
|
#
|
6
6
|
class ComplexType
|
7
|
+
GENERIC_TAG_NAME = 'generic'.freeze
|
7
8
|
# @!parse
|
8
9
|
# include TypeMethods
|
9
10
|
|
10
11
|
autoload :TypeMethods, 'solargraph/complex_type/type_methods'
|
11
12
|
autoload :UniqueType, 'solargraph/complex_type/unique_type'
|
12
13
|
|
13
|
-
# @param types [Array<UniqueType>]
|
14
|
+
# @param types [Array<[UniqueType, ComplexType]>]
|
14
15
|
def initialize types = [UniqueType::UNDEFINED]
|
15
|
-
@items
|
16
|
+
# @todo @items here should not need an annotation
|
17
|
+
# @type [Array<UniqueType>]
|
18
|
+
@items = types.flat_map(&:items).uniq(&:to_s)
|
16
19
|
end
|
17
20
|
|
18
21
|
# @param api_map [ApiMap]
|
19
22
|
# @param context [String]
|
20
23
|
# @return [ComplexType]
|
21
24
|
def qualify api_map, context = ''
|
22
|
-
|
25
|
+
red = reduce_object
|
26
|
+
types = red.items.map do |t|
|
23
27
|
next t if ['Boolean', 'nil', 'void', 'undefined'].include?(t.name)
|
24
28
|
t.qualify api_map, context
|
25
29
|
end
|
26
|
-
ComplexType.new(types)
|
30
|
+
ComplexType.new(types).reduce_object
|
27
31
|
end
|
28
32
|
|
33
|
+
# @param generics_to_resolve [Enumerable<String>]]
|
34
|
+
# @param context_type [UniqueType, nil]
|
35
|
+
# @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
|
36
|
+
# @return [self]
|
37
|
+
def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
|
38
|
+
return self unless generic?
|
39
|
+
|
40
|
+
ComplexType.new(@items.map { |i| i.resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: resolved_generic_values) })
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [UniqueType]
|
29
44
|
def first
|
30
45
|
@items.first
|
31
46
|
end
|
32
47
|
|
48
|
+
# @return [String]
|
49
|
+
def to_rbs
|
50
|
+
((@items.length > 1 ? '(' : '') +
|
51
|
+
@items.map(&:to_rbs).join(' | ') +
|
52
|
+
(@items.length > 1 ? ')' : ''))
|
53
|
+
end
|
54
|
+
|
55
|
+
# @yieldparam [UniqueType]
|
56
|
+
# @return [Array]
|
33
57
|
def map &block
|
34
58
|
@items.map &block
|
35
59
|
end
|
36
60
|
|
37
61
|
# @yieldparam [UniqueType]
|
38
|
-
# @return [
|
62
|
+
# @return [Enumerable<UniqueType>]
|
39
63
|
def each &block
|
40
64
|
@items.each &block
|
41
65
|
end
|
42
66
|
|
67
|
+
# @yieldparam [UniqueType]
|
68
|
+
# @return [void]
|
69
|
+
# @overload each_unique_type()
|
70
|
+
# @return [Enumerator<UniqueType>]
|
71
|
+
def each_unique_type &block
|
72
|
+
return enum_for(__method__) unless block_given?
|
73
|
+
|
74
|
+
@items.each do |item|
|
75
|
+
item.each_unique_type &block
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [Integer]
|
43
80
|
def length
|
44
81
|
@items.length
|
45
82
|
end
|
46
83
|
|
84
|
+
# @return [Array<UniqueType>]
|
85
|
+
def to_a
|
86
|
+
@items
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param index [Integer]
|
90
|
+
# @return [UniqueType]
|
47
91
|
def [](index)
|
48
92
|
@items[index]
|
49
93
|
end
|
50
94
|
|
95
|
+
# @return [Array<UniqueType>]
|
51
96
|
def select &block
|
52
97
|
@items.select &block
|
53
98
|
end
|
99
|
+
|
100
|
+
# @return [String]
|
54
101
|
def namespace
|
55
102
|
# cache this attr for high frequency call
|
56
103
|
@namespace ||= method_missing(:namespace).to_s
|
57
104
|
end
|
58
105
|
|
106
|
+
# @return [Array<String>]
|
107
|
+
def namespaces
|
108
|
+
@items.map(&:namespace)
|
109
|
+
end
|
110
|
+
|
111
|
+
# @param name [Symbol]
|
112
|
+
# @return [Object, nil]
|
59
113
|
def method_missing name, *args, &block
|
60
114
|
return if @items.first.nil?
|
61
115
|
return @items.first.send(name, *args, &block) if respond_to_missing?(name)
|
62
116
|
super
|
63
117
|
end
|
64
118
|
|
119
|
+
# @param name [Symbol]
|
120
|
+
# @param include_private [Boolean]
|
65
121
|
def respond_to_missing?(name, include_private = false)
|
66
122
|
TypeMethods.public_instance_methods.include?(name) || super
|
67
123
|
end
|
@@ -75,13 +131,33 @@ module Solargraph
|
|
75
131
|
end
|
76
132
|
|
77
133
|
def any? &block
|
78
|
-
@items.any? &block
|
134
|
+
@items.compact.any? &block
|
79
135
|
end
|
80
136
|
|
81
137
|
def selfy?
|
82
138
|
@items.any?(&:selfy?)
|
83
139
|
end
|
84
140
|
|
141
|
+
def generic?
|
142
|
+
any?(&:generic?)
|
143
|
+
end
|
144
|
+
|
145
|
+
# @param new_name [String, nil]
|
146
|
+
# @yieldparam t [UniqueType]
|
147
|
+
# @yieldreturn [UniqueType]
|
148
|
+
# @return [ComplexType]
|
149
|
+
def transform(new_name = nil, &transform_type)
|
150
|
+
ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
|
151
|
+
end
|
152
|
+
|
153
|
+
# @param definitions [Pin::Namespace, Pin::Method]
|
154
|
+
# @param context_type [ComplexType]
|
155
|
+
# @return [ComplexType]
|
156
|
+
def resolve_generics definitions, context_type
|
157
|
+
result = @items.map { |i| i.resolve_generics(definitions, context_type) }
|
158
|
+
ComplexType.parse(*result.map(&:tag))
|
159
|
+
end
|
160
|
+
|
85
161
|
# @param dst [String]
|
86
162
|
# @return [ComplexType]
|
87
163
|
def self_to dst
|
@@ -95,6 +171,25 @@ module Solargraph
|
|
95
171
|
@items.any?(&:nil_type?)
|
96
172
|
end
|
97
173
|
|
174
|
+
# @return [Array<ComplexType>]
|
175
|
+
def all_params
|
176
|
+
@items.first.all_params || []
|
177
|
+
end
|
178
|
+
|
179
|
+
attr_reader :items
|
180
|
+
|
181
|
+
protected
|
182
|
+
|
183
|
+
# @return [ComplexType]
|
184
|
+
def reduce_object
|
185
|
+
return self if name != 'Object' || subtypes.empty?
|
186
|
+
ComplexType.try_parse(reduce_class(subtypes.join(', ')))
|
187
|
+
end
|
188
|
+
|
189
|
+
def bottom?
|
190
|
+
@items.all?(&:bot?)
|
191
|
+
end
|
192
|
+
|
98
193
|
private
|
99
194
|
|
100
195
|
# @todo This is a quick and dirty hack that forces `self` keywords
|
@@ -124,9 +219,13 @@ module Solargraph
|
|
124
219
|
# used internally.
|
125
220
|
#
|
126
221
|
# @param *strings [Array<String>] The type definitions to parse
|
127
|
-
# @
|
128
|
-
# @
|
222
|
+
# @return [ComplexType]
|
223
|
+
# @overload parse(*strings, partial: false)
|
224
|
+
# @todo Need ability to use a literal true as a type below
|
225
|
+
# @param partial [Boolean] True if the string is part of a another type
|
226
|
+
# @return [Array<UniqueType>]
|
129
227
|
def parse *strings, partial: false
|
228
|
+
# @type [Hash{Array<String> => ComplexType}]
|
130
229
|
@cache ||= {}
|
131
230
|
unless partial
|
132
231
|
cached = @cache[strings]
|
@@ -140,7 +239,7 @@ module Solargraph
|
|
140
239
|
paren_stack = 0
|
141
240
|
base = String.new
|
142
241
|
subtype_string = String.new
|
143
|
-
type_string
|
242
|
+
type_string&.each_char do |char|
|
144
243
|
if char == '='
|
145
244
|
#raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
|
146
245
|
elsif char == '<'
|
@@ -152,6 +251,9 @@ module Solargraph
|
|
152
251
|
raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
|
153
252
|
# types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
|
154
253
|
types.push UniqueType.new(base[0..-2].strip)
|
254
|
+
# @todo this should either expand key_type's type
|
255
|
+
# automatically or complain about not being
|
256
|
+
# compatible with key_type's type in type checking
|
155
257
|
key_types = types
|
156
258
|
types = []
|
157
259
|
base.clear
|
@@ -174,7 +276,7 @@ module Solargraph
|
|
174
276
|
paren_stack += 1
|
175
277
|
elsif char == ')'
|
176
278
|
paren_stack -= 1
|
177
|
-
subtype_string += char
|
279
|
+
subtype_string += char
|
178
280
|
raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
|
179
281
|
next
|
180
282
|
elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
|
@@ -221,5 +323,6 @@ module Solargraph
|
|
221
323
|
NIL = ComplexType.parse('nil')
|
222
324
|
SELF = ComplexType.parse('self')
|
223
325
|
BOOLEAN = ComplexType.parse('Boolean')
|
326
|
+
BOT = ComplexType.parse('bot')
|
224
327
|
end
|
225
328
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
module Convention
|
5
|
+
class Rakefile < Base
|
6
|
+
def local source_map
|
7
|
+
basename = File.basename(source_map.filename)
|
8
|
+
return EMPTY_ENVIRON unless basename.end_with?('.rake') || basename == 'Rakefile'
|
9
|
+
|
10
|
+
@environ ||= Environ.new(
|
11
|
+
requires: ['rake'],
|
12
|
+
domains: ['Rake::DSL']
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'set'
|
4
3
|
|
5
4
|
module Solargraph
|
6
5
|
# Conventions provide a way to modify an ApiMap based on expectations about
|
@@ -9,8 +8,8 @@ module Solargraph
|
|
9
8
|
module Convention
|
10
9
|
autoload :Base, 'solargraph/convention/base'
|
11
10
|
autoload :Gemfile, 'solargraph/convention/gemfile'
|
12
|
-
autoload :Rspec, 'solargraph/convention/rspec'
|
13
11
|
autoload :Gemspec, 'solargraph/convention/gemspec'
|
12
|
+
autoload :Rakefile, 'solargraph/convention/rakefile'
|
14
13
|
|
15
14
|
@@conventions = Set.new
|
16
15
|
|
@@ -42,6 +41,6 @@ module Solargraph
|
|
42
41
|
|
43
42
|
register Gemfile
|
44
43
|
register Gemspec
|
45
|
-
register
|
44
|
+
register Rakefile
|
46
45
|
end
|
47
46
|
end
|
@@ -1,6 +1,11 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
1
3
|
module ReverseMarkdown
|
2
4
|
module Converters
|
3
5
|
class Dd < Base
|
6
|
+
# @return [String]
|
7
|
+
# @param node [Nokogiri::XML::Element]
|
8
|
+
# @param state [Hash]
|
4
9
|
def convert node, state = {}
|
5
10
|
content = treat_children(node, state)
|
6
11
|
": #{content.strip}\n"
|