From ded072e8af39545ca2ce38392ac9747a9e6b7e9b Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Fri, 3 Jan 2020 03:06:25 +0200 Subject: [PATCH] Fixed find all references for private identifiers. (#35887) --- src/compiler/utilities.ts | 3 ++- src/services/findAllReferences.ts | 8 +++---- src/services/utilities.ts | 2 +- .../findAllRefsPrivateNameProperties.ts | 24 +++++++++++++++++++ 4 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/findAllRefsPrivateNameProperties.ts diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 93343650841..7e7b261f0f0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2625,7 +2625,6 @@ namespace ts { case SyntaxKind.NumericLiteral: if (isComputedPropertyName(parent)) return parent.parent; // falls through - case SyntaxKind.Identifier: if (isDeclaration(parent)) { return parent.name === name ? parent : undefined; @@ -2643,6 +2642,8 @@ namespace ts { ? binExp : undefined; } + case SyntaxKind.PrivateIdentifier: + return isDeclaration(parent) && parent.name === name ? parent : undefined; default: return undefined; } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index d2edb6335aa..5a8ae1a3f4b 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -925,7 +925,7 @@ namespace ts.FindAllReferences { // The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form // here appears to be intentional). const { - text = stripQuotes(unescapeLeadingUnderscores((getLocalSymbolForExportDefault(symbol) || getNonModuleSymbolOfMergedModuleSymbol(symbol) || symbol).escapedName)), + text = stripQuotes(symbolName(getLocalSymbolForExportDefault(symbol) || getNonModuleSymbolOfMergedModuleSymbol(symbol) || symbol)), allSearchSymbols = [symbol], } = searchOptions; const escapedText = escapeLeadingUnderscores(text); @@ -1087,7 +1087,7 @@ namespace ts.FindAllReferences { // If this is private property or method, the scope is the containing class if (flags & (SymbolFlags.Property | SymbolFlags.Method)) { - const privateDeclaration = find(declarations, d => hasModifier(d, ModifierFlags.Private)); + const privateDeclaration = find(declarations, d => hasModifier(d, ModifierFlags.Private) || isPrivateIdentifierPropertyDeclaration(d)); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } @@ -1231,9 +1231,9 @@ namespace ts.FindAllReferences { function isValidReferencePosition(node: Node, searchSymbolName: string): boolean { // Compare the length so we filter out strict superstrings of the symbol we are looking for switch (node.kind) { + case SyntaxKind.PrivateIdentifier: case SyntaxKind.Identifier: - return (node as Identifier).text.length === searchSymbolName.length; - + return (node as PrivateIdentifier | Identifier).text.length === searchSymbolName.length; case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.StringLiteral: { const str = node as StringLiteralLike; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 39ce286486b..39123583b5d 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -721,7 +721,7 @@ namespace ts { * position >= start and (position < end or (position === end && token is literal or keyword or identifier)) */ export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node { - return getTouchingToken(sourceFile, position, n => isPropertyNameLiteral(n) || isKeyword(n.kind)); + return getTouchingToken(sourceFile, position, n => isPropertyNameLiteral(n) || isKeyword(n.kind) || isPrivateIdentifier(n)); } /** diff --git a/tests/cases/fourslash/findAllRefsPrivateNameProperties.ts b/tests/cases/fourslash/findAllRefsPrivateNameProperties.ts new file mode 100644 index 00000000000..8470772e9bf --- /dev/null +++ b/tests/cases/fourslash/findAllRefsPrivateNameProperties.ts @@ -0,0 +1,24 @@ +/// + +////class C { +//// [|[|{|"isDefinition": true, "isWriteAccess": true, "contextRangeIndex": 0 |}#foo|] = 10;|] +//// constructor() { +//// this.[|{|"isWriteAccess": true|}#foo|] = 20; +//// } +////} +////class D extends C { +//// constructor() { +//// super() +//// this.#foo = 20; +//// } +////} +////class E { +//// [|[|{|"isDefinition": true, "contextRangeIndex": 3 |}#foo|]: number;|] +//// constructor() { +//// this.[|{|"isWriteAccess": true|}#foo|] = 20; +//// } +////} + +const [rC0Def, rC0, rC1, rE0Def, rE0, rE1] = test.ranges(); +verify.singleReferenceGroup("(property) C.#foo: number", [rC0, rC1]); +verify.singleReferenceGroup("(property) E.#foo: number", [rE0, rE1]);