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");
|
||||
}
|
||||
|
||||
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;
|
||||
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,
|
||||
|
||||
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