Improve error for unclosed imports and exports (#54634)

Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
Jack Works
2023-06-29 10:22:05 -07:00
committed by GitHub
co-authored by Nathan Shively-Sanders
parent 18e19492be
commit ed5008da68
9 changed files with 57 additions and 106 deletions
+13 -1
View File
@@ -2869,6 +2869,11 @@ namespace Parser {
case ParsingContext.HeritageClauses:
return isHeritageClause();
case ParsingContext.ImportOrExportSpecifiers:
// bail out if the next token is [FromKeyword StringLiteral].
// That means we're in something like `import { from "mod"`. Stop here can give better error message.
if (token() === SyntaxKind.FromKeyword && lookAhead(nextTokenIsStringLiteral)) {
return false;
}
return tokenIsIdentifierOrKeyword(token());
case ParsingContext.JsxAttributes:
return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken;
@@ -3390,7 +3395,11 @@ namespace Parser {
case ParsingContext.TypeArguments: return parseErrorAtCurrentToken(Diagnostics.Type_argument_expected);
case ParsingContext.TupleElementTypes: return parseErrorAtCurrentToken(Diagnostics.Type_expected);
case ParsingContext.HeritageClauses: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_expected);
case ParsingContext.ImportOrExportSpecifiers: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
case ParsingContext.ImportOrExportSpecifiers:
if (token() === SyntaxKind.FromKeyword) {
return parseErrorAtCurrentToken(Diagnostics._0_expected, "}");
}
return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
case ParsingContext.JsxAttributes: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
case ParsingContext.JsxChildren: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
case ParsingContext.AssertEntries: return parseErrorAtCurrentToken(Diagnostics.Identifier_or_string_literal_expected); // AssertionKey.
@@ -7413,6 +7422,9 @@ namespace Parser {
}
}
function nextTokenIsStringLiteral() {
return nextToken() === SyntaxKind.StringLiteral;
}
function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
nextToken();
return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral);
@@ -1,43 +1,28 @@
t2.ts(1,13): error TS2305: Module '"./t1"' has no exported member 'from'.
t2.ts(1,18): error TS1005: ',' expected.
t3.ts(1,10): error TS2305: Module '"./t1"' has no exported member 'from'.
t3.ts(1,15): error TS1005: ',' expected.
t2.ts(1,13): error TS1005: '}' expected.
t3.ts(1,10): error TS1005: '}' expected.
t4.ts(1,17): error TS1005: ',' expected.
t4.ts(1,17): error TS2305: Module '"./t1"' has no exported member 'from'.
t4.ts(1,22): error TS1005: ',' expected.
t5.ts(1,18): error TS2305: Module '"./t1"' has no exported member 'from'.
t5.ts(1,23): error TS1005: ',' expected.
t5.ts(1,18): error TS1005: '}' expected.
==== t1.ts (0 errors) ====
export var x = "x";
==== t2.ts (2 errors) ====
==== t2.ts (1 errors) ====
export { x, from "./t1"
~~~~
!!! error TS2305: Module '"./t1"' has no exported member 'from'.
~~~~~~
!!! error TS1005: ',' expected.
!!! error TS1005: '}' expected.
==== t3.ts (2 errors) ====
==== t3.ts (1 errors) ====
export { from "./t1"
~~~~
!!! error TS2305: Module '"./t1"' has no exported member 'from'.
~~~~~~
!!! error TS1005: ',' expected.
!!! error TS1005: '}' expected.
==== t4.ts (3 errors) ====
==== t4.ts (1 errors) ====
export { x as a from "./t1"
~~~~
!!! error TS1005: ',' expected.
~~~~
!!! error TS2305: Module '"./t1"' has no exported member 'from'.
~~~~~~
!!! error TS1005: ',' expected.
==== t5.ts (2 errors) ====
==== t5.ts (1 errors) ====
export { x as a, from "./t1"
~~~~
!!! error TS2305: Module '"./t1"' has no exported member 'from'.
~~~~~~
!!! error TS1005: ',' expected.
!!! error TS1005: '}' expected.
@@ -23,27 +23,21 @@ exports.x = "x";
//// [t2.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = exports.x = void 0;
exports.x = void 0;
var t1_1 = require("./t1");
Object.defineProperty(exports, "x", { enumerable: true, get: function () { return t1_1.x; } });
Object.defineProperty(exports, "from", { enumerable: true, get: function () { return t1_1.from; } });
//// [t3.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = void 0;
var t1_1 = require("./t1");
Object.defineProperty(exports, "from", { enumerable: true, get: function () { return t1_1.from; } });
//// [t4.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = exports.a = void 0;
exports.a = void 0;
var t1_1 = require("./t1");
Object.defineProperty(exports, "a", { enumerable: true, get: function () { return t1_1.x; } });
Object.defineProperty(exports, "from", { enumerable: true, get: function () { return t1_1.from; } });
//// [t5.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = exports.a = void 0;
exports.a = void 0;
var t1_1 = require("./t1");
Object.defineProperty(exports, "a", { enumerable: true, get: function () { return t1_1.x; } });
Object.defineProperty(exports, "from", { enumerable: true, get: function () { return t1_1.from; } });
@@ -7,21 +7,18 @@ export var x = "x";
=== t2.ts ===
export { x, from "./t1"
>x : Symbol(x, Decl(t2.ts, 0, 8))
>from : Symbol(from, Decl(t2.ts, 0, 11))
=== t3.ts ===
export { from "./t1"
>from : Symbol(from, Decl(t3.ts, 0, 8))
=== t4.ts ===
export { x as a from "./t1"
>x : Symbol(x, Decl(t1.ts, 0, 10))
>a : Symbol(a, Decl(t4.ts, 0, 8))
>from : Symbol(from, Decl(t4.ts, 0, 15))
=== t5.ts ===
export { x as a, from "./t1"
>x : Symbol(x, Decl(t1.ts, 0, 10))
>a : Symbol(a, Decl(t5.ts, 0, 8))
>from : Symbol(from, Decl(t5.ts, 0, 16))
@@ -8,21 +8,18 @@ export var x = "x";
=== t2.ts ===
export { x, from "./t1"
>x : string
>from : any
=== t3.ts ===
export { from "./t1"
>from : any
=== t4.ts ===
export { x as a from "./t1"
>x : string
>a : string
>from : any
=== t5.ts ===
export { x as a, from "./t1"
>x : string
>a : string
>from : any
@@ -1,56 +1,32 @@
t2.ts(1,10): error TS2304: Cannot find name 'x'.
t2.ts(1,13): error TS2304: Cannot find name 'from'.
t2.ts(2,5): error TS1005: ',' expected.
t3.ts(1,10): error TS2304: Cannot find name 'from'.
t3.ts(2,5): error TS1005: ',' expected.
t4.ts(1,10): error TS2304: Cannot find name 'x'.
t2.ts(1,13): error TS1005: '}' expected.
t3.ts(1,10): error TS1005: '}' expected.
t4.ts(1,17): error TS1005: ',' expected.
t4.ts(1,17): error TS2304: Cannot find name 'from'.
t4.ts(2,5): error TS1005: ',' expected.
t5.ts(1,10): error TS2304: Cannot find name 'x'.
t5.ts(1,18): error TS2304: Cannot find name 'from'.
t5.ts(2,5): error TS1005: ',' expected.
t5.ts(1,18): error TS1005: '}' expected.
==== t1.ts (0 errors) ====
export var x = "x";
==== t2.ts (3 errors) ====
==== t2.ts (1 errors) ====
export { x, from
~
!!! error TS2304: Cannot find name 'x'.
~~~~
!!! error TS2304: Cannot find name 'from'.
!!! error TS1005: '}' expected.
"./t1";
~~~~~~
!!! error TS1005: ',' expected.
==== t3.ts (2 errors) ====
==== t3.ts (1 errors) ====
export { from
~~~~
!!! error TS2304: Cannot find name 'from'.
!!! error TS1005: '}' expected.
"./t1";
~~~~~~
!!! error TS1005: ',' expected.
==== t4.ts (4 errors) ====
==== t4.ts (1 errors) ====
export { x as a from
~
!!! error TS2304: Cannot find name 'x'.
~~~~
!!! error TS1005: ',' expected.
~~~~
!!! error TS2304: Cannot find name 'from'.
"./t1";
~~~~~~
!!! error TS1005: ',' expected.
==== t5.ts (3 errors) ====
==== t5.ts (1 errors) ====
export { x as a, from
~
!!! error TS2304: Cannot find name 'x'.
~~~~
!!! error TS2304: Cannot find name 'from'.
"./t1";
~~~~~~
!!! error TS1005: ',' expected.
!!! error TS1005: '}' expected.
"./t1";
@@ -27,20 +27,21 @@ exports.x = "x";
//// [t2.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = exports.x = void 0;
"./t1";
exports.x = void 0;
var t1_1 = require("./t1");
Object.defineProperty(exports, "x", { enumerable: true, get: function () { return t1_1.x; } });
//// [t3.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = void 0;
"./t1";
//// [t4.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = exports.a = void 0;
"./t1";
exports.a = void 0;
var t1_1 = require("./t1");
Object.defineProperty(exports, "a", { enumerable: true, get: function () { return t1_1.x; } });
//// [t5.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.from = exports.a = void 0;
"./t1";
exports.a = void 0;
var t1_1 = require("./t1");
Object.defineProperty(exports, "a", { enumerable: true, get: function () { return t1_1.x; } });
@@ -7,26 +7,24 @@ export var x = "x";
=== t2.ts ===
export { x, from
>x : Symbol(x, Decl(t2.ts, 0, 8))
>from : Symbol(from, Decl(t2.ts, 0, 11))
"./t1";
=== t3.ts ===
export { from
>from : Symbol(from, Decl(t3.ts, 0, 8))
export { from
"./t1";
=== t4.ts ===
export { x as a from
>x : Symbol(x, Decl(t1.ts, 0, 10))
>a : Symbol(a, Decl(t4.ts, 0, 8))
>from : Symbol(from, Decl(t4.ts, 0, 15))
"./t1";
=== t5.ts ===
export { x as a, from
>x : Symbol(x, Decl(t1.ts, 0, 10))
>a : Symbol(a, Decl(t5.ts, 0, 8))
>from : Symbol(from, Decl(t5.ts, 0, 16))
"./t1";
@@ -7,34 +7,25 @@ export var x = "x";
=== t2.ts ===
export { x, from
>x : any
>from : any
>x : string
"./t1";
>"./t1" : "./t1"
=== t3.ts ===
export { from
>from : any
export { from
"./t1";
>"./t1" : "./t1"
=== t4.ts ===
export { x as a from
>x : any
>a : any
>from : any
>x : string
>a : string
"./t1";
>"./t1" : "./t1"
=== t5.ts ===
export { x as a, from
>x : any
>a : any
>from : any
>x : string
>a : string
"./t1";
>"./t1" : "./t1"