rbs 1.7.0.beta.5 → 1.8.1
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/.gitignore +0 -1
- data/CHANGELOG.md +64 -3
- data/Steepfile +0 -1
- data/core/array.rbs +3 -3
- data/core/builtin.rbs +4 -0
- data/core/enumerable.rbs +3 -3
- data/core/env.rbs +881 -0
- data/core/false_class.rbs +2 -0
- data/core/nil_class.rbs +2 -0
- data/core/symbol.rbs +2 -0
- data/core/thread.rbs +1 -1
- data/core/true_class.rbs +2 -0
- data/docs/syntax.md +23 -20
- data/ext/rbs_extension/parser.c +97 -95
- data/ext/rbs_extension/ruby_objs.c +8 -6
- data/ext/rbs_extension/ruby_objs.h +2 -2
- data/lib/rbs/ast/declarations.rb +6 -2
- data/lib/rbs/cli.rb +1 -1
- data/lib/rbs/collection/sources/git.rb +9 -7
- data/lib/rbs/definition_builder.rb +58 -2
- data/lib/rbs/environment.rb +1 -0
- data/lib/rbs/environment_walker.rb +4 -1
- data/lib/rbs/errors.rb +12 -0
- data/lib/rbs/test/setup.rb +1 -0
- data/lib/rbs/type_alias_regularity.rb +115 -0
- data/lib/rbs/types.rb +11 -23
- data/lib/rbs/validator.rb +44 -15
- data/lib/rbs/variance_calculator.rb +52 -24
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +1 -1
- data/lib/rbs.rb +1 -0
- data/schema/decls.json +13 -1
- data/schema/types.json +8 -2
- data/sig/collection/collections.rbs +4 -2
- data/sig/declarations.rbs +9 -6
- data/sig/definition_builder.rbs +36 -0
- data/sig/environment_walker.rbs +26 -0
- data/sig/errors.rbs +10 -0
- data/sig/type_alias_regularity.rbs +92 -0
- data/sig/types.rbs +11 -8
- data/sig/validator.rbs +7 -0
- data/sig/variance_calculator.rbs +50 -0
- data/stdlib/bigdecimal/0/big_decimal.rbs +44 -0
- data/stdlib/csv/0/csv.rbs +49 -3
- data/stdlib/date/0/date.rbs +2 -2
- data/stdlib/set/0/set.rbs +3 -3
- data/steep/Gemfile.lock +10 -10
- metadata +7 -6
- data/lib/rbs/parser.y +0 -1805
- data/lib/ruby/signature.rb +0 -7
data/core/false_class.rbs
CHANGED
data/core/nil_class.rbs
CHANGED
data/core/symbol.rbs
CHANGED
data/core/thread.rbs
CHANGED
|
@@ -554,7 +554,7 @@ class Thread < Object
|
|
|
554
554
|
# b = Thread.new { raise 'something went wrong' }
|
|
555
555
|
# b.value #=> RuntimeError: something went wrong
|
|
556
556
|
# ```
|
|
557
|
-
def value: () ->
|
|
557
|
+
def value: () -> untyped
|
|
558
558
|
|
|
559
559
|
# Marks a given thread as eligible for scheduling, however it may still
|
|
560
560
|
# remain blocked on I/O.
|
data/core/true_class.rbs
CHANGED
data/docs/syntax.md
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
```markdown
|
|
6
6
|
_type_ ::= _class-name_ _type-arguments_ (Class instance type)
|
|
7
7
|
| _interface-name_ _type-arguments_ (Interface type)
|
|
8
|
+
| _alias-name_ _type-arguments_ (Alias type)
|
|
8
9
|
| `singleton(` _class-name_ `)` (Class singleton type)
|
|
9
|
-
| _alias-name_ (Alias type)
|
|
10
10
|
| _literal_ (Literal type)
|
|
11
11
|
| _type_ `|` _type_ (Union type)
|
|
12
12
|
| _type_ `&` _type_ (Intersection type)
|
|
13
13
|
| _type_ `?` (Optional type)
|
|
14
|
-
| `{` _record-name_ `:` _type_ `,` etc. `}`
|
|
15
|
-
| `[]` | `[` _type_ `,` etc. `]`
|
|
14
|
+
| `{` _record-name_ `:` _type_ `,` etc. `}` (Record type)
|
|
15
|
+
| `[]` | `[` _type_ `,` etc. `]` (Tuples)
|
|
16
16
|
| _type-variable_ (Type variables)
|
|
17
17
|
| `^(` _parameters_ `) ->` _type_ (Proc type)
|
|
18
18
|
| `self`
|
|
@@ -35,8 +35,8 @@ _namespace_ ::= (Empty namespace)
|
|
|
35
35
|
| `::` (Root)
|
|
36
36
|
| _namespace_ /[A-Z]\w*/ `::` (Namespace)
|
|
37
37
|
|
|
38
|
-
_type-arguments_ ::= (No
|
|
39
|
-
| `[` _type_ `,` etc. `]`
|
|
38
|
+
_type-arguments_ ::= (No type arguments)
|
|
39
|
+
| `[` _type_ `,` etc. `]` (Type arguments)
|
|
40
40
|
|
|
41
41
|
_literal_ ::= _string-literal_
|
|
42
42
|
| _symbol-literal_
|
|
@@ -64,25 +64,25 @@ _ToS # _ToS interface
|
|
|
64
64
|
::MyApp::_Each[String] # Interface name with namespace and type application
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
### Class singleton type
|
|
68
|
-
|
|
69
|
-
Class singleton type denotes _the type of a singleton object of a class_.
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
singleton(String)
|
|
73
|
-
singleton(::Hash) # Class singleton type cannot be parametrized.
|
|
74
|
-
```
|
|
75
|
-
|
|
76
67
|
### Alias type
|
|
77
68
|
|
|
78
69
|
Alias type denotes an alias declared with _alias declaration_.
|
|
79
70
|
|
|
80
71
|
The name of type aliases starts with lowercase `[a-z]`.
|
|
81
72
|
|
|
82
|
-
|
|
83
73
|
```
|
|
84
74
|
name
|
|
85
75
|
::JSON::t # Alias name with namespace
|
|
76
|
+
list[Integer] # Type alias can be generic
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Class singleton type
|
|
80
|
+
|
|
81
|
+
Class singleton type denotes _the type of a singleton object of a class_.
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
singleton(String)
|
|
85
|
+
singleton(::Hash) # Class singleton type cannot be parametrized.
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
### Literal type
|
|
@@ -155,7 +155,7 @@ Elem
|
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
Type variables cannot be distinguished from _class instance types_.
|
|
158
|
-
They are scoped in _class/module/interface declaration_ or _generic method types_.
|
|
158
|
+
They are scoped in _class/module/interface/alias declaration_ or _generic method types_.
|
|
159
159
|
|
|
160
160
|
```
|
|
161
161
|
class Ref[T] # Object is scoped in the class declaration.
|
|
@@ -414,7 +414,6 @@ These work only as _statements_, not per-method specifier.
|
|
|
414
414
|
_decl_ ::= _class-decl_ # Class declaration
|
|
415
415
|
| _module-decl_ # Module declaration
|
|
416
416
|
| _interface-decl_ # Interface declaration
|
|
417
|
-
| _extension-decl_ # Extension declaration
|
|
418
417
|
| _type-alias-decl_ # Type alias declaration
|
|
419
418
|
| _const-decl_ # Constant declaration
|
|
420
419
|
| _global-decl_ # Global declaration
|
|
@@ -434,9 +433,7 @@ _interface-members_ ::= _method-member_ # Method
|
|
|
434
433
|
| _include-member_ # Mixin (include)
|
|
435
434
|
| _alias-member_ # Alias
|
|
436
435
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
_type-alias-decl_ ::= `type` _alias-name_ `=` _type_
|
|
436
|
+
_type-alias-decl_ ::= `type` _alias-name_ _module-type-parameters_ `=` _type_
|
|
440
437
|
|
|
441
438
|
_const-decl_ ::= _const-name_ `:` _type_
|
|
442
439
|
|
|
@@ -536,6 +533,12 @@ type subject = Attendee | Speaker
|
|
|
536
533
|
type JSON::t = Integer | TrueClass | FalseClass | String | Hash[Symbol, t] | Array[t]
|
|
537
534
|
```
|
|
538
535
|
|
|
536
|
+
Type alias can be generic like class, module, and interface.
|
|
537
|
+
|
|
538
|
+
```
|
|
539
|
+
type list[out T] = [T, list[T]] | nil
|
|
540
|
+
```
|
|
541
|
+
|
|
539
542
|
### Constant type declaration
|
|
540
543
|
|
|
541
544
|
You can declare a constant.
|
data/ext/rbs_extension/parser.c
CHANGED
|
@@ -273,7 +273,7 @@ static VALUE parse_function_param(parserstate *state) {
|
|
|
273
273
|
param_range.start = type_range.start;
|
|
274
274
|
param_range.end = name_range.end;
|
|
275
275
|
|
|
276
|
-
VALUE name =
|
|
276
|
+
VALUE name = rb_to_symbol(rbs_unquote_string(state, state->current_token.range, 0));
|
|
277
277
|
VALUE location = rbs_new_location(state->buffer, param_range);
|
|
278
278
|
rbs_loc *loc = rbs_check_location(location);
|
|
279
279
|
rbs_loc_add_optional_child(loc, rb_intern("name"), name_range);
|
|
@@ -815,6 +815,8 @@ static VALUE parse_simple(parserstate *state) {
|
|
|
815
815
|
}
|
|
816
816
|
case tULIDENT:
|
|
817
817
|
// fallthrough
|
|
818
|
+
case tLIDENT:
|
|
819
|
+
// fallthrough
|
|
818
820
|
case pCOLON2: {
|
|
819
821
|
range name_range;
|
|
820
822
|
range args_range;
|
|
@@ -857,19 +859,11 @@ static VALUE parse_simple(parserstate *state) {
|
|
|
857
859
|
} else if (kind == INTERFACE_NAME) {
|
|
858
860
|
return rbs_interface(typename, types, location);
|
|
859
861
|
} else if (kind == ALIAS_NAME) {
|
|
860
|
-
return rbs_alias(typename, location);
|
|
862
|
+
return rbs_alias(typename, types, location);
|
|
861
863
|
} else {
|
|
862
864
|
return Qnil;
|
|
863
865
|
}
|
|
864
866
|
}
|
|
865
|
-
case tLIDENT: {
|
|
866
|
-
VALUE location = rbs_location_current_token(state);
|
|
867
|
-
rbs_loc *loc = rbs_check_location(location);
|
|
868
|
-
rbs_loc_add_required_child(loc, rb_intern("name"), state->current_token.range);
|
|
869
|
-
rbs_loc_add_optional_child(loc, rb_intern("args"), NULL_RANGE);
|
|
870
|
-
VALUE typename = parse_type_name(state, ALIAS_NAME, NULL);
|
|
871
|
-
return rbs_alias(typename, location);
|
|
872
|
-
}
|
|
873
867
|
case kSINGLETON: {
|
|
874
868
|
range name_range;
|
|
875
869
|
range type_range;
|
|
@@ -1093,12 +1087,98 @@ VALUE parse_const_decl(parserstate *state) {
|
|
|
1093
1087
|
return rbs_ast_decl_constant(typename, type, location, comment);
|
|
1094
1088
|
}
|
|
1095
1089
|
|
|
1090
|
+
/*
|
|
1091
|
+
module_type_params ::= {} `[` module_type_param `,` ... <`]`>
|
|
1092
|
+
| {<>}
|
|
1093
|
+
|
|
1094
|
+
module_type_param ::= kUNCHECKED? (kIN|kOUT|) tUIDENT
|
|
1095
|
+
*/
|
|
1096
|
+
VALUE parse_module_type_params(parserstate *state, range *rg) {
|
|
1097
|
+
VALUE params = rbs_ast_decl_module_type_params();
|
|
1098
|
+
|
|
1099
|
+
if (state->next_token.type == pLBRACKET) {
|
|
1100
|
+
parser_advance(state);
|
|
1101
|
+
|
|
1102
|
+
rg->start = state->current_token.range.start;
|
|
1103
|
+
|
|
1104
|
+
while (true) {
|
|
1105
|
+
VALUE name;
|
|
1106
|
+
VALUE unchecked = Qfalse;
|
|
1107
|
+
VALUE variance = ID2SYM(rb_intern("invariant"));
|
|
1108
|
+
|
|
1109
|
+
range param_range = NULL_RANGE;
|
|
1110
|
+
range name_range;
|
|
1111
|
+
range variance_range = NULL_RANGE;
|
|
1112
|
+
range unchecked_range = NULL_RANGE;
|
|
1113
|
+
|
|
1114
|
+
param_range.start = state->next_token.range.start;
|
|
1115
|
+
|
|
1116
|
+
if (state->next_token.type == kUNCHECKED) {
|
|
1117
|
+
unchecked = Qtrue;
|
|
1118
|
+
parser_advance(state);
|
|
1119
|
+
unchecked_range = state->current_token.range;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
if (state->next_token.type == kIN || state->next_token.type == kOUT) {
|
|
1123
|
+
switch (state->next_token.type) {
|
|
1124
|
+
case kIN:
|
|
1125
|
+
variance = ID2SYM(rb_intern("contravariant"));
|
|
1126
|
+
break;
|
|
1127
|
+
case kOUT:
|
|
1128
|
+
variance = ID2SYM(rb_intern("covariant"));
|
|
1129
|
+
break;
|
|
1130
|
+
default:
|
|
1131
|
+
rbs_abort();
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
parser_advance(state);
|
|
1135
|
+
variance_range = state->current_token.range;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
parser_advance_assert(state, tUIDENT);
|
|
1139
|
+
name_range = state->current_token.range;
|
|
1140
|
+
param_range.end = state->current_token.range.end;
|
|
1141
|
+
|
|
1142
|
+
ID id = INTERN_TOKEN(state, state->current_token);
|
|
1143
|
+
name = ID2SYM(id);
|
|
1144
|
+
|
|
1145
|
+
parser_insert_typevar(state, id);
|
|
1146
|
+
|
|
1147
|
+
VALUE location = rbs_new_location(state->buffer, param_range);
|
|
1148
|
+
rbs_loc *loc = rbs_check_location(location);
|
|
1149
|
+
rbs_loc_add_required_child(loc, rb_intern("name"), name_range);
|
|
1150
|
+
rbs_loc_add_optional_child(loc, rb_intern("variance"), variance_range);
|
|
1151
|
+
rbs_loc_add_optional_child(loc, rb_intern("unchecked"), unchecked_range);
|
|
1152
|
+
|
|
1153
|
+
VALUE param = rbs_ast_decl_module_type_params_param(name, variance, unchecked, location);
|
|
1154
|
+
rb_funcall(params, rb_intern("add"), 1, param);
|
|
1155
|
+
|
|
1156
|
+
if (state->next_token.type == pCOMMA) {
|
|
1157
|
+
parser_advance(state);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
if (state->next_token.type == pRBRACKET) {
|
|
1161
|
+
break;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
parser_advance_assert(state, pRBRACKET);
|
|
1166
|
+
rg->end = state->current_token.range.end;
|
|
1167
|
+
} else {
|
|
1168
|
+
*rg = NULL_RANGE;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
return params;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1096
1174
|
/*
|
|
1097
1175
|
type_decl ::= {kTYPE} alias_name `=` <type>
|
|
1098
1176
|
*/
|
|
1099
1177
|
VALUE parse_type_decl(parserstate *state, position comment_pos, VALUE annotations) {
|
|
1100
1178
|
range decl_range;
|
|
1101
|
-
range keyword_range, name_range, eq_range;
|
|
1179
|
+
range keyword_range, name_range, params_range, eq_range;
|
|
1180
|
+
|
|
1181
|
+
parser_push_typevar_table(state, true);
|
|
1102
1182
|
|
|
1103
1183
|
decl_range.start = state->current_token.range.start;
|
|
1104
1184
|
comment_pos = nonnull_pos_or(comment_pos, decl_range.start);
|
|
@@ -1108,6 +1188,8 @@ VALUE parse_type_decl(parserstate *state, position comment_pos, VALUE annotation
|
|
|
1108
1188
|
parser_advance(state);
|
|
1109
1189
|
VALUE typename = parse_type_name(state, ALIAS_NAME, &name_range);
|
|
1110
1190
|
|
|
1191
|
+
VALUE type_params = parse_module_type_params(state, ¶ms_range);
|
|
1192
|
+
|
|
1111
1193
|
parser_advance_assert(state, pEQ);
|
|
1112
1194
|
eq_range = state->current_token.range;
|
|
1113
1195
|
|
|
@@ -1118,10 +1200,14 @@ VALUE parse_type_decl(parserstate *state, position comment_pos, VALUE annotation
|
|
|
1118
1200
|
rbs_loc *loc = rbs_check_location(location);
|
|
1119
1201
|
rbs_loc_add_required_child(loc, rb_intern("keyword"), keyword_range);
|
|
1120
1202
|
rbs_loc_add_required_child(loc, rb_intern("name"), name_range);
|
|
1203
|
+
rbs_loc_add_optional_child(loc, rb_intern("type_params"), params_range);
|
|
1121
1204
|
rbs_loc_add_required_child(loc, rb_intern("eq"), eq_range);
|
|
1122
1205
|
|
|
1206
|
+
parser_pop_typevar_table(state);
|
|
1207
|
+
|
|
1123
1208
|
return rbs_ast_decl_alias(
|
|
1124
1209
|
typename,
|
|
1210
|
+
type_params,
|
|
1125
1211
|
type,
|
|
1126
1212
|
annotations,
|
|
1127
1213
|
location,
|
|
@@ -1184,90 +1270,6 @@ VALUE parse_annotation(parserstate *state) {
|
|
|
1184
1270
|
return rbs_ast_annotation(string, location);
|
|
1185
1271
|
}
|
|
1186
1272
|
|
|
1187
|
-
/*
|
|
1188
|
-
module_type_params ::= {} `[` module_type_param `,` ... <`]`>
|
|
1189
|
-
| {<>}
|
|
1190
|
-
|
|
1191
|
-
module_type_param ::= kUNCHECKED? (kIN|kOUT|) tUIDENT
|
|
1192
|
-
*/
|
|
1193
|
-
VALUE parse_module_type_params(parserstate *state, range *rg) {
|
|
1194
|
-
VALUE params = rbs_ast_decl_module_type_params();
|
|
1195
|
-
|
|
1196
|
-
if (state->next_token.type == pLBRACKET) {
|
|
1197
|
-
parser_advance(state);
|
|
1198
|
-
|
|
1199
|
-
rg->start = state->current_token.range.start;
|
|
1200
|
-
|
|
1201
|
-
while (true) {
|
|
1202
|
-
VALUE name;
|
|
1203
|
-
VALUE unchecked = Qfalse;
|
|
1204
|
-
VALUE variance = ID2SYM(rb_intern("invariant"));
|
|
1205
|
-
|
|
1206
|
-
range param_range = NULL_RANGE;
|
|
1207
|
-
range name_range;
|
|
1208
|
-
range variance_range = NULL_RANGE;
|
|
1209
|
-
range unchecked_range = NULL_RANGE;
|
|
1210
|
-
|
|
1211
|
-
param_range.start = state->next_token.range.start;
|
|
1212
|
-
|
|
1213
|
-
if (state->next_token.type == kUNCHECKED) {
|
|
1214
|
-
unchecked = Qtrue;
|
|
1215
|
-
parser_advance(state);
|
|
1216
|
-
unchecked_range = state->current_token.range;
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
if (state->next_token.type == kIN || state->next_token.type == kOUT) {
|
|
1220
|
-
switch (state->next_token.type) {
|
|
1221
|
-
case kIN:
|
|
1222
|
-
variance = ID2SYM(rb_intern("contravariant"));
|
|
1223
|
-
break;
|
|
1224
|
-
case kOUT:
|
|
1225
|
-
variance = ID2SYM(rb_intern("covariant"));
|
|
1226
|
-
break;
|
|
1227
|
-
default:
|
|
1228
|
-
rbs_abort();
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
parser_advance(state);
|
|
1232
|
-
variance_range = state->current_token.range;
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
parser_advance_assert(state, tUIDENT);
|
|
1236
|
-
name_range = state->current_token.range;
|
|
1237
|
-
param_range.end = state->current_token.range.end;
|
|
1238
|
-
|
|
1239
|
-
ID id = INTERN_TOKEN(state, state->current_token);
|
|
1240
|
-
name = ID2SYM(id);
|
|
1241
|
-
|
|
1242
|
-
parser_insert_typevar(state, id);
|
|
1243
|
-
|
|
1244
|
-
VALUE location = rbs_new_location(state->buffer, param_range);
|
|
1245
|
-
rbs_loc *loc = rbs_check_location(location);
|
|
1246
|
-
rbs_loc_add_required_child(loc, rb_intern("name"), name_range);
|
|
1247
|
-
rbs_loc_add_optional_child(loc, rb_intern("variance"), variance_range);
|
|
1248
|
-
rbs_loc_add_optional_child(loc, rb_intern("unchecked"), unchecked_range);
|
|
1249
|
-
|
|
1250
|
-
VALUE param = rbs_ast_decl_module_type_params_param(name, variance, unchecked, location);
|
|
1251
|
-
rb_funcall(params, rb_intern("add"), 1, param);
|
|
1252
|
-
|
|
1253
|
-
if (state->next_token.type == pCOMMA) {
|
|
1254
|
-
parser_advance(state);
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
|
-
if (state->next_token.type == pRBRACKET) {
|
|
1258
|
-
break;
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
parser_advance_assert(state, pRBRACKET);
|
|
1263
|
-
rg->end = state->current_token.range.end;
|
|
1264
|
-
} else {
|
|
1265
|
-
*rg = NULL_RANGE;
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
return params;
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
1273
|
/*
|
|
1272
1274
|
annotations ::= {} annotation ... <annotation>
|
|
1273
1275
|
| {<>}
|
|
@@ -70,15 +70,16 @@ VALUE rbs_class_singleton(VALUE typename, VALUE location) {
|
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
VALUE rbs_alias(VALUE typename, VALUE location) {
|
|
74
|
-
VALUE
|
|
75
|
-
rb_hash_aset(
|
|
76
|
-
rb_hash_aset(
|
|
73
|
+
VALUE rbs_alias(VALUE typename, VALUE args, VALUE location) {
|
|
74
|
+
VALUE kwargs = rb_hash_new();
|
|
75
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("name")), typename);
|
|
76
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("args")), args);
|
|
77
|
+
rb_hash_aset(kwargs, ID2SYM(rb_intern("location")), location);
|
|
77
78
|
|
|
78
79
|
return CLASS_NEW_INSTANCE(
|
|
79
80
|
RBS_Types_Alias,
|
|
80
81
|
1,
|
|
81
|
-
&
|
|
82
|
+
&kwargs
|
|
82
83
|
);
|
|
83
84
|
}
|
|
84
85
|
|
|
@@ -339,9 +340,10 @@ VALUE rbs_ast_decl_global(VALUE name, VALUE type, VALUE location, VALUE comment)
|
|
|
339
340
|
);
|
|
340
341
|
}
|
|
341
342
|
|
|
342
|
-
VALUE rbs_ast_decl_alias(VALUE name, VALUE type, VALUE annotations, VALUE location, VALUE comment) {
|
|
343
|
+
VALUE rbs_ast_decl_alias(VALUE name, VALUE type_params, VALUE type, VALUE annotations, VALUE location, VALUE comment) {
|
|
343
344
|
VALUE args = rb_hash_new();
|
|
344
345
|
rb_hash_aset(args, ID2SYM(rb_intern("name")), name);
|
|
346
|
+
rb_hash_aset(args, ID2SYM(rb_intern("type_params")), type_params);
|
|
345
347
|
rb_hash_aset(args, ID2SYM(rb_intern("type")), type);
|
|
346
348
|
rb_hash_aset(args, ID2SYM(rb_intern("annotations")), annotations);
|
|
347
349
|
rb_hash_aset(args, ID2SYM(rb_intern("location")), location);
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
#include "ruby.h"
|
|
5
5
|
|
|
6
|
-
VALUE rbs_alias(VALUE typename, VALUE location);
|
|
6
|
+
VALUE rbs_alias(VALUE typename, VALUE args, VALUE location);
|
|
7
7
|
VALUE rbs_ast_annotation(VALUE string, VALUE location);
|
|
8
8
|
VALUE rbs_ast_comment(VALUE string, VALUE location);
|
|
9
|
-
VALUE rbs_ast_decl_alias(VALUE name, VALUE type, VALUE annotations, VALUE location, VALUE comment);
|
|
9
|
+
VALUE rbs_ast_decl_alias(VALUE name, VALUE type_params, VALUE type, VALUE annotations, VALUE location, VALUE comment);
|
|
10
10
|
VALUE rbs_ast_decl_class_super(VALUE name, VALUE args, VALUE location);
|
|
11
11
|
VALUE rbs_ast_decl_class(VALUE name, VALUE type_params, VALUE super_class, VALUE members, VALUE annotations, VALUE location, VALUE comment);
|
|
12
12
|
VALUE rbs_ast_decl_constant(VALUE name, VALUE type, VALUE location, VALUE comment);
|
data/lib/rbs/ast/declarations.rb
CHANGED
|
@@ -362,13 +362,15 @@ module RBS
|
|
|
362
362
|
|
|
363
363
|
class Alias < Base
|
|
364
364
|
attr_reader :name
|
|
365
|
+
attr_reader :type_params
|
|
365
366
|
attr_reader :type
|
|
366
367
|
attr_reader :annotations
|
|
367
368
|
attr_reader :location
|
|
368
369
|
attr_reader :comment
|
|
369
370
|
|
|
370
|
-
def initialize(name:, type:, annotations:, location:, comment:)
|
|
371
|
+
def initialize(name:, type_params:, type:, annotations:, location:, comment:)
|
|
371
372
|
@name = name
|
|
373
|
+
@type_params = type_params
|
|
372
374
|
@type = type
|
|
373
375
|
@annotations = annotations
|
|
374
376
|
@location = location
|
|
@@ -378,19 +380,21 @@ module RBS
|
|
|
378
380
|
def ==(other)
|
|
379
381
|
other.is_a?(Alias) &&
|
|
380
382
|
other.name == name &&
|
|
383
|
+
other.type_params == type_params &&
|
|
381
384
|
other.type == type
|
|
382
385
|
end
|
|
383
386
|
|
|
384
387
|
alias eql? ==
|
|
385
388
|
|
|
386
389
|
def hash
|
|
387
|
-
self.class.hash ^ name.hash ^ type.hash
|
|
390
|
+
self.class.hash ^ name.hash ^ type_params.hash ^ type.hash
|
|
388
391
|
end
|
|
389
392
|
|
|
390
393
|
def to_json(state = _ = nil)
|
|
391
394
|
{
|
|
392
395
|
declaration: :alias,
|
|
393
396
|
name: name,
|
|
397
|
+
type_params: type_params,
|
|
394
398
|
type: type,
|
|
395
399
|
annotations: annotations,
|
|
396
400
|
location: location,
|
data/lib/rbs/cli.rb
CHANGED
|
@@ -460,7 +460,7 @@ EOU
|
|
|
460
460
|
|
|
461
461
|
env.alias_decls.each do |name, decl|
|
|
462
462
|
stdout.puts "Validating alias: `#{name}`..."
|
|
463
|
-
builder.
|
|
463
|
+
builder.expand_alias1(name).tap do |type|
|
|
464
464
|
validator.validate_type type, context: [Namespace.root]
|
|
465
465
|
end
|
|
466
466
|
validator.validate_type_alias(entry: decl)
|
|
@@ -104,9 +104,9 @@ module RBS
|
|
|
104
104
|
else
|
|
105
105
|
begin
|
|
106
106
|
# git v2.27.0 or greater
|
|
107
|
-
git 'clone', '--filter=blob:none', remote, git_dir.to_s
|
|
107
|
+
git 'clone', '--filter=blob:none', remote, git_dir.to_s, chdir: nil
|
|
108
108
|
rescue CommandError
|
|
109
|
-
git 'clone', remote, git_dir.to_s
|
|
109
|
+
git 'clone', remote, git_dir.to_s, chdir: nil
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
|
|
@@ -131,7 +131,8 @@ module RBS
|
|
|
131
131
|
private def git_dir
|
|
132
132
|
@git_dir ||= (
|
|
133
133
|
base = Pathname(ENV['XDG_CACHE_HOME'] || File.expand_path("~/.cache"))
|
|
134
|
-
|
|
134
|
+
cache_key = remote.start_with?('.') ? "#{remote}\0#{Dir.pwd}" : remote
|
|
135
|
+
dir = base.join('rbs', Digest::SHA256.hexdigest(cache_key))
|
|
135
136
|
dir.mkpath
|
|
136
137
|
dir
|
|
137
138
|
)
|
|
@@ -149,13 +150,14 @@ module RBS
|
|
|
149
150
|
git('rev-parse', 'HEAD').chomp
|
|
150
151
|
end
|
|
151
152
|
|
|
152
|
-
private def git(*cmd)
|
|
153
|
-
sh! 'git', *cmd
|
|
153
|
+
private def git(*cmd, **opt)
|
|
154
|
+
sh! 'git', *cmd, **opt
|
|
154
155
|
end
|
|
155
156
|
|
|
156
|
-
private def sh!(*cmd)
|
|
157
|
+
private def sh!(*cmd, **opt)
|
|
157
158
|
RBS.logger.debug "$ #{cmd.join(' ')}"
|
|
158
|
-
|
|
159
|
+
opt = { chdir: git_dir }.merge(opt).compact
|
|
160
|
+
(__skip__ = Open3.capture3(*cmd, **opt)).then do |out, err, status|
|
|
159
161
|
raise CommandError, "Unexpected status #{status.exitstatus}\n\n#{err}" unless status.success?
|
|
160
162
|
|
|
161
163
|
out
|
|
@@ -291,6 +291,10 @@ module RBS
|
|
|
291
291
|
end
|
|
292
292
|
|
|
293
293
|
one_ancestors.each_extended_module do |mod|
|
|
294
|
+
mod.args.each do |arg|
|
|
295
|
+
validate_type_presence(arg)
|
|
296
|
+
end
|
|
297
|
+
|
|
294
298
|
mod_defn = build_instance(mod.name, no_self_types: true)
|
|
295
299
|
merge_definition(src: mod_defn,
|
|
296
300
|
dest: definition,
|
|
@@ -299,6 +303,10 @@ module RBS
|
|
|
299
303
|
|
|
300
304
|
interface_methods = {}
|
|
301
305
|
one_ancestors.each_extended_interface do |mod|
|
|
306
|
+
mod.args.each do |arg|
|
|
307
|
+
validate_type_presence(arg)
|
|
308
|
+
end
|
|
309
|
+
|
|
302
310
|
mod_defn = build_interface(mod.name)
|
|
303
311
|
subst = Substitution.build(mod_defn.type_params, mod.args)
|
|
304
312
|
|
|
@@ -781,9 +789,36 @@ module RBS
|
|
|
781
789
|
end
|
|
782
790
|
|
|
783
791
|
def expand_alias(type_name)
|
|
784
|
-
|
|
792
|
+
expand_alias2(type_name, [])
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
def expand_alias1(type_name)
|
|
796
|
+
entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
|
|
797
|
+
as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) }
|
|
798
|
+
expand_alias2(type_name, as)
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
def expand_alias2(type_name, args)
|
|
802
|
+
entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
|
|
803
|
+
|
|
785
804
|
ensure_namespace!(type_name.namespace, location: entry.decl.location)
|
|
786
|
-
entry.decl.
|
|
805
|
+
params = entry.decl.type_params.each.map(&:name)
|
|
806
|
+
|
|
807
|
+
unless params.size == args.size
|
|
808
|
+
as = "[#{args.join(", ")}]" unless args.empty?
|
|
809
|
+
ps = "[#{params.join(", ")}]" unless params.empty?
|
|
810
|
+
|
|
811
|
+
raise "Invalid type application: type = #{type_name}#{as}, decl = #{type_name}#{ps}"
|
|
812
|
+
end
|
|
813
|
+
|
|
814
|
+
type = entry.decl.type
|
|
815
|
+
|
|
816
|
+
unless params.empty?
|
|
817
|
+
subst = Substitution.build(params, args)
|
|
818
|
+
type = type.sub(subst)
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
type
|
|
787
822
|
end
|
|
788
823
|
|
|
789
824
|
def update(env:, except:, ancestor_builder:)
|
|
@@ -804,5 +839,26 @@ module RBS
|
|
|
804
839
|
end
|
|
805
840
|
end
|
|
806
841
|
end
|
|
842
|
+
|
|
843
|
+
def validate_type_presence(type)
|
|
844
|
+
case type
|
|
845
|
+
when Types::ClassInstance, Types::ClassSingleton, Types::Interface, Types::Alias
|
|
846
|
+
validate_type_name(type.name, type.location)
|
|
847
|
+
end
|
|
848
|
+
|
|
849
|
+
type.each_type do |type|
|
|
850
|
+
validate_type_presence(type)
|
|
851
|
+
end
|
|
852
|
+
end
|
|
853
|
+
|
|
854
|
+
def validate_type_name(name, location)
|
|
855
|
+
name = name.absolute!
|
|
856
|
+
|
|
857
|
+
return if name.class? && env.class_decls.key?(name)
|
|
858
|
+
return if name.interface? && env.interface_decls.key?(name)
|
|
859
|
+
return if name.alias? && env.alias_decls.key?(name)
|
|
860
|
+
|
|
861
|
+
raise NoTypeFoundError.new(type_name: name, location: location)
|
|
862
|
+
end
|
|
807
863
|
end
|
|
808
864
|
end
|
data/lib/rbs/environment.rb
CHANGED
|
@@ -319,6 +319,7 @@ module RBS
|
|
|
319
319
|
when AST::Declarations::Alias
|
|
320
320
|
AST::Declarations::Alias.new(
|
|
321
321
|
name: decl.name.with_prefix(prefix),
|
|
322
|
+
type_params: decl.type_params,
|
|
322
323
|
type: absolute_type(resolver, decl.type, context: context),
|
|
323
324
|
location: decl.location,
|
|
324
325
|
annotations: decl.annotations,
|
|
@@ -57,7 +57,7 @@ module RBS
|
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
when name.alias?
|
|
60
|
-
each_type_node builder.
|
|
60
|
+
each_type_node builder.expand_alias1(name), &block
|
|
61
61
|
else
|
|
62
62
|
raise "Unexpected TypeNameNode with type_name=#{name}"
|
|
63
63
|
end
|
|
@@ -126,6 +126,9 @@ module RBS
|
|
|
126
126
|
end
|
|
127
127
|
when RBS::Types::Alias
|
|
128
128
|
yield TypeNameNode.new(type_name: type.name)
|
|
129
|
+
type.args.each do |ty|
|
|
130
|
+
each_type_node(ty, &block)
|
|
131
|
+
end
|
|
129
132
|
when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Tuple
|
|
130
133
|
type.types.each do |ty|
|
|
131
134
|
each_type_node ty, &block
|
data/lib/rbs/errors.rb
CHANGED
|
@@ -431,4 +431,16 @@ module RBS
|
|
|
431
431
|
@alias_names.map(&:name).join(', ')
|
|
432
432
|
end
|
|
433
433
|
end
|
|
434
|
+
|
|
435
|
+
class NonregularTypeAliasError < LoadingError
|
|
436
|
+
attr_reader :diagnostic
|
|
437
|
+
attr_reader :location
|
|
438
|
+
|
|
439
|
+
def initialize(diagnostic:, location:)
|
|
440
|
+
@diagnostic = diagnostic
|
|
441
|
+
@location = location
|
|
442
|
+
|
|
443
|
+
super "#{Location.to_string location}: Nonregular generic type alias is prohibited: #{diagnostic.type_name}, #{diagnostic.nonregular_type}"
|
|
444
|
+
end
|
|
445
|
+
end
|
|
434
446
|
end
|
data/lib/rbs/test/setup.rb
CHANGED
|
@@ -13,6 +13,7 @@ begin
|
|
|
13
13
|
filter = ENV.fetch('RBS_TEST_TARGET', "").split(',').map! { |e| e.strip }
|
|
14
14
|
skips = (ENV['RBS_TEST_SKIP'] || '').split(',').map! { |e| e.strip }
|
|
15
15
|
RBS.logger_level = (ENV["RBS_TEST_LOGLEVEL"] || "info")
|
|
16
|
+
logger.level = RBS.logger_level
|
|
16
17
|
sample_size = get_sample_size(ENV['RBS_TEST_SAMPLE_SIZE'] || '')
|
|
17
18
|
double_class = to_double_class(ENV['RBS_TEST_DOUBLE_SUITE'])
|
|
18
19
|
unchecked_classes = (ENV['RBS_TEST_UNCHECKED_CLASSES'] || '').split(',').map! { |unchecked_class| unchecked_class.strip }.push(*double_class)
|