Skip to content

Commit

Permalink
Do not parse template arguments in JavaScript files.
Browse files Browse the repository at this point in the history
Fixes #36662.
  • Loading branch information
mprobst committed Feb 7, 2020
1 parent 2cc5856 commit f308ac1
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 38 deletions.
10 changes: 8 additions & 2 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4540,7 +4540,7 @@ namespace ts {
}

const tagName = parseJsxElementName();
const typeArguments = tryParseTypeArguments();
const typeArguments = (contextFlags & NodeFlags.JavaScriptFile) === 0 ? tryParseTypeArguments() : undefined;
const attributes = parseJsxAttributes();

let node: JsxOpeningLikeElement;
Expand Down Expand Up @@ -4797,7 +4797,8 @@ namespace ts {
const questionDotToken = parseOptionalToken(SyntaxKind.QuestionDotToken);

// handle 'foo<<T>()'
if (token() === SyntaxKind.LessThanToken || token() === SyntaxKind.LessThanLessThanToken) {
// parse template arguments only in TypeScript files (not in JavaScript files).
if ((contextFlags & NodeFlags.JavaScriptFile) === 0 && (token() === SyntaxKind.LessThanToken || token() === SyntaxKind.LessThanLessThanToken)) {
// See if this is the start of a generic invocation. If so, consume it and
// keep checking for postfix expressions. Otherwise, it's just a '<' that's
// part of an arithmetic expression. Break out so we consume it higher in the
Expand Down Expand Up @@ -4854,6 +4855,11 @@ namespace ts {
}

function parseTypeArgumentsInExpression() {
if ((contextFlags & NodeFlags.JavaScriptFile) !== 0) {
// TypeArguments must not be parsed in JavaScript files to avoid ambiguity with binary operators.
return undefined;
}

if (reScanLessThanToken() !== SyntaxKind.LessThanToken) {
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Syntactic Diagnostics for file '/tests/cases/fourslash/getJavaScriptSyntacticDiagnostics14.ts':
/tests/cases/fourslash/a.js(1,5): error TS8011: Type arguments can only be used in TypeScript files.
/tests/cases/fourslash/a.js(1,13): error TS1109: Expression expected.


==== /tests/cases/fourslash/a.js (1 errors) ====
Foo<number>();
~~~~~~
!!! error TS8011: Type arguments can only be used in TypeScript files.
~
!!! error TS1109: Expression expected.
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
tests/cases/compiler/a.jsx(1,5): error TS8011: Type arguments can only be used in TypeScript files.
tests/cases/compiler/a.jsx(2,5): error TS8011: Type arguments can only be used in TypeScript files.
tests/cases/compiler/a.jsx(3,6): error TS8011: Type arguments can only be used in TypeScript files.
tests/cases/compiler/a.jsx(4,6): error TS8011: Type arguments can only be used in TypeScript files.
tests/cases/compiler/a.jsx(1,13): error TS1109: Expression expected.
tests/cases/compiler/a.jsx(4,5): error TS1003: Identifier expected.
tests/cases/compiler/a.jsx(4,14): error TS17002: Expected corresponding JSX closing tag for 'number'.
tests/cases/compiler/a.jsx(4,20): error TS2657: JSX expressions must have one parent element.
tests/cases/compiler/a.jsx(5,5): error TS1003: Identifier expected.
tests/cases/compiler/a.jsx(5,6): error TS17008: JSX element 'number' has no corresponding closing tag.
tests/cases/compiler/a.jsx(6,1): error TS1005: '</' expected.


==== tests/cases/compiler/a.jsx (4 errors) ====
==== tests/cases/compiler/a.jsx (7 errors) ====
Foo<number>();
~~~~~~
!!! error TS8011: Type arguments can only be used in TypeScript files.
~
!!! error TS1109: Expression expected.
Foo<number>(1);
Foo<number>``;
~~~~~~
!!! error TS8011: Type arguments can only be used in TypeScript files.
<Foo<number>></Foo>;
~~~~~~
!!! error TS8011: Type arguments can only be used in TypeScript files.
~
!!! error TS1003: Identifier expected.
~~~~~~
!!! error TS17002: Expected corresponding JSX closing tag for 'number'.
~
!!! error TS2657: JSX expressions must have one parent element.
<Foo<number>/>;
~
!!! error TS1003: Identifier expected.
~~~~~~
!!! error TS8011: Type arguments can only be used in TypeScript files.
!!! error TS17008: JSX element 'number' has no corresponding closing tag.


!!! error TS1005: '</' expected.
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
//// [a.jsx]
Foo<number>();
Foo<number>(1);
Foo<number>``;
<Foo<number>></Foo>;
<Foo<number>/>;
<Foo<number>/>;


//// [a.js]
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
Foo();
Foo(__makeTemplateObject([""], [""]));
<Foo></Foo>;
<Foo />;
Foo < number > ();
Foo < number > (1);
Foo < number > "";
<Foo />, <number>></Foo>;
<Foo />, <number>/>;
</>;
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
tests/cases/conformance/jsx/file.jsx(4,17): error TS8011: Type arguments can only be used in TypeScript files.
tests/cases/conformance/jsx/file.jsx(4,9): error TS2695: Left side of comma operator is unused and has no side effects.
tests/cases/conformance/jsx/file.jsx(4,16): error TS1003: Identifier expected.
tests/cases/conformance/jsx/file.jsx(4,17): error TS2693: 'Prop' only refers to a type, but is being used as a value here.
tests/cases/conformance/jsx/file.jsx(4,17): error TS17008: JSX element 'Prop' has no corresponding closing tag.
tests/cases/conformance/jsx/file.jsx(5,1): error TS1005: '</' expected.


==== tests/cases/conformance/jsx/component.d.ts (0 errors) ====
Expand All @@ -12,11 +16,19 @@ tests/cases/conformance/jsx/file.jsx(4,17): error TS8011: Type arguments can onl
b: string
}

==== tests/cases/conformance/jsx/file.jsx (1 errors) ====
==== tests/cases/conformance/jsx/file.jsx (5 errors) ====
import { MyComp, Prop } from "./component";
import * as React from "react";

let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
~~~~~~~
!!! error TS2695: Left side of comma operator is unused and has no side effects.
~
!!! error TS1003: Identifier expected.
~~~~
!!! error TS8011: Type arguments can only be used in TypeScript files.

!!! error TS2693: 'Prop' only refers to a type, but is being used as a value here.
~~~~
!!! error TS17008: JSX element 'Prop' has no corresponding closing tag.


!!! error TS1005: '</' expected.
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
exports.__esModule = true;
var component_1 = require("./component");
var React = require("react");
var x = <component_1.MyComp a={10} b="hi"/>; // error, no type arguments in js
var x = <component_1.MyComp />, <Prop> a={10} b="hi" />; // error, no type arguments in js
</>;
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,4 @@ import * as React from "react";
let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
>x : Symbol(x, Decl(file.jsx, 3, 3))
>MyComp : Symbol(MyComp, Decl(file.jsx, 0, 8))
>Prop : Symbol(Prop, Decl(file.jsx, 0, 16))
>a : Symbol(a, Decl(file.jsx, 3, 21))
>b : Symbol(b, Decl(file.jsx, 3, 28))

Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ import * as React from "react";

let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
>x : JSX.Element
><MyComp<Prop> a={10} b="hi" /> : JSX.Element
><MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js : JSX.Element
><MyComp : JSX.Element
>MyComp : typeof MyComp
>a : number
><Prop> a={10} b="hi" />; // error, no type arguments in js : JSX.Element
>Prop : any
>10 : 10
>b : string

> : any

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// @noTypesAndSymbols: true
// @filename: a.jsx
Foo<number>();
Foo<number>(1);
Foo<number>``;
<Foo<number>></Foo>;
<Foo<number>/>;
<Foo<number>/>;

0 comments on commit f308ac1

Please sign in to comment.