add related error span for default exports (#25396)

* add related error span for default exports

* accept baseline

* stash

* accept baseline and fix lint

* update testcase

* Add missing semicolon
This commit is contained in:
Wenlu Wang
2019-03-12 13:15:14 -07:00
committed by Wesley Wigham
parent bd27296ba6
commit d2476759e2
20 changed files with 148 additions and 18 deletions
+19 -6
View File
@@ -403,13 +403,15 @@ namespace ts {
messageNeedsName = false;
}
if (symbol.declarations && symbol.declarations.length) {
let multipleDefaultExports = false;
if (length(symbol.declarations)) {
// If the current node is a default export of some sort, then check if
// there are any other default exports that we need to error on.
// We'll know whether we have other default exports depending on if `symbol` already has a declaration list set.
if (isDefaultExport) {
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
messageNeedsName = false;
multipleDefaultExports = true;
}
else {
// This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration.
@@ -420,15 +422,26 @@ namespace ts {
(node.kind === SyntaxKind.ExportAssignment && !(<ExportAssignment>node).isExportEquals)) {
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
messageNeedsName = false;
multipleDefaultExports = true;
}
}
}
const addError = (decl: Declaration): void => {
file.bindDiagnostics.push(createDiagnosticForNode(getNameOfDeclaration(decl) || decl, message, messageNeedsName ? getDisplayName(decl) : undefined));
};
forEach(symbol.declarations, addError);
addError(node);
const declarationName = getNameOfDeclaration(node) || node;
const relatedInformation: DiagnosticRelatedInformation[] = [];
forEach(symbol.declarations, (declaration, index) => {
const decl = getNameOfDeclaration(declaration) || declaration;
const diag = createDiagnosticForNode(decl, message, messageNeedsName ? getDisplayName(declaration) : undefined);
file.bindDiagnostics.push(
multipleDefaultExports ? addRelatedInfo(diag, createDiagnosticForNode(declarationName, index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here)) : diag
);
if (multipleDefaultExports) {
relatedInformation.push(createDiagnosticForNode(decl, Diagnostics.The_first_export_default_is_here));
}
});
const diag = createDiagnosticForNode(declarationName, message, messageNeedsName ? getDisplayName(node) : undefined);
file.bindDiagnostics.push(multipleDefaultExports ? addRelatedInfo(diag, ...relatedInformation) : diag);
symbol = createSymbol(SymbolFlags.None, name);
}
-8
View File
@@ -792,14 +792,6 @@ namespace ts {
}
}
function addRelatedInfo(diagnostic: Diagnostic, ...relatedInformation: [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]]) {
if (!diagnostic.relatedInformation) {
diagnostic.relatedInformation = [];
}
diagnostic.relatedInformation.push(...relatedInformation);
return diagnostic;
}
function error(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic {
const diagnostic = location
? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3)
+8
View File
@@ -2593,6 +2593,14 @@
"category": "Error",
"code": 2751
},
"The first export default is here.": {
"category": "Error",
"code": 2752
},
"Another export default is here.": {
"category": "Error",
"code": 2753
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
+8
View File
@@ -8516,6 +8516,14 @@ namespace ts {
return arr.slice(index);
}
export function addRelatedInfo<T extends Diagnostic>(diagnostic: T, ...relatedInformation: DiagnosticRelatedInformation[]): T {
if (!diagnostic.relatedInformation) {
diagnostic.relatedInformation = [];
}
diagnostic.relatedInformation.push(...relatedInformation);
return diagnostic;
}
export function minAndMax<T>(arr: ReadonlyArray<T>, getValue: (value: T) => number): { readonly min: number, readonly max: number } {
Debug.assert(arr.length !== 0);
let min = getValue(arr[0]);
@@ -6,7 +6,9 @@ tests/cases/compiler/duplicateDefaultExport.ts(2,1): error TS2528: A module cann
export default 0;
~~~~~~~~~~~~~~~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/compiler/duplicateDefaultExport.ts:2:1: The first export default is here.
export default function() {}
~~~~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/compiler/duplicateDefaultExport.ts:1:1: Another export default is here.
@@ -6,8 +6,10 @@ tests/cases/compiler/exportDefaultAlias_excludesEverything.ts(3,16): error TS252
export default interface A {}
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/compiler/exportDefaultAlias_excludesEverything.ts:3:16: Another export default is here.
interface B {}
export default B;
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/compiler/exportDefaultAlias_excludesEverything.ts:1:26: The first export default is here.
@@ -9,12 +9,14 @@ tests/cases/compiler/a.js(3,20): error TS2652: Merged declaration 'a' cannot inc
export default class a {
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/compiler/a.js:3:15: Another export default is here.
~
!!! error TS2652: Merged declaration 'a' cannot include a default export declaration. Consider adding a separate 'export default a' declaration instead.
}
export default var a = 10;
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/compiler/a.js:1:22: The first export default is here.
~~~
!!! error TS1109: Expression expected.
~
@@ -1,18 +1,24 @@
tests/cases/conformance/es6/modules/m1.ts(1,22): error TS2528: A module cannot have multiple default exports.
tests/cases/conformance/es6/modules/m1.ts(5,25): error TS2528: A module cannot have multiple default exports.
tests/cases/conformance/es6/modules/m1.ts(5,25): error TS2528: A module cannot have multiple default exports.
tests/cases/conformance/es6/modules/m1.ts(10,16): error TS2528: A module cannot have multiple default exports.
==== tests/cases/conformance/es6/modules/m1.ts (3 errors) ====
==== tests/cases/conformance/es6/modules/m1.ts (4 errors) ====
export default class foo {
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/es6/modules/m1.ts:5:25: The first export default is here.
}
export default function bar() {
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/es6/modules/m1.ts:1:22: Another export default is here.
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/es6/modules/m1.ts:10:16: Another export default is here.
}
@@ -20,6 +26,7 @@ tests/cases/conformance/es6/modules/m1.ts(10,16): error TS2528: A module cannot
export default x;
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/es6/modules/m1.ts:5:25: The first export default is here.
==== tests/cases/conformance/es6/modules/m2.ts (0 errors) ====
import Entity from "./m1"
@@ -6,9 +6,11 @@ tests/cases/conformance/es6/modules/multipleDefaultExports03.ts(4,22): error TS2
export default class C {
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/es6/modules/multipleDefaultExports03.ts:4:22: Another export default is here.
}
export default class C {
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/es6/modules/multipleDefaultExports03.ts:1:22: The first export default is here.
}
@@ -0,0 +1,25 @@
tests/cases/conformance/es6/modules/multipleDefaultExports05.ts(1,22): error TS2528: A module cannot have multiple default exports.
tests/cases/conformance/es6/modules/multipleDefaultExports05.ts(1,22): error TS2528: A module cannot have multiple default exports.
tests/cases/conformance/es6/modules/multipleDefaultExports05.ts(3,22): error TS2528: A module cannot have multiple default exports.
tests/cases/conformance/es6/modules/multipleDefaultExports05.ts(5,22): error TS2528: A module cannot have multiple default exports.
==== tests/cases/conformance/es6/modules/multipleDefaultExports05.ts (4 errors) ====
export default class AA1 {}
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/es6/modules/multipleDefaultExports05.ts:3:22: Another export default is here.
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/es6/modules/multipleDefaultExports05.ts:5:22: Another export default is here.
export default class BB1 {}
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/es6/modules/multipleDefaultExports05.ts:1:22: The first export default is here.
export default class CC1 {}
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/es6/modules/multipleDefaultExports05.ts:1:22: The first export default is here.
@@ -0,0 +1,29 @@
//// [multipleDefaultExports05.ts]
export default class AA1 {}
export default class BB1 {}
export default class CC1 {}
//// [multipleDefaultExports05.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var AA1 = /** @class */ (function () {
function AA1() {
}
return AA1;
}());
exports.default = AA1;
var BB1 = /** @class */ (function () {
function BB1() {
}
return BB1;
}());
exports.default = BB1;
var CC1 = /** @class */ (function () {
function CC1() {
}
return CC1;
}());
exports.default = CC1;
@@ -0,0 +1,10 @@
=== tests/cases/conformance/es6/modules/multipleDefaultExports05.ts ===
export default class AA1 {}
>AA1 : Symbol(AA1, Decl(multipleDefaultExports05.ts, 0, 0))
export default class BB1 {}
>BB1 : Symbol(BB1, Decl(multipleDefaultExports05.ts, 0, 27))
export default class CC1 {}
>CC1 : Symbol(CC1, Decl(multipleDefaultExports05.ts, 2, 27))
@@ -0,0 +1,10 @@
=== tests/cases/conformance/es6/modules/multipleDefaultExports05.ts ===
export default class AA1 {}
>AA1 : AA1
export default class BB1 {}
>BB1 : import("tests/cases/conformance/es6/modules/multipleDefaultExports05").default
export default class CC1 {}
>CC1 : import("tests/cases/conformance/es6/modules/multipleDefaultExports05").default
@@ -6,6 +6,7 @@ tests/cases/conformance/externalModules/multipleExportDefault1.ts(5,1): error TS
export default function Foo (){
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/externalModules/multipleExportDefault1.ts:5:1: Another export default is here.
}
@@ -16,4 +17,5 @@ tests/cases/conformance/externalModules/multipleExportDefault1.ts(5,1): error TS
};
~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/externalModules/multipleExportDefault1.ts:1:25: The first export default is here.
@@ -10,9 +10,11 @@ tests/cases/conformance/externalModules/multipleExportDefault2.ts(5,25): error T
};
~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/externalModules/multipleExportDefault2.ts:5:25: The first export default is here.
export default function Foo() { }
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/externalModules/multipleExportDefault2.ts:1:1: Another export default is here.
@@ -10,9 +10,11 @@ tests/cases/conformance/externalModules/multipleExportDefault3.ts(5,22): error T
};
~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/externalModules/multipleExportDefault3.ts:5:22: Another export default is here.
export default class C { }
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/externalModules/multipleExportDefault3.ts:1:1: The first export default is here.
@@ -6,6 +6,7 @@ tests/cases/conformance/externalModules/multipleExportDefault4.ts(3,1): error TS
export default class C { }
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/externalModules/multipleExportDefault4.ts:3:1: Another export default is here.
export default {
~~~~~~~~~~~~~~~~
@@ -13,4 +14,5 @@ tests/cases/conformance/externalModules/multipleExportDefault4.ts(3,1): error TS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
};
~~
!!! error TS2528: A module cannot have multiple default exports.
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/externalModules/multipleExportDefault4.ts:1:22: The first export default is here.
@@ -6,6 +6,8 @@ tests/cases/conformance/externalModules/multipleExportDefault5.ts(2,22): error T
export default function bar() { }
~~~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/externalModules/multipleExportDefault5.ts:2:22: Another export default is here.
export default class C {}
~
!!! error TS2528: A module cannot have multiple default exports.
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/externalModules/multipleExportDefault5.ts:1:25: The first export default is here.
@@ -10,6 +10,7 @@ tests/cases/conformance/externalModules/multipleExportDefault6.ts(5,1): error TS
}
~
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2753 tests/cases/conformance/externalModules/multipleExportDefault6.ts:5:1: Another export default is here.
export default {
~~~~~~~~~~~~~~~~
@@ -17,4 +18,5 @@ tests/cases/conformance/externalModules/multipleExportDefault6.ts(5,1): error TS
~~~~~~~~~~
}
~
!!! error TS2528: A module cannot have multiple default exports.
!!! error TS2528: A module cannot have multiple default exports.
!!! related TS2752 tests/cases/conformance/externalModules/multipleExportDefault6.ts:1:1: The first export default is here.
@@ -0,0 +1,8 @@
// @module: commonjs
// @target: ES5
export default class AA1 {}
export default class BB1 {}
export default class CC1 {}