Skip to content

Commit c741e26

Browse files
committed
Support external module names correctelly
1 parent fefe2fb commit c741e26

File tree

5 files changed

+106
-16
lines changed

5 files changed

+106
-16
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6814,7 +6814,7 @@ module ts {
68146814
return getSymbolOfNode(node.parent);
68156815
}
68166816

6817-
if (isInRightSideOfImportOrExportAssignment(node)) {
6817+
if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(node)) {
68186818
return node.parent.kind === SyntaxKind.ExportAssignment
68196819
? getSymbolOfEntityName(<Identifier>node)
68206820
: getSymbolOfPartOfRightHandSideOfImport(node);

src/services/services.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ module ts {
367367
identifiers.push((<Identifier>node).text);
368368
return undefined;
369369
case SyntaxKind.StringLiteral:
370+
if (isNameOfExternalModuleImportOrDeclaration(node)) {
371+
identifiers.push((<LiteralExpression>node).text);
372+
}
373+
// intential fall through
370374
case SyntaxKind.NumericLiteral:
371375
if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
372376
identifiers.push((<LiteralExpression>node).text);
@@ -1322,6 +1326,12 @@ module ts {
13221326
return false;
13231327
}
13241328

1329+
function isNameOfExternalModuleImportOrDeclaration(node: Node): boolean {
1330+
return node.kind === SyntaxKind.StringLiteral &&
1331+
((node.parent.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>node.parent).name === node) ||
1332+
(node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node));
1333+
}
1334+
13251335
enum SearchMeaning {
13261336
Value = 0x1,
13271337
Type = 0x2,
@@ -2126,7 +2136,9 @@ module ts {
21262136
return undefined;
21272137
}
21282138

2129-
if (node.kind !== SyntaxKind.Identifier && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
2139+
if (node.kind !== SyntaxKind.Identifier &&
2140+
!isLiteralNameOfPropertyDeclarationOrIndexAccess(node) &&
2141+
!isNameOfExternalModuleImportOrDeclaration(node)) {
21302142
return undefined;
21312143
}
21322144

@@ -2163,27 +2175,36 @@ module ts {
21632175
// Compute the meaning from the location and the symbol it references
21642176
var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), symbol.getDeclarations());
21652177

2178+
// Get the text to search for, we need to normalize it as external module names will have quote
2179+
var symbolName = getNormalizedSymbolName(symbol.getName());
2180+
21662181
var scope = getSymbolScope(symbol);
21672182

21682183
if (scope) {
21692184
result = [];
2170-
getReferencesInNode(scope, symbol, node, searchMeaning, result);
2185+
getReferencesInNode(scope, symbol, symbolName, node, searchMeaning, result);
21712186
}
21722187
else {
2173-
var symbolName = symbol.getName();
2174-
21752188
forEach(program.getSourceFiles(), sourceFile => {
21762189
cancellationToken.throwIfCancellationRequested();
21772190

21782191
if (sourceFile.getBloomFilter().probablyContains(symbolName)) {
21792192
result = result || [];
2180-
getReferencesInNode(sourceFile, symbol, node, searchMeaning, result);
2193+
getReferencesInNode(sourceFile, symbol, symbolName, node, searchMeaning, result);
21812194
}
21822195
});
21832196
}
21842197

21852198
return result;
21862199

2200+
function getNormalizedSymbolName(name: string): string {
2201+
var length = name.length;
2202+
if (length >= 2 && name.charCodeAt(0) === CharacterCodes.doubleQuote && name.charCodeAt(length - 1) === CharacterCodes.doubleQuote) {
2203+
return name.substring(1, length - 1);
2204+
};
2205+
return name;
2206+
}
2207+
21872208
function getSymbolScope(symbol: Symbol): Node {
21882209
// If this is private property or method, the scope is the containing class
21892210
if (symbol.getFlags() && (SymbolFlags.Property | SymbolFlags.Method)) {
@@ -2281,17 +2302,16 @@ module ts {
22812302
return result;
22822303
}
22832304

2284-
function isValidReferencePosition(node: Node, searchSymbol: Symbol): boolean {
2305+
function isValidReferencePosition(node: Node, searchSymbolName: string): boolean {
22852306
if (node) {
2286-
var searchSymbolName = searchSymbol.getName();
2287-
22882307
// Compare the length so we filter out strict superstrings of the symbol we are looking for
22892308
switch (node.kind) {
22902309
case SyntaxKind.Identifier:
22912310
return node.getWidth() === searchSymbolName.length;
22922311

22932312
case SyntaxKind.StringLiteral:
2294-
if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
2313+
if (isLiteralNameOfPropertyDeclarationOrIndexAccess(node) ||
2314+
isNameOfExternalModuleImportOrDeclaration(node)) {
22952315
// For string literals we have two additional chars for the quotes
22962316
return node.getWidth() === searchSymbolName.length + 2;
22972317
}
@@ -2309,14 +2329,12 @@ module ts {
23092329
}
23102330

23112331
/// Search within node "container" for references for a search value, where the search value is defined as a
2312-
/// tuple of(searchSymbol, searchLocation, and searchMeaning).
2332+
/// tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
23132333
/// searchLocation: a node where the search value
2314-
function getReferencesInNode(container: Node, searchSymbol: Symbol, searchLocation: Node, searchMeaning: SearchMeaning, result: ReferenceEntry[]): void {
2315-
var searchSymbolName = searchSymbol.getName();
2316-
2334+
function getReferencesInNode(container: Node, searchSymbol: Symbol, searchText: string, searchLocation: Node, searchMeaning: SearchMeaning, result: ReferenceEntry[]): void {
23172335
var sourceFile = container.getSourceFile();
23182336

2319-
var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchSymbolName, container.getStart(), container.getEnd());
2337+
var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
23202338

23212339
if (possiblePositions.length) {
23222340
// Build the set of symbols to search for, initially it has only the current symbol
@@ -2326,7 +2344,7 @@ module ts {
23262344
cancellationToken.throwIfCancellationRequested();
23272345

23282346
var referenceLocation = getNodeAtPosition(sourceFile, position);
2329-
if (!isValidReferencePosition(referenceLocation, searchSymbol)) {
2347+
if (!isValidReferencePosition(referenceLocation, searchText)) {
23302348
return;
23312349
}
23322350

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
////declare module /*1*/"foo" {
4+
//// var f: number;
5+
////}
6+
////
7+
////declare module "bar" {
8+
//// export import foo = require(/*2*/"foo");
9+
//// var f2: typeof foo./*4*/f;
10+
////}
11+
////
12+
////declare module "baz" {
13+
//// import bar = require(/*3*/"bar");
14+
//// var f2: typeof bar./*5*/foo;
15+
////}
16+
17+
goTo.marker("1");
18+
verify.referencesCountIs(2);
19+
20+
goTo.marker("2");
21+
verify.referencesCountIs(2);
22+
23+
goTo.marker("3");
24+
verify.referencesCountIs(2);
25+
26+
goTo.marker("4");
27+
verify.referencesCountIs(2);
28+
29+
goTo.marker("5");
30+
verify.referencesCountIs(3);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// Global interface reference.
4+
5+
// @Filename: referencesForGlobals_1.ts
6+
////declare module /*1*/"foo" {
7+
//// var f: number;
8+
////}
9+
10+
11+
// @Filename: referencesForGlobals_2.ts
12+
////import f = require(/*2*/"foo");
13+
14+
goTo.marker("1");
15+
verify.referencesCountIs(2);
16+
17+
goTo.marker("2");
18+
verify.referencesCountIs(2);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// Global variable reference.
4+
5+
////var /*1*/topLevelVar = 2;
6+
////var topLevelVar2 = topLevelVar;
7+
////
8+
////class /*2*/topLevelClass { }
9+
////var c = new topLevelClass();
10+
////
11+
////interface topLevelInterface { }
12+
////var i: /*3*/topLevelInterface;
13+
////
14+
////module topLevelModule {
15+
//// export var x;
16+
////}
17+
////var x = /*4*/topLevelModule.x;
18+
////
19+
////export = x;
20+
21+
test.markers().forEach(m => {
22+
goTo.position(m.position, m.fileName);
23+
verify.referencesCountIs(2);
24+
});

0 commit comments

Comments
 (0)