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]);