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:
parent
0a69b45126
commit
25a3825a1d
@ -321,6 +321,44 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
return this.finishNode(node, "TSTypeParameterDeclaration");
|
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`,
|
// Note: In TypeScript implementation we must provide `yieldContext` and `awaitContext`,
|
||||||
// but here it's always false, because this is only used for types.
|
// but here it's always false, because this is only used for types.
|
||||||
tsFillSignature(
|
tsFillSignature(
|
||||||
@ -937,12 +975,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
tsParseTypeAssertion(): N.TsTypeAssertion {
|
tsParseTypeAssertion(): N.TsTypeAssertion {
|
||||||
const node: N.TsTypeAssertion = this.startNode();
|
const node: N.TsTypeAssertion = this.startNode();
|
||||||
this.next(); // <
|
const _const = this.tsTryNextParseConstantContext();
|
||||||
// Not actually necessary to set state.inType because we never reach here if JSX plugin is enabled,
|
node.typeAnnotation = _const || this.tsNextThenParseType();
|
||||||
// but need `tsInType` to satisfy the assertion in `tsParseType`.
|
|
||||||
node.typeAnnotation = this.tsInType(() => this.tsParseType());
|
|
||||||
this.expectRelational(">");
|
this.expectRelational(">");
|
||||||
node.expression = this.parseMaybeUnary();
|
node.expression = this.parseMaybeUnary();
|
||||||
|
if (_const) {
|
||||||
|
this.tsCheckLiteralForConstantContext(node.expression);
|
||||||
|
}
|
||||||
return this.finishNode(node, "TSTypeAssertion");
|
return this.finishNode(node, "TSTypeAssertion");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1605,7 +1644,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
leftStartLoc,
|
leftStartLoc,
|
||||||
);
|
);
|
||||||
node.expression = left;
|
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");
|
this.finishNode(node, "TSAsExpression");
|
||||||
return this.parseExprOp(
|
return this.parseExprOp(
|
||||||
node,
|
node,
|
||||||
|
|||||||
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-2/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-2/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
let e = v as const; // Error
|
||||||
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-2/options.json
vendored
Normal file
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-2/options.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sourceType": "module",
|
||||||
|
"plugins": [
|
||||||
|
"typescript"
|
||||||
|
],
|
||||||
|
"throws": "Only literal values are allowed in constant contexts (1:8)"
|
||||||
|
}
|
||||||
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-3/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-3/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
let e = (true ? 1 : 0) as const; // Error
|
||||||
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-3/options.json
vendored
Normal file
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-3/options.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sourceType": "module",
|
||||||
|
"plugins": [
|
||||||
|
"typescript"
|
||||||
|
],
|
||||||
|
"throws": "Only literal values are allowed in constant contexts (1:9)"
|
||||||
|
}
|
||||||
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-4/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-4/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
let e = id(1) as const; // Error
|
||||||
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-4/options.json
vendored
Normal file
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-4/options.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sourceType": "module",
|
||||||
|
"plugins": [
|
||||||
|
"typescript"
|
||||||
|
],
|
||||||
|
"throws": "Only literal values are allowed in constant contexts (1:8)"
|
||||||
|
}
|
||||||
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-5/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/cast/as-const-5/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
let e = [v()] as const; // Error
|
||||||
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-5/options.json
vendored
Normal file
7
packages/babel-parser/test/fixtures/typescript/cast/as-const-5/options.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"sourceType": "module",
|
||||||
|
"plugins": [
|
||||||
|
"typescript"
|
||||||
|
],
|
||||||
|
"throws": "Only literal values are allowed in constant contexts (1:9)"
|
||||||
|
}
|
||||||
39
packages/babel-parser/test/fixtures/typescript/cast/as-const/input.js
vendored
Normal file
39
packages/babel-parser/test/fixtures/typescript/cast/as-const/input.js
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copied over from TypeScript's test case
|
||||||
|
// https://github.com/Microsoft/TypeScript/blob/master/tests/baselines/reference/constAssertions.js
|
||||||
|
let v1 = 'abc' as const;
|
||||||
|
let v2 = `abc` as const;
|
||||||
|
let v3 = 10 as const;
|
||||||
|
let v4 = -10 as const;
|
||||||
|
let v5 = +10 as const;
|
||||||
|
let v6 = 10 as const;
|
||||||
|
let v7 = -10 as const;
|
||||||
|
let v8 = true as const;
|
||||||
|
let v9 = false as const;
|
||||||
|
|
||||||
|
let a1 = [] as const;
|
||||||
|
let a2 = [1, 2, 3] as const;
|
||||||
|
let a3 = [10, 'hello', true] as const;
|
||||||
|
let a4 = [...[1, 2, 3]] as const;
|
||||||
|
let a5 = [1, 2, 3];
|
||||||
|
let a6 = [...a5] as const;
|
||||||
|
let a8 = ['abc', ...a7] as const;
|
||||||
|
|
||||||
|
let o1 = { x: 10, y: 20 } as const;
|
||||||
|
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
|
||||||
|
let o3 = { ...o1, ...o2 } as const;
|
||||||
|
let o5 = { ...o4 } as const;
|
||||||
|
let o7 = { ...d } as const;
|
||||||
|
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
|
||||||
|
|
||||||
|
let p1 = (10) as const;
|
||||||
|
let p2 = ((-10)) as const;
|
||||||
|
let p3 = ([(10)]) as const;
|
||||||
|
let p4 = [[[[10]]]] as const;
|
||||||
|
|
||||||
|
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;
|
||||||
|
|
||||||
|
let q1 = <const> 10;
|
||||||
|
let q2 = <const> 'abc';
|
||||||
|
let q3 = <const> true;
|
||||||
|
let q4 = <const> [1, 2, 3];
|
||||||
|
let q5 = <const> { x: 10, y: 20 };
|
||||||
5572
packages/babel-parser/test/fixtures/typescript/cast/as-const/output.json
vendored
Normal file
5572
packages/babel-parser/test/fixtures/typescript/cast/as-const/output.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
packages/babel-parser/test/fixtures/typescript/const/reserved-word/input.js
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/const/reserved-word/input.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
const b: const;
|
||||||
3
packages/babel-parser/test/fixtures/typescript/const/reserved-word/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/typescript/const/reserved-word/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token (1:9)"
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user