From 7836ae82b799e2ee8e64b5b1fa3d9d7d6f12ce7a Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 21 Nov 2014 16:50:39 -0800 Subject: [PATCH 1/2] Fixed issue where findAllRefs on identifiers starting with 2+ underscores failed. --- src/services/services.ts | 29 ++++++++++++++----- .../findAllRefsWithLeadingUnderscoreNames1.ts | 18 ++++++++++++ .../findAllRefsWithLeadingUnderscoreNames2.ts | 18 ++++++++++++ .../findAllRefsWithLeadingUnderscoreNames3.ts | 18 ++++++++++++ .../findAllRefsWithLeadingUnderscoreNames4.ts | 18 ++++++++++++ .../findAllRefsWithLeadingUnderscoreNames5.ts | 24 +++++++++++++++ .../findAllRefsWithLeadingUnderscoreNames6.ts | 24 +++++++++++++++ .../findAllRefsWithLeadingUnderscoreNames7.ts | 14 +++++++++ .../findAllRefsWithLeadingUnderscoreNames8.ts | 14 +++++++++ .../findAllRefsWithLeadingUnderscoreNames9.ts | 14 +++++++++ .../getOccurrencesOfAnonymousFunction.ts | 13 +++++++-- 11 files changed, 194 insertions(+), 10 deletions(-) create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts create mode 100644 tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts diff --git a/src/services/services.ts b/src/services/services.ts index cf5ca07132e..587b07390a2 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3887,39 +3887,54 @@ 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 symbolName = getNormalizedSymbolName(symbol.name, declarations); + var declaredName = getDeclaredName(symbol); - // Get syntactic diagnostics + // 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). var scope = getSymbolScope(symbol); if (scope) { result = []; - getReferencesInNode(scope, symbol, symbolName, node, searchMeaning, findInStrings, findInComments, result); + getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result); } else { + var internedName = getInternedName(symbol, declarations) forEach(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - if (lookUp(sourceFile.identifiers, symbolName)) { + if (lookUp(sourceFile.identifiers, internedName)) { result = result || []; - getReferencesInNode(sourceFile, symbol, symbolName, node, searchMeaning, findInStrings, findInComments, result); + getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result); } }); } return result; - function getNormalizedSymbolName(symbolName: string, declarations: Declaration[]): string { + function getDeclaredName(symbol: Symbol) { + var name = typeInfoResolver.symbolToString(symbol); + + return stripQuotes(name); + } + + function getInternedName(symbol: Symbol, declarations: Declaration[]): string { // Special case for function expressions, whose names are solely local to their bodies. var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.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. if (functionExpression && functionExpression.name) { var name = functionExpression.name.text; } else { - var name = symbolName; + var name = symbol.name; } + return stripQuotes(name); + } + + function stripQuotes(name: string) { var length = name.length; if (length >= 2 && name.charCodeAt(0) === CharacterCodes.doubleQuote && name.charCodeAt(length - 1) === CharacterCodes.doubleQuote) { return name.substring(1, length - 1); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts new file mode 100644 index 00000000000..369258832a9 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts @@ -0,0 +1,18 @@ +/// + +////class Foo { +//// public [|_bar|]() { return 0; } +////} +//// +////var x: Foo; +////x.[|_bar|]; + + +test.ranges().forEach(r1 => { + goTo.position(r1.start); + verify.referencesCountIs(2); + + test.ranges().forEach(r2 => { + verify.referencesAtPositionContains(r2); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts new file mode 100644 index 00000000000..53adb8236a4 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts @@ -0,0 +1,18 @@ +/// + +////class Foo { +//// public [|__bar|]() { return 0; } +////} +//// +////var x: Foo; +////x.[|__bar|]; + + +test.ranges().forEach(r1 => { + goTo.position(r1.start); + verify.referencesCountIs(2); + + test.ranges().forEach(r2 => { + verify.referencesAtPositionContains(r2); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts new file mode 100644 index 00000000000..1793ec6ddc4 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts @@ -0,0 +1,18 @@ +/// + +////class Foo { +//// public [|___bar|]() { return 0; } +////} +//// +////var x: Foo; +////x.[|___bar|]; + + +test.ranges().forEach(r1 => { + goTo.position(r1.start); + verify.referencesCountIs(2); + + test.ranges().forEach(r2 => { + verify.referencesAtPositionContains(r2); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts new file mode 100644 index 00000000000..694ecdc79ab --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts @@ -0,0 +1,18 @@ +/// + +////class Foo { +//// public [|____bar|]() { return 0; } +////} +//// +////var x: Foo; +////x.[|____bar|]; + + +test.ranges().forEach(r1 => { + goTo.position(r1.start); + verify.referencesCountIs(2); + + test.ranges().forEach(r2 => { + verify.referencesAtPositionContains(r2); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts new file mode 100644 index 00000000000..a110597f4b7 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts @@ -0,0 +1,24 @@ +/// + +////class Foo { +//// public _bar; +//// public __bar; +//// public [|___bar|]; +//// public ____bar; +////} +//// +////var x: Foo; +////x._bar; +////x.__bar; +////x.[|___bar|]; +////x.____bar; + + +test.ranges().forEach(r1 => { + goTo.position(r1.start); + verify.referencesCountIs(2); + + test.ranges().forEach(r2 => { + verify.referencesAtPositionContains(r2); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts new file mode 100644 index 00000000000..97ed29eb178 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts @@ -0,0 +1,24 @@ +/// + +////class Foo { +//// public _bar; +//// public [|__bar|]; +//// public ___bar; +//// public ____bar; +////} +//// +////var x: Foo; +////x._bar; +////x.[|__bar|]; +////x.___bar; +////x.____bar; + + +test.ranges().forEach(r1 => { + goTo.position(r1.start); + verify.referencesCountIs(2); + + test.ranges().forEach(r2 => { + verify.referencesAtPositionContains(r2); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts new file mode 100644 index 00000000000..76adc714b2c --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts @@ -0,0 +1,14 @@ +/// + +////function [|__foo|]() { +//// [|__foo|](); +////} + +test.ranges().forEach(r => { + goTo.position(r.start); + verify.referencesCountIs(2); + + test.ranges().forEach(range => { + verify.referencesAtPositionContains(range); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts new file mode 100644 index 00000000000..d25d6335f2b --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts @@ -0,0 +1,14 @@ +/// + +////(function [|__foo|]() { +//// [|__foo|](); +////}) + +test.ranges().forEach(r => { + goTo.position(r.start); + verify.referencesCountIs(2); + + test.ranges().forEach(range => { + verify.referencesAtPositionContains(range); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts new file mode 100644 index 00000000000..295344d23f9 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts @@ -0,0 +1,14 @@ +/// + +////(function [|___foo|]() { +//// [|___foo|](); +////}) + +test.ranges().forEach(r => { + goTo.position(r.start); + verify.referencesCountIs(2); + + test.ranges().forEach(range => { + verify.referencesAtPositionContains(range); + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesOfAnonymousFunction.ts b/tests/cases/fourslash/getOccurrencesOfAnonymousFunction.ts index 9e32b9c0357..96354df6b05 100644 --- a/tests/cases/fourslash/getOccurrencesOfAnonymousFunction.ts +++ b/tests/cases/fourslash/getOccurrencesOfAnonymousFunction.ts @@ -1,9 +1,16 @@ /// -////(function f/**/oo(): number { +////(function [|foo|](): number { +//// var x = [|foo|]; //// return 0; ////}) -goTo.marker(); -verify.occurrencesAtPositionCount(1); +test.ranges().forEach(r => { + goTo.position(r.start); + verify.occurrencesAtPositionCount(2); + + test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range); + }); +}); \ No newline at end of file From e2eec0e15c5bc6c3ff5614fbf2878ab92297b0d0 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sun, 23 Nov 2014 12:23:19 -0800 Subject: [PATCH 2/2] Added to comment. --- src/services/services.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 587b07390a2..5ad63e50811 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3923,7 +3923,9 @@ module ts { // 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. + // 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; } @@ -5400,7 +5402,7 @@ module ts { getFormattingEditsForDocument, getFormattingEditsAfterKeystroke, getEmitOutput, - getSourceFile: getCurrentSourceFile, + getSourceFile: getCurrentSourceFile, }; }