Skip to content

Commit

Permalink
[tsx] raise error on single arrow type argument without comma (#14135)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
ozanhonamlioglu and nicolo-ribaudo committed Feb 27, 2022
1 parent 7686fc0 commit 5749c16
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 18 deletions.
@@ -1,2 +1,2 @@
// Same as `generic`. Verify that JSX doesn't change things.
<T>(a: T): T => a;
<T,>(a: T): T => a;
32 changes: 31 additions & 1 deletion packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -18,7 +18,7 @@ import {
} from "../../tokenizer/types";
import { types as tc } from "../../tokenizer/context";
import * as N from "../../types";
import type { Position } from "../../util/location";
import { Position, createPositionWithColumnOffset } from "../../util/location";
import type Parser from "../../parser";
import {
type BindingTypes,
Expand Down Expand Up @@ -148,6 +148,8 @@ const TSErrors = makeErrorTemplates(
"A 'set' accessor cannot have rest parameter.",
SetAccesorCannotHaveReturnType:
"A 'set' accessor cannot have a return type annotation.",
SingleTypeParameterWithoutTrailingComma:
"Single type parameter %0 should have a trailing comma. Example usage: <%0,>.",
StaticBlockCannotHaveModifier:
"Static class blocks cannot have any modifier.",
TypeAnnotationAfterAssign:
Expand Down Expand Up @@ -2933,6 +2935,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
// Either way, we're looking at a '<': tt.jsxTagStart or relational.

let typeParameters: ?N.TsTypeParameterDeclaration;
let invalidSingleType: ?N.TsTypeParameter;
state = state || this.state.clone();

const arrow = this.tryParse(abort => {
Expand All @@ -2952,9 +2955,36 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.resetStartLocationFromNode(expr, typeParameters);
}
expr.typeParameters = typeParameters;

// report error if single type parameter used without trailing comma.
if (
this.hasPlugin("jsx") &&
expr.typeParameters.params.length === 1 &&
!expr.typeParameters.extra?.trailingComma
) {
const parameter = expr.typeParameters.params[0];
if (!parameter.constraint) {
// A single type parameter must either have constraints
// or a trailing comma, otherwise it's ambiguous with JSX.
invalidSingleType = parameter;
}
}

return expr;
}, state);

if (invalidSingleType) {
this.raise(
TSErrors.SingleTypeParameterWithoutTrailingComma,
{
at: createPositionWithColumnOffset(invalidSingleType.loc.end, 1),
},
process.env.BABEL_8_BREAKING
? invalidSingleType.name.name
: invalidSingleType.name,
);
}

/*:: invariant(arrow.node != null) */
if (!arrow.error && !arrow.aborted) {
// This error is reported outside of the this.tryParse call so that
Expand Down
@@ -1,6 +1,9 @@
{
"type": "File",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":18,"index":79}},
"errors": [
"SyntaxError: Single type parameter T should have a trailing comma. Example usage: <T,>. (2:3)"
],
"program": {
"type": "Program",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":18,"index":79}},
Expand Down
@@ -1,2 +1,2 @@
// Same as `generic`. Verify that JSX doesn't change things.
<T>(a: T): T => a;
<T,>(a: T): T => a;
@@ -1,27 +1,27 @@
{
"type": "File",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":18,"index":79}},
"start":0,"end":80,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":19,"index":80}},
"program": {
"type": "Program",
"start":0,"end":79,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":18,"index":79}},
"start":0,"end":80,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":19,"index":80}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":61,"end":79,"loc":{"start":{"line":2,"column":0,"index":61},"end":{"line":2,"column":18,"index":79}},
"start":61,"end":80,"loc":{"start":{"line":2,"column":0,"index":61},"end":{"line":2,"column":19,"index":80}},
"expression": {
"type": "ArrowFunctionExpression",
"start":61,"end":78,"loc":{"start":{"line":2,"column":0,"index":61},"end":{"line":2,"column":17,"index":78}},
"start":61,"end":79,"loc":{"start":{"line":2,"column":0,"index":61},"end":{"line":2,"column":18,"index":79}},
"returnType": {
"type": "TSTypeAnnotation",
"start":70,"end":73,"loc":{"start":{"line":2,"column":9,"index":70},"end":{"line":2,"column":12,"index":73}},
"start":71,"end":74,"loc":{"start":{"line":2,"column":10,"index":71},"end":{"line":2,"column":13,"index":74}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":72,"end":73,"loc":{"start":{"line":2,"column":11,"index":72},"end":{"line":2,"column":12,"index":73}},
"start":73,"end":74,"loc":{"start":{"line":2,"column":12,"index":73},"end":{"line":2,"column":13,"index":74}},
"typeName": {
"type": "Identifier",
"start":72,"end":73,"loc":{"start":{"line":2,"column":11,"index":72},"end":{"line":2,"column":12,"index":73},"identifierName":"T"},
"start":73,"end":74,"loc":{"start":{"line":2,"column":12,"index":73},"end":{"line":2,"column":13,"index":74},"identifierName":"T"},
"name": "T"
}
}
Expand All @@ -32,17 +32,17 @@
"params": [
{
"type": "Identifier",
"start":65,"end":69,"loc":{"start":{"line":2,"column":4,"index":65},"end":{"line":2,"column":8,"index":69},"identifierName":"a"},
"start":66,"end":70,"loc":{"start":{"line":2,"column":5,"index":66},"end":{"line":2,"column":9,"index":70},"identifierName":"a"},
"name": "a",
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start":66,"end":69,"loc":{"start":{"line":2,"column":5,"index":66},"end":{"line":2,"column":8,"index":69}},
"start":67,"end":70,"loc":{"start":{"line":2,"column":6,"index":67},"end":{"line":2,"column":9,"index":70}},
"typeAnnotation": {
"type": "TSTypeReference",
"start":68,"end":69,"loc":{"start":{"line":2,"column":7,"index":68},"end":{"line":2,"column":8,"index":69}},
"start":69,"end":70,"loc":{"start":{"line":2,"column":8,"index":69},"end":{"line":2,"column":9,"index":70}},
"typeName": {
"type": "Identifier",
"start":68,"end":69,"loc":{"start":{"line":2,"column":7,"index":68},"end":{"line":2,"column":8,"index":69},"identifierName":"T"},
"start":69,"end":70,"loc":{"start":{"line":2,"column":8,"index":69},"end":{"line":2,"column":9,"index":70},"identifierName":"T"},
"name": "T"
}
}
Expand All @@ -51,12 +51,12 @@
],
"body": {
"type": "Identifier",
"start":77,"end":78,"loc":{"start":{"line":2,"column":16,"index":77},"end":{"line":2,"column":17,"index":78},"identifierName":"a"},
"start":78,"end":79,"loc":{"start":{"line":2,"column":17,"index":78},"end":{"line":2,"column":18,"index":79},"identifierName":"a"},
"name": "a"
},
"typeParameters": {
"type": "TSTypeParameterDeclaration",
"start":61,"end":64,"loc":{"start":{"line":2,"column":0,"index":61},"end":{"line":2,"column":3,"index":64}},
"start":61,"end":65,"loc":{"start":{"line":2,"column":0,"index":61},"end":{"line":2,"column":4,"index":65}},
"params": [
{
"type": "TSTypeParameter",
Expand All @@ -67,7 +67,10 @@
"name": "T"
}
}
]
],
"extra": {
"trailingComma": 63
}
}
},
"leadingComments": [
Expand Down
2 changes: 1 addition & 1 deletion test/jest-light-runner/src/worker-runner.js
Expand Up @@ -4,7 +4,7 @@ import { performance } from "perf_hooks";
import snapshot from "jest-snapshot";
import expect from "expect";
import * as circus from "jest-circus";
import { inspect } from "util"
import { inspect } from "util";

import "./global-setup.js";

Expand Down

0 comments on commit 5749c16

Please sign in to comment.