Merge pull request #6376 from Microsoft/fixFindReferencesOnExports
Fix find all refs in shorthand properties for imports and exports
This commit is contained in:
commit
c5dd17fa6b
8 changed files with 95 additions and 8 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,10 +5962,19 @@ namespace ts {
|
|||
let result = [symbol];
|
||||
|
||||
// If the symbol is an alias, add what it alaises to the list
|
||||
if (isImportOrExportSpecifierImportSymbol(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
|
||||
// to get a contextual type for it, and add the property symbol from the contextual
|
||||
// type to the search set
|
||||
|
@ -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
|
||||
|
|
10
tests/cases/fourslash/renameImportAndExport.ts
Normal file
10
tests/cases/fourslash/renameImportAndExport.ts
Normal 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);
|
||||
}
|
10
tests/cases/fourslash/renameImportAndShorthand.ts
Normal file
10
tests/cases/fourslash/renameImportAndShorthand.ts
Normal 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);
|
||||
}
|
10
tests/cases/fourslash/renameImportNamespaceAndShorthand.ts
Normal file
10
tests/cases/fourslash/renameImportNamespaceAndShorthand.ts
Normal 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);
|
||||
}
|
18
tests/cases/fourslash/renameImportOfExportEquals.ts
Normal file
18
tests/cases/fourslash/renameImportOfExportEquals.ts
Normal 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);
|
||||
}
|
12
tests/cases/fourslash/renameImportRequire.ts
Normal file
12
tests/cases/fourslash/renameImportRequire.ts
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue