mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-11 05:32:14 -05:00
Support find references on the new import/export syntax
This commit is contained in:
@@ -3986,7 +3986,7 @@ module ts {
|
||||
var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
|
||||
|
||||
// Get the text to search for, we need to normalize it as external module names will have quote
|
||||
var declaredName = getDeclaredName(symbol);
|
||||
var declaredName = getDeclaredName(symbol, node);
|
||||
|
||||
// Try to get the smallest valid scope that we can limit our search to;
|
||||
// otherwise we'll need to search globally (i.e. include each file).
|
||||
@@ -4003,7 +4003,7 @@ module ts {
|
||||
getReferencesInNode(sourceFiles[0], symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result);
|
||||
}
|
||||
else {
|
||||
var internedName = getInternedName(symbol, declarations)
|
||||
var internedName = getInternedName(symbol, node, declarations)
|
||||
forEach(sourceFiles, sourceFile => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
@@ -4023,13 +4023,51 @@ module ts {
|
||||
|
||||
return result;
|
||||
|
||||
function getDeclaredName(symbol: Symbol) {
|
||||
function isImportOrExportSpecifierName(location: Node): boolean {
|
||||
return location.parent &&
|
||||
(location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) &&
|
||||
(<ImportOrExportSpecifier>location.parent).propertyName === location;
|
||||
}
|
||||
|
||||
function isImportOrExportSpecifierImportSymbol(symbol: Symbol) {
|
||||
return (symbol.flags & SymbolFlags.Import) && forEach(symbol.declarations, declaration => {
|
||||
return declaration.kind === SyntaxKind.ImportSpecifier || declaration.kind === SyntaxKind.ExportSpecifier;
|
||||
});
|
||||
}
|
||||
|
||||
function getDeclaredName(symbol: Symbol, location: Node) {
|
||||
// Special case for function expressions, whose names are solely local to their bodies.
|
||||
var functionExpression = forEach(symbol.declarations, d => d.kind === SyntaxKind.FunctionExpression ? <FunctionExpression>d : undefined);
|
||||
|
||||
// When a name gets interned into a SourceFile's 'identifiers' Map,
|
||||
// its name is escaped and stored in the same way its symbol name/identifier
|
||||
// name should be stored. Function expressions, however, are a special case,
|
||||
// because despite sometimes having a name, the binder unconditionally binds them
|
||||
// to a symbol with the name "__function".
|
||||
if (functionExpression && functionExpression.name) {
|
||||
var name = functionExpression.name.text;
|
||||
}
|
||||
|
||||
// If this is an export or import specifier it could have been renamed using the as syntax.
|
||||
// if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name)
|
||||
// so check for the propertyName.
|
||||
if (isImportOrExportSpecifierName(location)) {
|
||||
return location.getText();
|
||||
}
|
||||
|
||||
var name = typeInfoResolver.symbolToString(symbol);
|
||||
|
||||
return stripQuotes(name);
|
||||
}
|
||||
|
||||
function getInternedName(symbol: Symbol, declarations: Declaration[]): string {
|
||||
function getInternedName(symbol: Symbol, location: Node, declarations: Declaration[]): string {
|
||||
// If this is an export or import specifier it could have been renamed using the as syntax.
|
||||
// if so we want to search for whatever under the cursor, the symbol is pointing to the alias (name)
|
||||
// so check for the propertyName.
|
||||
if (isImportOrExportSpecifierName(location)) {
|
||||
return location.getText();
|
||||
}
|
||||
|
||||
// Special case for function expressions, whose names are solely local to their bodies.
|
||||
var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? <FunctionExpression>d : undefined);
|
||||
|
||||
@@ -4058,16 +4096,22 @@ module ts {
|
||||
|
||||
function getSymbolScope(symbol: Symbol): Node {
|
||||
// If this is private property or method, the scope is the containing class
|
||||
if (symbol.getFlags() && (SymbolFlags.Property | SymbolFlags.Method)) {
|
||||
if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) {
|
||||
var privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined);
|
||||
if (privateDeclaration) {
|
||||
return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
// If the symbol is an import we would like to find it if we are looking for what it imports.
|
||||
// So consider it visibile outside its declaration scope.
|
||||
if (symbol.flags & SymbolFlags.Import) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// if this symbol is visible from its parent container, e.g. exported, then bail out
|
||||
// if symbol correspond to the union property - bail out
|
||||
if (symbol.parent || (symbol.getFlags() & SymbolFlags.UnionProperty)) {
|
||||
if (symbol.parent || (symbol.flags & SymbolFlags.UnionProperty)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -4422,6 +4466,11 @@ module ts {
|
||||
// The search set contains at least the current symbol
|
||||
var result = [symbol];
|
||||
|
||||
// If the symbol is an alias, add what it alaises to the list
|
||||
if (isImportOrExportSpecifierImportSymbol(symbol)) {
|
||||
result.push(typeInfoResolver.getAliasedSymbol(symbol));
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -4498,6 +4547,13 @@ module ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the reference symbol is an alias, check if what it is aliasing is one of the search
|
||||
// symbols.
|
||||
if (isImportOrExportSpecifierImportSymbol(referenceSymbol) &&
|
||||
searchSymbols.indexOf(typeInfoResolver.getAliasedSymbol(referenceSymbol)) >= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
29
tests/cases/fourslash/findAllRefsOnImportAliases.ts
Normal file
29
tests/cases/fourslash/findAllRefsOnImportAliases.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//@Filename: a.ts
|
||||
////export class /*1*/Class{
|
||||
////}
|
||||
|
||||
//@Filename: b.ts
|
||||
////import { /*2*/Class } from "a";
|
||||
////
|
||||
////var c = new /*3*/Class();
|
||||
|
||||
//@Filename: c.ts
|
||||
////export { /*4*/Class } from "a";
|
||||
|
||||
goTo.file("a.ts");
|
||||
goTo.marker("1");
|
||||
verify.referencesCountIs(4);
|
||||
|
||||
goTo.file("b.ts");
|
||||
goTo.marker("2");
|
||||
verify.referencesCountIs(4);
|
||||
|
||||
goTo.marker("3");
|
||||
verify.referencesCountIs(4);
|
||||
|
||||
goTo.file("c.ts");
|
||||
goTo.marker("4");
|
||||
verify.referencesCountIs(4);
|
||||
|
||||
31
tests/cases/fourslash/findAllRefsOnImportAliases2.ts
Normal file
31
tests/cases/fourslash/findAllRefsOnImportAliases2.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
//@Filename: a.ts
|
||||
////export class /*1*/Class{
|
||||
////}
|
||||
|
||||
//@Filename: b.ts
|
||||
////import { /*2*/Class as /*3*/C2} from "a";
|
||||
////
|
||||
////var c = new C2();
|
||||
|
||||
//@Filename: c.ts
|
||||
////export { /*4*/Class as /*5*/C3 } from "a";
|
||||
|
||||
goTo.file("a.ts");
|
||||
goTo.marker("1");
|
||||
verify.referencesCountIs(3);
|
||||
|
||||
goTo.file("b.ts");
|
||||
goTo.marker("2");
|
||||
verify.referencesCountIs(3);
|
||||
|
||||
goTo.marker("3");
|
||||
verify.referencesCountIs(2);
|
||||
|
||||
goTo.file("c.ts");
|
||||
goTo.marker("4");
|
||||
verify.referencesCountIs(3);
|
||||
|
||||
goTo.marker("5");
|
||||
verify.referencesCountIs(1);
|
||||
Reference in New Issue
Block a user