TypeScript Constant contexts (#9534)

* Add as const fixtures

* parse constant context

* parse constant context

* quick check for literal

* code review, better error message, check array elements

* Removed unneeded test cases
This commit is contained in:
Tan Li Hau
2019-03-16 13:40:39 +08:00
committed by Nicolò Ribaudo
parent 0a69b45126
commit 25a3825a1d
13 changed files with 5697 additions and 5 deletions

View File

@@ -321,6 +321,44 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "TSTypeParameterDeclaration");
}
tsTryNextParseConstantContext(): ?N.TsTypeReference {
if (this.lookahead().type === tt._const) {
this.next();
return this.tsParseTypeReference();
}
return null;
}
tsCheckLiteralForConstantContext(node: N.Node) {
switch (node.type) {
case "StringLiteral":
case "TemplateLiteral":
case "NumericLiteral":
case "BooleanLiteral":
case "SpreadElement":
case "ObjectMethod":
case "ObjectExpression":
return;
case "ArrayExpression":
return (node: N.ArrayExpression).elements.forEach(element => {
if (element) {
this.tsCheckLiteralForConstantContext(element);
}
});
case "ObjectProperty":
return this.tsCheckLiteralForConstantContext(
(node: N.ObjectProperty).value,
);
case "UnaryExpression":
return this.tsCheckLiteralForConstantContext(node.argument);
default:
this.raise(
node.start,
"Only literal values are allowed in constant contexts",
);
}
}
// Note: In TypeScript implementation we must provide `yieldContext` and `awaitContext`,
// but here it's always false, because this is only used for types.
tsFillSignature(
@@ -937,12 +975,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
tsParseTypeAssertion(): N.TsTypeAssertion {
const node: N.TsTypeAssertion = this.startNode();
this.next(); // <
// Not actually necessary to set state.inType because we never reach here if JSX plugin is enabled,
// but need `tsInType` to satisfy the assertion in `tsParseType`.
node.typeAnnotation = this.tsInType(() => this.tsParseType());
const _const = this.tsTryNextParseConstantContext();
node.typeAnnotation = _const || this.tsNextThenParseType();
this.expectRelational(">");
node.expression = this.parseMaybeUnary();
if (_const) {
this.tsCheckLiteralForConstantContext(node.expression);
}
return this.finishNode(node, "TSTypeAssertion");
}
@@ -1605,7 +1644,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
leftStartLoc,
);
node.expression = left;
node.typeAnnotation = this.tsNextThenParseType();
const _const = this.tsTryNextParseConstantContext();
if (_const) {
this.tsCheckLiteralForConstantContext(node.expression);
node.typeAnnotation = _const;
} else {
node.typeAnnotation = this.tsNextThenParseType();
}
this.finishNode(node, "TSAsExpression");
return this.parseExprOp(
node,