rbs 1.7.0.beta.5 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|