Merge pull request #6376 from Microsoft/fixFindReferencesOnExports

Fix find all refs in shorthand properties for imports and exports
This commit is contained in:
Mohamed Hegazy 2016-01-13 16:00:10 -08:00
commit c5dd17fa6b
8 changed files with 95 additions and 8 deletions

View file

@ -83,6 +83,7 @@ namespace ts {
getSymbolsInScope,
getSymbolAtLocation,
getShorthandAssignmentValueSymbol,
getExportSpecifierLocalTargetSymbol,
getTypeAtLocation: getTypeOfNode,
typeToString,
getSymbolDisplayBuilder,
@ -15062,11 +15063,18 @@ namespace ts {
// This is necessary as an identifier in short-hand property assignment can contains two meaning:
// property name and property value.
if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) {
return resolveEntityName((<ShorthandPropertyAssignment>location).name, SymbolFlags.Value);
return resolveEntityName((<ShorthandPropertyAssignment>location).name, SymbolFlags.Value | SymbolFlags.Alias);
}
return undefined;
}
/** Returns the target of an export specifier without following aliases */
function getExportSpecifierLocalTargetSymbol(node: ExportSpecifier): Symbol {
return (<ExportDeclaration>node.parent.parent).moduleSpecifier ?
getExternalModuleMember(<ExportDeclaration>node.parent.parent, node) :
resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
}
function getTypeOfNode(node: Node): Type {
if (isInsideWithStatementBody(node)) {
// We cannot answer semantic questions within a with block, do not proceed any further

View file

@ -1725,6 +1725,7 @@ namespace ts {
getSymbolAtLocation(node: Node): Symbol;
getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[];
getShorthandAssignmentValueSymbol(location: Node): Symbol;
getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol;
getTypeAtLocation(node: Node): Type;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;

View file

@ -5517,10 +5517,8 @@ namespace ts {
};
}
function isImportOrExportSpecifierImportSymbol(symbol: Symbol) {
return (symbol.flags & SymbolFlags.Alias) && forEach(symbol.declarations, declaration => {
return declaration.kind === SyntaxKind.ImportSpecifier || declaration.kind === SyntaxKind.ExportSpecifier;
});
function isImportSpecifierSymbol(symbol: Symbol) {
return (symbol.flags & SymbolFlags.Alias) && !!getDeclarationOfKind(symbol, SyntaxKind.ImportSpecifier);
}
function getInternedName(symbol: Symbol, location: Node, declarations: Declaration[]): string {
@ -5964,8 +5962,17 @@ namespace ts {
let result = [symbol];
// If the symbol is an alias, add what it alaises to the list
if (isImportOrExportSpecifierImportSymbol(symbol)) {
result.push(typeChecker.getAliasedSymbol(symbol));
if (isImportSpecifierSymbol(symbol)) {
result.push(typeChecker.getAliasedSymbol(symbol));
}
// For export specifiers, the exported name can be refering to a local symbol, e.g.:
// import {a} from "mod";
// export {a as somethingElse}
// We want the *local* declaration of 'a' as declared in the import,
// *not* as declared within "mod" (or farther)
if (location.parent.kind === SyntaxKind.ExportSpecifier) {
result.push(typeChecker.getExportSpecifierLocalTargetSymbol(<ExportSpecifier>location.parent));
}
// If the location is in a context sensitive location (i.e. in an object literal) try
@ -6055,13 +6062,24 @@ namespace ts {
// If the reference symbol is an alias, check if what it is aliasing is one of the search
// symbols.
if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) {
if (isImportSpecifierSymbol(referenceSymbol)) {
const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol);
if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
return aliasedSymbol;
}
}
// For export specifiers, it can be a local symbol, e.g.
// import {a} from "mod";
// export {a as somethingElse}
// We want the local target of the export (i.e. the import symbol) and not the final target (i.e. "mod".a)
if (referenceLocation.parent.kind === SyntaxKind.ExportSpecifier) {
const aliasedSymbol = typeChecker.getExportSpecifierLocalTargetSymbol(<ExportSpecifier>referenceLocation.parent);
if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
return aliasedSymbol;
}
}
// If the reference location is in an object literal, try to get the contextual type for the
// object literal, lookup the property symbol in the contextual type, and use this symbol to
// compare to our searchSymbol

View file

@ -0,0 +1,10 @@
/// <reference path='fourslash.ts' />
////import [|a|] from "module";
////export { [|a|] };
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View file

@ -0,0 +1,10 @@
/// <reference path='fourslash.ts' />
////import [|foo|] from 'bar';
////const bar = { [|foo|] };
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View file

@ -0,0 +1,10 @@
/// <reference path='fourslash.ts' />
////import * as [|foo|] from 'bar';
////const bar = { [|foo|] };
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View file

@ -0,0 +1,18 @@
/// <reference path='fourslash.ts' />
////declare namespace N {
//// export var x: number;
////}
////declare module "mod" {
//// export = N;
////}
////declare module "test" {
//// import * as [|N|] from "mod";
//// export { [|N|] }; // Renaming N here would rename
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View file

@ -0,0 +1,12 @@
/// <reference path='fourslash.ts' />
////import [|e|] = require("mod4");
////[|e|];
////a = { [|e|] };
////export { [|e|] };
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}