rbs 1.7.1 → 2.0.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +104 -3
- data/core/array.rbs +3 -3
- data/core/builtin.rbs +4 -0
- data/core/enumerable.rbs +3 -3
- data/docs/collection.md +23 -1
- data/docs/syntax.md +117 -61
- data/ext/rbs_extension/constants.c +2 -6
- data/ext/rbs_extension/constants.h +1 -2
- data/ext/rbs_extension/parser.c +220 -184
- data/ext/rbs_extension/parserstate.c +6 -2
- data/ext/rbs_extension/parserstate.h +10 -0
- data/ext/rbs_extension/ruby_objs.c +17 -17
- data/ext/rbs_extension/ruby_objs.h +3 -4
- data/lib/rbs/ast/declarations.rb +6 -99
- data/lib/rbs/ast/type_param.rb +134 -0
- data/lib/rbs/cli.rb +33 -5
- data/lib/rbs/collection/config/lockfile_generator.rb +26 -18
- data/lib/rbs/collection/sources/git.rb +18 -7
- data/lib/rbs/collection/sources/rubygems.rb +7 -0
- data/lib/rbs/collection/sources/stdlib.rb +6 -0
- data/lib/rbs/definition.rb +9 -0
- data/lib/rbs/definition_builder.rb +78 -16
- data/lib/rbs/environment.rb +32 -8
- data/lib/rbs/environment_loader.rb +0 -2
- data/lib/rbs/environment_walker.rb +4 -1
- data/lib/rbs/errors.rb +31 -6
- data/lib/rbs/location_aux.rb +2 -0
- data/lib/rbs/method_type.rb +29 -6
- data/lib/rbs/prototype/rb.rb +3 -3
- data/lib/rbs/prototype/rbi.rb +8 -6
- data/lib/rbs/prototype/runtime.rb +4 -4
- data/lib/rbs/type_alias_regularity.rb +115 -0
- data/lib/rbs/types.rb +99 -22
- data/lib/rbs/validator.rb +99 -15
- data/lib/rbs/variance_calculator.rb +60 -31
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +2 -14
- data/lib/rbs.rb +2 -0
- data/schema/decls.json +19 -46
- data/schema/methodType.json +1 -1
- data/schema/typeParam.json +36 -0
- data/schema/types.json +8 -2
- data/sig/collection/collections.rbs +11 -2
- data/sig/collection/config.rbs +2 -2
- data/sig/declarations.rbs +15 -62
- data/sig/definition.rbs +11 -1
- data/sig/definition_builder.rbs +37 -1
- data/sig/environment.rbs +7 -1
- data/sig/environment_walker.rbs +26 -0
- data/sig/errors.rbs +28 -3
- data/sig/location.rbs +3 -1
- data/sig/locator.rbs +1 -1
- data/sig/method_types.rbs +25 -4
- data/sig/type_alias_regularity.rbs +92 -0
- data/sig/type_param.rbs +74 -0
- data/sig/types.rbs +37 -8
- data/sig/validator.rbs +38 -2
- data/sig/variance_calculator.rbs +50 -0
- data/sig/writer.rbs +1 -1
- data/stdlib/bigdecimal-math/0/manifest.yaml +2 -0
- data/stdlib/csv/0/manifest.yaml +2 -0
- data/stdlib/date/0/date.rbs +2 -2
- data/stdlib/logger/0/manifest.yaml +2 -0
- data/stdlib/net-http/0/manifest.yaml +2 -0
- data/stdlib/openssl/0/manifest.yaml +2 -0
- data/stdlib/prime/0/manifest.yaml +2 -0
- data/stdlib/resolv/0/manifest.yaml +3 -0
- data/stdlib/set/0/set.rbs +3 -3
- data/stdlib/uri/0/common.rbs +10 -5
- data/stdlib/uri/0/ftp.rbs +10 -0
- data/stdlib/uri/0/generic.rbs +34 -34
- data/stdlib/uri/0/mailto.rbs +5 -0
- data/stdlib/uri/0/ws.rbs +10 -0
- data/stdlib/uri/0/wss.rbs +7 -0
- data/stdlib/yaml/0/manifest.yaml +3 -0
- data/steep/Gemfile.lock +10 -10
- metadata +21 -4
data/sig/declarations.rbs
CHANGED
@@ -6,56 +6,6 @@ module RBS
|
|
6
6
|
class Base
|
7
7
|
end
|
8
8
|
|
9
|
-
type variance = :invariant | :covariant | :contravariant
|
10
|
-
|
11
|
-
class ModuleTypeParams
|
12
|
-
class TypeParam
|
13
|
-
# Key
|
14
|
-
# ^^^ name
|
15
|
-
#
|
16
|
-
# unchecked out Elem
|
17
|
-
# ^^^^^^^^^ unchecked
|
18
|
-
# ^^^ variance
|
19
|
-
# ^^^^ name
|
20
|
-
type loc = Location[:name, :variance | :unchecked]
|
21
|
-
|
22
|
-
attr_reader name: Symbol
|
23
|
-
attr_reader variance: variance
|
24
|
-
attr_reader skip_validation: bool
|
25
|
-
attr_reader location: loc?
|
26
|
-
|
27
|
-
def initialize: (name: Symbol, variance: variance, skip_validation: boolish, location: loc?) -> void
|
28
|
-
|
29
|
-
include _ToJson
|
30
|
-
end
|
31
|
-
|
32
|
-
attr_reader params: Array[TypeParam]
|
33
|
-
|
34
|
-
def initialize: () -> void
|
35
|
-
|
36
|
-
def add: (TypeParam param) -> self
|
37
|
-
|
38
|
-
include _HashEqual
|
39
|
-
include _ToJson
|
40
|
-
|
41
|
-
def []: (Symbol) -> TypeParam?
|
42
|
-
|
43
|
-
def each: { (TypeParam) -> void } -> void
|
44
|
-
| () -> Enumerator[TypeParam, void]
|
45
|
-
|
46
|
-
def self.empty: () -> instance
|
47
|
-
|
48
|
-
def variance: (Symbol) -> variance
|
49
|
-
|
50
|
-
def skip_validation?: (Symbol) -> bool
|
51
|
-
|
52
|
-
def empty?: () -> bool
|
53
|
-
|
54
|
-
def size: () -> Integer
|
55
|
-
|
56
|
-
def rename_to: (Array[Symbol] names) -> ModuleTypeParams
|
57
|
-
end
|
58
|
-
|
59
9
|
interface _WithMember
|
60
10
|
def members: () -> Array[untyped]
|
61
11
|
end
|
@@ -118,14 +68,14 @@ module RBS
|
|
118
68
|
include MixinHelper
|
119
69
|
|
120
70
|
attr_reader name: TypeName
|
121
|
-
attr_reader type_params:
|
71
|
+
attr_reader type_params: Array[TypeParam]
|
122
72
|
attr_reader members: Array[member]
|
123
73
|
attr_reader super_class: Super?
|
124
74
|
attr_reader annotations: Array[Annotation]
|
125
75
|
attr_reader location: loc?
|
126
76
|
attr_reader comment: Comment?
|
127
77
|
|
128
|
-
def initialize: (name: TypeName, type_params:
|
78
|
+
def initialize: (name: TypeName, type_params: Array[TypeParam], members: Array[member], super_class: Super?, annotations: Array[Annotation], location: loc?, comment: Comment?) -> void
|
129
79
|
|
130
80
|
include _HashEqual
|
131
81
|
include _ToJson
|
@@ -172,14 +122,14 @@ module RBS
|
|
172
122
|
include MixinHelper
|
173
123
|
|
174
124
|
attr_reader name: TypeName
|
175
|
-
attr_reader type_params:
|
125
|
+
attr_reader type_params: Array[TypeParam]
|
176
126
|
attr_reader members: Array[member]
|
177
127
|
attr_reader location: loc?
|
178
128
|
attr_reader annotations: Array[Annotation]
|
179
129
|
attr_reader self_types: Array[Self]
|
180
130
|
attr_reader comment: Comment?
|
181
131
|
|
182
|
-
def initialize: (name: TypeName, type_params:
|
132
|
+
def initialize: (name: TypeName, type_params: Array[TypeParam], members: Array[member], location: loc?, annotations: Array[Annotation], self_types: Array[Self], comment: Comment?) -> void
|
183
133
|
|
184
134
|
include _HashEqual
|
185
135
|
include _ToJson
|
@@ -202,13 +152,13 @@ module RBS
|
|
202
152
|
type loc = Location[:name | :keyword | :end, :type_params]
|
203
153
|
|
204
154
|
attr_reader name: TypeName
|
205
|
-
attr_reader type_params:
|
155
|
+
attr_reader type_params: Array[TypeParam]
|
206
156
|
attr_reader members: Array[member]
|
207
157
|
attr_reader annotations: Array[Annotation]
|
208
158
|
attr_reader location: loc?
|
209
159
|
attr_reader comment: Comment?
|
210
160
|
|
211
|
-
def initialize: (name: TypeName, type_params:
|
161
|
+
def initialize: (name: TypeName, type_params: Array[TypeParam], members: Array[member], annotations: Array[Annotation], location: loc?, comment: Comment?) -> void
|
212
162
|
|
213
163
|
include MixinHelper
|
214
164
|
|
@@ -217,19 +167,22 @@ module RBS
|
|
217
167
|
end
|
218
168
|
|
219
169
|
class Alias < Base
|
220
|
-
# type loc = Location
|
221
|
-
# ^^^^
|
222
|
-
# ^^^
|
223
|
-
#
|
224
|
-
|
170
|
+
# type loc[T] = Location[T, bot]
|
171
|
+
# ^^^^ keyword
|
172
|
+
# ^^^ name
|
173
|
+
# ^^^ type_params
|
174
|
+
# ^ eq
|
175
|
+
#
|
176
|
+
type loc = Location[:keyword | :name | :eq, :type_params]
|
225
177
|
|
226
178
|
attr_reader name: TypeName
|
179
|
+
attr_reader type_params: Array[TypeParam]
|
227
180
|
attr_reader type: Types::t
|
228
181
|
attr_reader annotations: Array[Annotation]
|
229
182
|
attr_reader location: loc?
|
230
183
|
attr_reader comment: Comment?
|
231
184
|
|
232
|
-
def initialize: (name: TypeName, type: Types::t, annotations: Array[Annotation], location: loc?, comment: Comment?) -> void
|
185
|
+
def initialize: (name: TypeName, type_params: Array[TypeParam], type: Types::t, annotations: Array[Annotation], location: loc?, comment: Comment?) -> void
|
233
186
|
|
234
187
|
include _HashEqual
|
235
188
|
include _ToJson
|
data/sig/definition.rbs
CHANGED
@@ -54,10 +54,20 @@ module RBS
|
|
54
54
|
|
55
55
|
def private?: () -> bool
|
56
56
|
|
57
|
+
# Substitutes type variables to some types.
|
58
|
+
# Takes care of type parameter bounds.
|
59
|
+
#
|
57
60
|
def sub: (Substitution) -> Method
|
58
61
|
|
62
|
+
# Applies the mapping from `Types::t` to `Types::t`.
|
63
|
+
#
|
64
|
+
# Note this method doesn't handle upper bound in type params.
|
65
|
+
# You may want to use `#map_type_bound` explicitly, or `#sub` for simple substitution.
|
66
|
+
#
|
59
67
|
def map_type: () { (Types::t) -> Types::t } -> Method
|
60
68
|
|
69
|
+
def map_type_bound: () { (AST::TypeParam::bound) -> AST::TypeParam::bound } -> Method
|
70
|
+
|
61
71
|
def map_method_type: () { (MethodType) -> MethodType } -> Method
|
62
72
|
end
|
63
73
|
|
@@ -127,7 +137,7 @@ module RBS
|
|
127
137
|
|
128
138
|
def type_params: () -> Array[Symbol]
|
129
139
|
|
130
|
-
def type_params_decl: () -> AST::
|
140
|
+
def type_params_decl: () -> Array[AST::TypeParam]
|
131
141
|
|
132
142
|
def sub: (Substitution) -> Definition
|
133
143
|
|
data/sig/definition_builder.rbs
CHANGED
@@ -33,7 +33,7 @@ module RBS
|
|
33
33
|
def try_cache: (TypeName, cache: Hash[TypeName, Definition | false | nil]) { () -> Definition } -> Definition
|
34
34
|
| [A] (TypeName, cache: Hash[A, Definition | false | nil], key: A) { () -> Definition } -> Definition
|
35
35
|
|
36
|
-
def validate_params_with: (AST::
|
36
|
+
def validate_params_with: (Array[AST::TypeParam], result: VarianceCalculator::Result) { (AST::TypeParam) -> void } -> void
|
37
37
|
|
38
38
|
def validate_type_params: (Definition, ancestors: AncestorBuilder::OneAncestors, methods: MethodBuilder::Methods) -> void
|
39
39
|
|
@@ -43,8 +43,44 @@ module RBS
|
|
43
43
|
|
44
44
|
def define_methods: (Definition, interface_methods: Hash[Symbol, Definition::Method], methods: MethodBuilder::Methods, super_interface_method: bool) -> void
|
45
45
|
|
46
|
+
# Validates presence of type names recursively.
|
47
|
+
# Assumes the type names are already resolved.
|
48
|
+
#
|
49
|
+
def validate_type_presence: (Types::t) -> void
|
50
|
+
|
51
|
+
def validate_type_name: (TypeName, Location[untyped, untyped]?) -> void
|
52
|
+
|
53
|
+
# Expand a type alias of given name without type arguments.
|
54
|
+
# Raises an error if the type alias requires arguments.
|
55
|
+
#
|
56
|
+
# Assume `type foo[T] = [T, T]`:
|
57
|
+
#
|
58
|
+
# ```
|
59
|
+
# expand_alias("::foo") # => error
|
60
|
+
# ```
|
61
|
+
#
|
46
62
|
def expand_alias: (TypeName) -> Types::t
|
47
63
|
|
64
|
+
# Expand a type alias of given name with arguments of `untyped`.
|
65
|
+
#
|
66
|
+
# Assume `type foo[T] = [T, T]`:
|
67
|
+
#
|
68
|
+
# ```
|
69
|
+
# expand_alias1("::foo") # => [untyped, untyped]
|
70
|
+
# ```
|
71
|
+
#
|
72
|
+
def expand_alias1: (TypeName) -> Types::t
|
73
|
+
|
74
|
+
# Expand a type alias of given name with `args`.
|
75
|
+
#
|
76
|
+
# Assume `type foo[T] = [T, T]`:
|
77
|
+
#
|
78
|
+
# ```
|
79
|
+
# expand_alias2("::foo", ["::Integer"]) # => [::Integer, ::Integer]
|
80
|
+
# ```
|
81
|
+
#
|
82
|
+
def expand_alias2: (TypeName, Array[Types::t] args) -> Types::t
|
83
|
+
|
48
84
|
def update: (env: Environment, ancestor_builder: AncestorBuilder, except: _Each[TypeName]) -> DefinitionBuilder
|
49
85
|
end
|
50
86
|
end
|
data/sig/environment.rbs
CHANGED
@@ -31,7 +31,9 @@ module RBS
|
|
31
31
|
|
32
32
|
def validate_type_params: () -> void
|
33
33
|
|
34
|
-
def
|
34
|
+
def compatible_params?: (Array[AST::TypeParam], Array[AST::TypeParam]) -> boolish
|
35
|
+
|
36
|
+
def type_params: () -> Array[AST::TypeParam]
|
35
37
|
|
36
38
|
def primary: () -> D[module_decl]
|
37
39
|
end
|
@@ -96,6 +98,10 @@ module RBS
|
|
96
98
|
|
97
99
|
def resolve_member: (TypeNameResolver, AST::Members::t, context: Array[Namespace]) -> AST::Members::t
|
98
100
|
|
101
|
+
def resolve_method_type: (TypeNameResolver, RBS::MethodType, context: Array[Namespace]) -> RBS::MethodType
|
102
|
+
|
103
|
+
def resolve_type_params: (TypeNameResolver resolver, Array[AST::TypeParam], context: Array[Namespace]) -> Array[AST::TypeParam]
|
104
|
+
|
99
105
|
def absolute_type: (TypeNameResolver, Types::t, context: Array[Namespace]) -> Types::t
|
100
106
|
|
101
107
|
def absolute_type_name: (TypeNameResolver, TypeName, context: Array[Namespace]) -> TypeName
|
data/sig/environment_walker.rbs
CHANGED
@@ -1,4 +1,28 @@
|
|
1
1
|
module RBS
|
2
|
+
# EnvironmentWalker provides topological sort of class/module definitions.
|
3
|
+
#
|
4
|
+
# If a method, attribute, or ancestor in a class definition have a reference to another class, it is dependency.
|
5
|
+
#
|
6
|
+
# ```rb
|
7
|
+
# walker = EnvironmentWalker.new(env: env)
|
8
|
+
#
|
9
|
+
# walker.each_strongly_connected_component do |scc|
|
10
|
+
# # Yields an array of strongly connected components.
|
11
|
+
# end
|
12
|
+
# ```
|
13
|
+
#
|
14
|
+
# The `#only_ancestors!` method limits the dependency only to ancestors.
|
15
|
+
# Only super classes and included modules are dependencies with the option.
|
16
|
+
# This is useful to calculate the dependencies of class hierarchy.
|
17
|
+
#
|
18
|
+
# ```rb
|
19
|
+
# walker = EnvironmentWalker.new(env: env).only_ancestors!
|
20
|
+
#
|
21
|
+
# walker.each_strongly_connected_component do |scc|
|
22
|
+
# # Yields an array of strongly connected components.
|
23
|
+
# end
|
24
|
+
# ```
|
25
|
+
#
|
2
26
|
class EnvironmentWalker
|
3
27
|
class InstanceNode
|
4
28
|
attr_reader type_name: TypeName
|
@@ -32,6 +56,8 @@ module RBS
|
|
32
56
|
|
33
57
|
def tsort_each_child: (node) { (node) -> void } -> void
|
34
58
|
|
59
|
+
private
|
60
|
+
|
35
61
|
def each_type_name: (Types::t) { (TypeName) -> void } -> void
|
36
62
|
|
37
63
|
def each_type_node: (Types::t) { (node) -> void } -> void
|
data/sig/errors.rbs
CHANGED
@@ -179,10 +179,10 @@ module RBS
|
|
179
179
|
|
180
180
|
class InvalidVarianceAnnotationError < DefinitionError
|
181
181
|
attr_reader type_name: TypeName
|
182
|
-
attr_reader param: AST::
|
182
|
+
attr_reader param: AST::TypeParam
|
183
183
|
attr_reader location: Location[untyped, untyped]?
|
184
184
|
|
185
|
-
def initialize: (type_name: TypeName, param: AST::
|
185
|
+
def initialize: (type_name: TypeName, param: AST::TypeParam, location: Location[untyped, untyped]?) -> void
|
186
186
|
end
|
187
187
|
|
188
188
|
class RecursiveAliasDefinitionError < DefinitionError
|
@@ -212,7 +212,7 @@ module RBS
|
|
212
212
|
def mixin_name: () -> String
|
213
213
|
end
|
214
214
|
|
215
|
-
class RecursiveTypeAliasError <
|
215
|
+
class RecursiveTypeAliasError < BaseError
|
216
216
|
attr_reader alias_names: Array[TypeName]
|
217
217
|
attr_reader location: Location[untyped, untyped]?
|
218
218
|
|
@@ -220,4 +220,29 @@ module RBS
|
|
220
220
|
|
221
221
|
def name: () -> String
|
222
222
|
end
|
223
|
+
|
224
|
+
class NonregularTypeAliasError < BaseError
|
225
|
+
# Diagnostic reported from `TypeAliasRegularity`.
|
226
|
+
attr_reader diagnostic: TypeAliasRegularity::Diagnostic
|
227
|
+
|
228
|
+
# Location of the definition.
|
229
|
+
attr_reader location: Location[untyped, untyped]?
|
230
|
+
|
231
|
+
def initialize: (diagnostic: TypeAliasRegularity::Diagnostic, location: Location[untyped, untyped]?) -> void
|
232
|
+
end
|
233
|
+
|
234
|
+
class CyclicTypeParameterBound < BaseError
|
235
|
+
attr_reader location: Location[untyped, untyped]?
|
236
|
+
|
237
|
+
# Array of parameters which contains cyclic dependencies.
|
238
|
+
attr_reader params: Array[AST::TypeParam]
|
239
|
+
|
240
|
+
# Type name
|
241
|
+
attr_reader type_name: TypeName
|
242
|
+
|
243
|
+
# Method name
|
244
|
+
attr_reader method_name: Symbol?
|
245
|
+
|
246
|
+
def initialize: (type_name: TypeName, method_name: Symbol?, params: Array[AST::TypeParam], location: Location[untyped, untyped]?) -> void
|
247
|
+
end
|
223
248
|
end
|
data/sig/location.rbs
CHANGED
@@ -8,7 +8,7 @@ module RBS
|
|
8
8
|
#
|
9
9
|
# ```
|
10
10
|
#
|
11
|
-
class Location[RequiredChildKeys, OptionalChildKeys]
|
11
|
+
class Location[in RequiredChildKeys, in OptionalChildKeys]
|
12
12
|
# The buffer this location points on.
|
13
13
|
attr_reader buffer (): Buffer
|
14
14
|
|
@@ -79,6 +79,8 @@ module RBS
|
|
79
79
|
| (OptionalChildKeys) -> Location[bot, bot]?
|
80
80
|
| (Symbol) -> Location[bot, bot]?
|
81
81
|
|
82
|
+
alias aref []
|
83
|
+
|
82
84
|
def each_optional_key: () { (Symbol) -> void } -> void
|
83
85
|
| () -> Enumerator[Symbol, void]
|
84
86
|
|
data/sig/locator.rbs
CHANGED
data/sig/method_types.rbs
CHANGED
@@ -1,27 +1,48 @@
|
|
1
1
|
module RBS
|
2
2
|
class MethodType
|
3
|
-
|
3
|
+
# () -> void
|
4
|
+
# ^^^^^^^^^^ type
|
5
|
+
#
|
6
|
+
# [A] () { () -> A } -> A
|
7
|
+
# ^^^ type_params
|
8
|
+
# ^^^^^^^^^^^^^^^^^^^ type
|
9
|
+
#
|
10
|
+
type loc = Location[:type, :type_params]
|
11
|
+
|
12
|
+
attr_reader type_params: Array[AST::TypeParam]
|
4
13
|
attr_reader type: Types::Function
|
5
14
|
attr_reader block: Types::Block?
|
6
|
-
attr_reader location:
|
15
|
+
attr_reader location: loc?
|
7
16
|
|
8
|
-
def initialize: (type_params: Array[
|
17
|
+
def initialize: (type_params: Array[AST::TypeParam], type: Types::Function, block: Types::Block?, location: loc?) -> void
|
9
18
|
|
10
19
|
def ==: (untyped other) -> bool
|
11
20
|
|
12
21
|
include _ToJson
|
13
22
|
|
23
|
+
# Substitute type variables to some types.
|
24
|
+
# Takes care of type parameter bounds.
|
25
|
+
#
|
14
26
|
def sub: (Substitution) -> MethodType
|
15
27
|
|
16
|
-
def update: (?type_params: Array[
|
28
|
+
def update: (?type_params: Array[AST::TypeParam], ?type: Types::Function, ?block: Types::Block?, ?location: loc?) -> MethodType
|
17
29
|
|
18
30
|
def free_variables: (?Set[Symbol] set) -> Set[Symbol]
|
19
31
|
|
32
|
+
# Apply the mapping included in the MethodType.
|
33
|
+
#
|
34
|
+
# Note that type bound in generics parameter is not handled by this method.
|
35
|
+
# You may want to use `#map_type_bound` explicitly, or `#sub` for simple substitution.
|
36
|
+
#
|
20
37
|
def map_type: () { (Types::t) -> Types::t } -> MethodType
|
21
38
|
|
39
|
+
def map_type_bound: () { (AST::TypeParam::bound) -> AST::TypeParam::bound } -> MethodType
|
40
|
+
|
22
41
|
def each_type: () { (Types::t) -> void } -> void
|
23
42
|
| () -> Enumerator[Types::t, void]
|
24
43
|
|
25
44
|
def to_s: () -> String
|
45
|
+
|
46
|
+
def type_param_names: () -> Array[Symbol]
|
26
47
|
end
|
27
48
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module RBS
|
2
|
+
# `TypeAliasRegularity` validates if a type alias is regular or not.
|
3
|
+
#
|
4
|
+
# Generic and recursive type alias cannot be polymorphic in their definitions.
|
5
|
+
#
|
6
|
+
# ```rbs
|
7
|
+
# type foo[T] = Integer
|
8
|
+
# | foo[T]? # Allowed. The type argument of `foo` doesn't change.
|
9
|
+
#
|
10
|
+
# type bar[T] = Integer
|
11
|
+
# | foo[T]
|
12
|
+
# | foo[Array[T]] # Allowed. There are two type arguments `T` and `Array[T]` of `foo`, but it's not definition of `foo`.
|
13
|
+
#
|
14
|
+
# type baz[T] = Integer
|
15
|
+
# | baz[Array[T]] # Error. Recursive definition of `baz` has different type argument from the definition.
|
16
|
+
# ```
|
17
|
+
#
|
18
|
+
# The `#nonregular?` method can be used to test if given type name is regular or not.
|
19
|
+
#
|
20
|
+
# ```rb
|
21
|
+
# validator = RBS::TypeAliasRegularity.validate(env: env)
|
22
|
+
#
|
23
|
+
# validator.nonregular?(TypeName("::foo")) # => nil
|
24
|
+
# validator.nonregular?(TypeName("::bar")) # => nil
|
25
|
+
# validator.nonregular?(TypeName("::baz")) # => TypeAliasRegularity::Diagnostic
|
26
|
+
# ```
|
27
|
+
#
|
28
|
+
# A special case is when the type argument is `untyped`.
|
29
|
+
#
|
30
|
+
# ```rbs
|
31
|
+
# type foo[T] = Integer | foo[untyped] # This is allowed.
|
32
|
+
# ```
|
33
|
+
#
|
34
|
+
class TypeAliasRegularity
|
35
|
+
attr_reader env: Environment
|
36
|
+
|
37
|
+
attr_reader builder: DefinitionBuilder
|
38
|
+
|
39
|
+
attr_reader diagnostics: Hash[TypeName, Diagnostic]
|
40
|
+
|
41
|
+
# `Diagnostic` represents an non-regular type alias declaration error.
|
42
|
+
# It consists of the name of the alias type and a type on which the nonregularity is detected.
|
43
|
+
#
|
44
|
+
# ```rbs
|
45
|
+
# type t[T] = Integer | t[T?]
|
46
|
+
# ```
|
47
|
+
#
|
48
|
+
# The type `t` is nonregular because it contains `t[T?]` on it's right hand side.
|
49
|
+
#
|
50
|
+
# ```
|
51
|
+
# diagnostic = validator.nonregular?(TypeName("::t"))
|
52
|
+
# diagnostic.type_name # => TypeName("::t")
|
53
|
+
# diagnostic.nonregular_type # => t[T?]
|
54
|
+
# ```
|
55
|
+
#
|
56
|
+
class Diagnostic
|
57
|
+
attr_reader type_name: TypeName
|
58
|
+
|
59
|
+
attr_reader nonregular_type: Types::Alias
|
60
|
+
|
61
|
+
def initialize: (type_name: TypeName, nonregular_type: Types::Alias) -> void
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns new instance which already run `#validate`.
|
65
|
+
#
|
66
|
+
def self.validate: (env: Environment) -> TypeAliasRegularity
|
67
|
+
|
68
|
+
def initialize: (env: Environment) -> void
|
69
|
+
|
70
|
+
# Returns `Diagnostic` instance if the alias type is nonregular.
|
71
|
+
# Regurns `nil` if the alias type is regular.
|
72
|
+
#
|
73
|
+
def nonregular?: (TypeName) -> Diagnostic?
|
74
|
+
|
75
|
+
def validate: () -> void
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def validate_alias_type: (Types::Alias, Set[TypeName], Hash[TypeName, Types::Alias]) -> void
|
80
|
+
|
81
|
+
# Returns alias type for given type name, if the alias is generic.
|
82
|
+
# Returns nil if the type alias is not generic.
|
83
|
+
#
|
84
|
+
def build_alias_type: (TypeName) -> Types::Alias?
|
85
|
+
|
86
|
+
def compatible_args?: (Array[Types::t], Array[Types::t]) -> boolish
|
87
|
+
|
88
|
+
def each_alias_type: (Types::t) { (Types::Alias) -> void } -> void
|
89
|
+
|
90
|
+
def each_mutual_alias_defs: () { (Set[TypeName]) -> void } -> void
|
91
|
+
end
|
92
|
+
end
|
data/sig/type_param.rbs
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
module RBS
|
2
|
+
module AST
|
3
|
+
class TypeParam
|
4
|
+
# Key
|
5
|
+
# ^^^ name
|
6
|
+
#
|
7
|
+
# unchecked out Elem < _ToJson
|
8
|
+
# ^^^^^^^^^ unchecked
|
9
|
+
# ^^^ variance
|
10
|
+
# ^^^^ name
|
11
|
+
# ^^^^^^^^^ upper_bound
|
12
|
+
type loc = Location[:name, :variance | :unchecked | :upper_bound]
|
13
|
+
|
14
|
+
type variance = :invariant | :covariant | :contravariant
|
15
|
+
|
16
|
+
type bound = Types::ClassInstance | Types::ClassSingleton | Types::Interface
|
17
|
+
|
18
|
+
attr_reader name: Symbol
|
19
|
+
attr_reader variance: variance
|
20
|
+
attr_reader location: loc?
|
21
|
+
|
22
|
+
attr_reader upper_bound: bound?
|
23
|
+
|
24
|
+
def initialize: (name: Symbol, variance: variance, upper_bound: bound?, location: loc?) -> void
|
25
|
+
|
26
|
+
include _ToJson
|
27
|
+
|
28
|
+
def ==: (untyped) -> bool
|
29
|
+
|
30
|
+
def eql?: (untyped) -> bool
|
31
|
+
|
32
|
+
def hash: () -> Integer
|
33
|
+
|
34
|
+
@unchecked: bool
|
35
|
+
|
36
|
+
def unchecked!: (?boolish) -> self
|
37
|
+
|
38
|
+
def unchecked?: () -> bool
|
39
|
+
|
40
|
+
def map_type: () { (bound) -> bound } -> TypeParam
|
41
|
+
|
42
|
+
# Helper function to resolve _class instance types_ to _type variables_.
|
43
|
+
#
|
44
|
+
# We need this step because RBS language has an identical syntax for both unqualified class instance types and type variables.
|
45
|
+
# `String` may be an instance of `::String` class or type variable depending on the list of bound type variables.
|
46
|
+
#
|
47
|
+
# So, we need second pass to parse the following generics parameter declaration.
|
48
|
+
#
|
49
|
+
# ```rbs
|
50
|
+
# class Foo[X < _Each[Y], Y]
|
51
|
+
# # ^ We want this `Y` to be a type variable.
|
52
|
+
# end
|
53
|
+
# ```
|
54
|
+
#
|
55
|
+
def self.resolve_variables: (Array[TypeParam]) -> void
|
56
|
+
|
57
|
+
def self.subst_var: (Set[Symbol], Types::t) -> Types::t
|
58
|
+
|
59
|
+
# Rename type parameter name.
|
60
|
+
#
|
61
|
+
# The renaming cannot be done separately because a set of `TypeParam` decls may be mutual recursive.
|
62
|
+
#
|
63
|
+
# Example:
|
64
|
+
#
|
65
|
+
# * Renaming `A -> X, B -> Y`
|
66
|
+
# * Input `[A, B < _Pushable[A]]`
|
67
|
+
# * Result `[X, Y < _Pushable[X]]`
|
68
|
+
#
|
69
|
+
def self.rename: (Array[TypeParam], new_names: Array[Symbol]) -> Array[TypeParam]
|
70
|
+
|
71
|
+
def to_s: () -> String
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/sig/types.rbs
CHANGED
@@ -55,6 +55,11 @@ module RBS
|
|
55
55
|
module EmptyEachType
|
56
56
|
def each_type: () { (t) -> void } -> void
|
57
57
|
| () -> Enumerator[t, void]
|
58
|
+
|
59
|
+
# `map_type` returns itself, because there is no sub type.
|
60
|
+
#
|
61
|
+
def map_type: () { (t) -> t } -> self
|
62
|
+
| () -> Enumerator[t, self]
|
58
63
|
end
|
59
64
|
|
60
65
|
module NoTypeName
|
@@ -199,6 +204,9 @@ module RBS
|
|
199
204
|
include _TypeBase
|
200
205
|
|
201
206
|
attr_reader location: loc?
|
207
|
+
|
208
|
+
def map_type: () { (t) -> t } -> Interface
|
209
|
+
| () -> Enumerator[t, Interface]
|
202
210
|
end
|
203
211
|
|
204
212
|
# ClassInstance represents a type of an instance of a class.
|
@@ -224,21 +232,30 @@ module RBS
|
|
224
232
|
attr_reader location: loc?
|
225
233
|
|
226
234
|
include _TypeBase
|
235
|
+
|
236
|
+
def map_type: () { (t) -> t } -> ClassInstance
|
237
|
+
| () -> Enumerator[t, ClassInstance]
|
227
238
|
end
|
228
239
|
|
229
240
|
class Alias
|
230
|
-
|
241
|
+
# foo
|
242
|
+
# ^^^ => name
|
243
|
+
#
|
244
|
+
# foo[bar, baz]
|
245
|
+
# ^^^ => name
|
246
|
+
# ^^^^^^^^^^ => args
|
247
|
+
#
|
248
|
+
type loc = Location[:name, :args]
|
231
249
|
|
232
|
-
|
250
|
+
attr_reader location: loc?
|
233
251
|
|
234
|
-
def initialize: (name: TypeName, location: loc?) -> void
|
252
|
+
def initialize: (name: TypeName, args: Array[t], location: loc?) -> void
|
235
253
|
|
236
254
|
include _TypeBase
|
237
|
-
include
|
238
|
-
include NoSubst
|
239
|
-
include EmptyEachType
|
255
|
+
include Application
|
240
256
|
|
241
|
-
|
257
|
+
def map_type: () { (t) -> t } -> Alias
|
258
|
+
| () -> Enumerator[t, Alias]
|
242
259
|
end
|
243
260
|
|
244
261
|
class Tuple
|
@@ -251,6 +268,9 @@ module RBS
|
|
251
268
|
include _TypeBase
|
252
269
|
|
253
270
|
attr_reader location: loc?
|
271
|
+
|
272
|
+
def map_type: () { (t) -> t } -> Tuple
|
273
|
+
| () -> Enumerator[t, Tuple]
|
254
274
|
end
|
255
275
|
|
256
276
|
class Record
|
@@ -263,6 +283,9 @@ module RBS
|
|
263
283
|
include _TypeBase
|
264
284
|
|
265
285
|
attr_reader location: loc?
|
286
|
+
|
287
|
+
def map_type: () { (t) -> t } -> Record
|
288
|
+
| () -> Enumerator[t, Record]
|
266
289
|
end
|
267
290
|
|
268
291
|
class Optional
|
@@ -275,6 +298,9 @@ module RBS
|
|
275
298
|
include _TypeBase
|
276
299
|
|
277
300
|
attr_reader location: loc?
|
301
|
+
|
302
|
+
def map_type: () { (t) -> t } -> Optional
|
303
|
+
| () -> Enumerator[t, Optional]
|
278
304
|
end
|
279
305
|
|
280
306
|
class Union
|
@@ -392,7 +418,7 @@ module RBS
|
|
392
418
|
|
393
419
|
def sub: (Substitution) -> Block
|
394
420
|
|
395
|
-
def map_type: () { (
|
421
|
+
def map_type: () { (t) -> t } -> Block
|
396
422
|
end
|
397
423
|
|
398
424
|
class Proc
|
@@ -406,6 +432,9 @@ module RBS
|
|
406
432
|
include _TypeBase
|
407
433
|
|
408
434
|
attr_reader location: loc?
|
435
|
+
|
436
|
+
def map_type: () { (t) -> t } -> Proc
|
437
|
+
| () -> Enumerator[t, Proc]
|
409
438
|
end
|
410
439
|
|
411
440
|
class Literal
|