Improve error span:duplicate symbols cross-js/ts

when the JS symbol is a JS initializer
This commit is contained in:
Nathan Shively-Sanders 2018-03-08 10:33:38 -08:00
parent 04ceb3d9bd
commit 35730f2879
3 changed files with 21 additions and 6 deletions

View File

@ -911,10 +911,12 @@ namespace ts {
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
: Diagnostics.Duplicate_identifier_0;
forEach(source.declarations, node => {
error(getNameOfDeclaration(node) || node, message, symbolToString(source));
const errorNode = (getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? getOuterNameOfJsInitializer(node) : getNameOfDeclaration(node)) || node;
error(errorNode, message, symbolToString(source));
});
forEach(target.declarations, node => {
error(getNameOfDeclaration(node) || node, message, symbolToString(source));
const errorNode = (getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? getOuterNameOfJsInitializer(node) : getNameOfDeclaration(node)) || node;
error(errorNode, message, symbolToString(source));
});
}
}

View File

@ -1522,13 +1522,13 @@ namespace ts {
*
* This function returns the provided initializer, or undefined if it is not valid.
*/
export function getJavascriptInitializer(initializer: Expression, isPrototypeAssignment: boolean) {
export function getJavascriptInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression {
if (isCallExpression(initializer)) {
const e = skipParentheses(initializer.expression);
return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined;
}
if (initializer.kind === SyntaxKind.FunctionExpression || initializer.kind === SyntaxKind.ClassExpression) {
return initializer;
return initializer as Expression;
}
if (isObjectLiteralExpression(initializer) && (initializer.properties.length === 0 || isPrototypeAssignment)) {
return initializer;
@ -1550,6 +1550,19 @@ namespace ts {
}
}
/** Given a Javascript initializer, return the outer name. That is, the lhs of the assignment or the declaration name. */
export function getOuterNameOfJsInitializer(node: Declaration): DeclarationName | undefined {
if (isBinaryExpression(node.parent)) {
const parent = (node.parent.operatorToken.kind === SyntaxKind.BarBarToken && isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent;
if (parent.operatorToken.kind === SyntaxKind.EqualsToken && isIdentifier(parent.left)) {
return parent.left;
}
}
else if (isVariableDeclaration(node.parent)) {
return node.parent.name;
}
}
/**
* Is the 'declared' name the same as the one in the initializer?
* @return true for identical entity names, as well as ones where the initializer is prefixed with

View File

@ -1,6 +1,6 @@
error TS5055: Cannot write file 'tests/cases/conformance/salsa/a.js' because it would overwrite input file.
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
tests/cases/conformance/salsa/a.js(1,23): error TS2300: Duplicate identifier 'x'.
tests/cases/conformance/salsa/a.js(1,10): error TS2300: Duplicate identifier 'x'.
tests/cases/conformance/salsa/b.ts(1,5): error TS2300: Duplicate identifier 'x'.
@ -8,7 +8,7 @@ tests/cases/conformance/salsa/b.ts(1,5): error TS2300: Duplicate identifier 'x'.
!!! error TS5055: Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
==== tests/cases/conformance/salsa/a.js (1 errors) ====
var /*1*/x = function foo() {
~~~
~
!!! error TS2300: Duplicate identifier 'x'.
}
x.a = function bar() {