Disallow flow type parameter defaults in some cases
This commit is contained in:
parent
65ca968f8b
commit
0353ce9ed5
@ -505,7 +505,18 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
// Type annotations
|
// Type annotations
|
||||||
|
|
||||||
flowParseTypeParameter(): N.TypeParameter {
|
flowParseTypeParameter(
|
||||||
|
allowDefault?: boolean = true,
|
||||||
|
requireDefault?: boolean = false,
|
||||||
|
): N.TypeParameter {
|
||||||
|
if (!allowDefault && requireDefault) {
|
||||||
|
throw new Error(
|
||||||
|
"Cannot disallow a default value (`allowDefault`) while also requiring it (`requireDefault`).",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeStart = this.state.start;
|
||||||
|
|
||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
|
|
||||||
const variance = this.flowParseVariance();
|
const variance = this.flowParseVariance();
|
||||||
@ -516,14 +527,28 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
node.bound = ident.typeAnnotation;
|
node.bound = ident.typeAnnotation;
|
||||||
|
|
||||||
if (this.match(tt.eq)) {
|
if (this.match(tt.eq)) {
|
||||||
|
if (allowDefault) {
|
||||||
this.eat(tt.eq);
|
this.eat(tt.eq);
|
||||||
node.default = this.flowParseType();
|
node.default = this.flowParseType();
|
||||||
|
} else {
|
||||||
|
this.unexpected();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (requireDefault) {
|
||||||
|
this.unexpected(
|
||||||
|
nodeStart,
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
"Type parameter declaration needs a default, since a preceding type parameter declaration has a default.",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.finishNode(node, "TypeParameter");
|
return this.finishNode(node, "TypeParameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
flowParseTypeParameterDeclaration(): N.TypeParameterDeclaration {
|
flowParseTypeParameterDeclaration(
|
||||||
|
allowDefault?: boolean = true,
|
||||||
|
): N.TypeParameterDeclaration {
|
||||||
const oldInType = this.state.inType;
|
const oldInType = this.state.inType;
|
||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
node.params = [];
|
node.params = [];
|
||||||
@ -537,8 +562,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
this.unexpected();
|
this.unexpected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let defaultRequired = false;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
node.params.push(this.flowParseTypeParameter());
|
const typeParameter = this.flowParseTypeParameter(
|
||||||
|
allowDefault,
|
||||||
|
defaultRequired,
|
||||||
|
);
|
||||||
|
|
||||||
|
node.params.push(typeParameter);
|
||||||
|
|
||||||
|
if (typeParameter.default) {
|
||||||
|
defaultRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.isRelational(">")) {
|
if (!this.isRelational(">")) {
|
||||||
this.expect(tt.comma);
|
this.expect(tt.comma);
|
||||||
}
|
}
|
||||||
@ -607,7 +644,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
node.typeParameters = null;
|
node.typeParameters = null;
|
||||||
|
|
||||||
if (this.isRelational("<")) {
|
if (this.isRelational("<")) {
|
||||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
node.typeParameters = this.flowParseTypeParameterDeclaration(
|
||||||
|
/* allowDefault */ false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.expect(tt.parenL);
|
this.expect(tt.parenL);
|
||||||
@ -668,17 +707,16 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
while (!this.match(endDelim)) {
|
while (!this.match(endDelim)) {
|
||||||
let isStatic = false;
|
let isStatic = false;
|
||||||
const node = this.startNode();
|
const node = this.startNode();
|
||||||
|
|
||||||
|
if (allowStatic && this.isContextual("static")) {
|
||||||
const lookahead = this.lookahead();
|
const lookahead = this.lookahead();
|
||||||
|
|
||||||
if (
|
|
||||||
allowStatic &&
|
|
||||||
this.isContextual("static") &&
|
|
||||||
// static is a valid identifier name
|
// static is a valid identifier name
|
||||||
(lookahead.type !== tt.colon && lookahead.type !== tt.question)
|
if (lookahead.type !== tt.colon && lookahead.type !== tt.question) {
|
||||||
) {
|
|
||||||
this.next();
|
this.next();
|
||||||
isStatic = true;
|
isStatic = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const variance = this.flowParseVariance();
|
const variance = this.flowParseVariance();
|
||||||
|
|
||||||
@ -999,7 +1037,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
case tt.relational:
|
case tt.relational:
|
||||||
if (this.state.value === "<") {
|
if (this.state.value === "<") {
|
||||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
node.typeParameters = this.flowParseTypeParameterDeclaration(
|
||||||
|
/* allowDefault */ false,
|
||||||
|
);
|
||||||
this.expect(tt.parenL);
|
this.expect(tt.parenL);
|
||||||
tmp = this.flowParseFunctionTypeParams();
|
tmp = this.flowParseFunctionTypeParams();
|
||||||
node.params = tmp.params;
|
node.params = tmp.params;
|
||||||
@ -1777,7 +1817,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
}
|
}
|
||||||
delete (method: $FlowFixMe).variance;
|
delete (method: $FlowFixMe).variance;
|
||||||
if (this.isRelational("<")) {
|
if (this.isRelational("<")) {
|
||||||
method.typeParameters = this.flowParseTypeParameterDeclaration();
|
method.typeParameters = this.flowParseTypeParameterDeclaration(
|
||||||
|
/* allowDefault */ false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.pushClassMethod(
|
super.pushClassMethod(
|
||||||
@ -1858,7 +1900,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
// method shorthand
|
// method shorthand
|
||||||
if (this.isRelational("<")) {
|
if (this.isRelational("<")) {
|
||||||
typeParameters = this.flowParseTypeParameterDeclaration();
|
typeParameters = this.flowParseTypeParameterDeclaration(
|
||||||
|
/* allowDefault */ false,
|
||||||
|
);
|
||||||
if (!this.match(tt.parenL)) this.unexpected();
|
if (!this.match(tt.parenL)) this.unexpected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2057,7 +2101,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
const kind = node.kind;
|
const kind = node.kind;
|
||||||
if (kind !== "get" && kind !== "set" && this.isRelational("<")) {
|
if (kind !== "get" && kind !== "set" && this.isRelational("<")) {
|
||||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
node.typeParameters = this.flowParseTypeParameterDeclaration(
|
||||||
|
/* allowDefault */ false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
super.parseFunctionParams(node);
|
super.parseFunctionParams(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -856,6 +856,7 @@ export type TypeParameterBase = NodeBase & {
|
|||||||
|
|
||||||
export type TypeParameter = TypeParameterBase & {
|
export type TypeParameter = TypeParameterBase & {
|
||||||
type: "TypeParameter",
|
type: "TypeParameter",
|
||||||
|
default?: TypeAnnotation,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TsTypeParameter = TypeParameterBase & {
|
export type TsTypeParameter = TypeParameterBase & {
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "File",
|
|
||||||
"start": 0,
|
|
||||||
"end": 0,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"program": {
|
|
||||||
"type": "Program",
|
|
||||||
"start": 0,
|
|
||||||
"end": 0,
|
|
||||||
"loc": {
|
|
||||||
"start": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"line": 1,
|
|
||||||
"column": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sourceType": "module",
|
|
||||||
"body": [],
|
|
||||||
"directives": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-1/input.js
vendored
Normal file
3
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-1/input.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
(class A {
|
||||||
|
foo<T = string>() {}
|
||||||
|
});
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (2:8)"
|
||||||
|
}
|
||||||
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-2/input.js
vendored
Normal file
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-2/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
({ foo<T = string>() {} });
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (1:9)"
|
||||||
|
}
|
||||||
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-3/input.js
vendored
Normal file
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-3/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare class A { foo<T = string>(): void }
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (1:24)"
|
||||||
|
}
|
||||||
3
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-4/input.js
vendored
Normal file
3
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-4/input.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
foo<T = string>() {}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (2:8)"
|
||||||
|
}
|
||||||
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-5/input.js
vendored
Normal file
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-invalid-5/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
function foo<T = string>() {}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (1:15)"
|
||||||
|
}
|
||||||
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-missing/input.js
vendored
Normal file
1
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-missing/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
type A<HasDefault = string, NoDefault> = T;
|
||||||
3
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-missing/options.json
vendored
Normal file
3
packages/babylon/test/fixtures/flow/type-parameter-declaration/default-missing/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Type parameter declaration needs a default, since a preceding type parameter declaration has a default. (1:28)"
|
||||||
|
}
|
||||||
@ -28,12 +28,6 @@ types/annotations/migrated_0001.js
|
|||||||
types/annotations_in_comments_invalid/migrated_0003.js
|
types/annotations_in_comments_invalid/migrated_0003.js
|
||||||
types/annotations/void_is_reserved_param.js
|
types/annotations/void_is_reserved_param.js
|
||||||
types/member/reserved_words.js
|
types/member/reserved_words.js
|
||||||
types/parameter_defaults/migrated_0023.js
|
|
||||||
types/parameter_defaults/migrated_0026.js
|
|
||||||
types/parameter_defaults/migrated_0028.js
|
|
||||||
types/parameter_defaults/migrated_0029.js
|
|
||||||
types/parameter_defaults/migrated_0030.js
|
|
||||||
types/parameter_defaults/migrated_0031.js
|
|
||||||
types/parameter_defaults/migrated_0032.js
|
types/parameter_defaults/migrated_0032.js
|
||||||
types/typecasts_invalid/migrated_0001.js
|
types/typecasts_invalid/migrated_0001.js
|
||||||
class_method_kinds/polymorphic_getter.js
|
class_method_kinds/polymorphic_getter.js
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user