diff --git a/src/harness/unittests/extractMethods.ts b/src/harness/unittests/extractMethods.ts index c836698aeb4..bfd7519449d 100644 --- a/src/harness/unittests/extractMethods.ts +++ b/src/harness/unittests/extractMethods.ts @@ -709,6 +709,25 @@ function M3() { }`); } M3() { } constructor() { } +}`); + // Shorthand property names + testExtractMethod("extractMethod29", + `interface UnaryExpression { + kind: "Unary"; + operator: string; + operand: any; +} + +function parseUnaryExpression(operator: string): UnaryExpression { + [#|return { + kind: "Unary", + operator, + operand: parsePrimaryExpression(), + };|] +} + +function parsePrimaryExpression(): any { + throw "Not implemented"; }`); }); diff --git a/src/services/refactors/extractMethod.ts b/src/services/refactors/extractMethod.ts index 7b5e1e40c7e..5749c2b71d5 100644 --- a/src/services/refactors/extractMethod.ts +++ b/src/services/refactors/extractMethod.ts @@ -1161,7 +1161,11 @@ namespace ts.refactor.extractMethod { } function recordUsagebySymbol(identifier: Identifier, usage: Usage, isTypeName: boolean) { - const symbol = checker.getSymbolAtLocation(identifier); + // If the identifier is both a property name and its value, we're only interested in its value + // (since the name is a declaration and will be included in the extracted range). + const symbol = identifier.parent && isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + ? checker.getShorthandAssignmentValueSymbol(identifier.parent) + : checker.getSymbolAtLocation(identifier); if (!symbol) { // cannot find symbol - do nothing return undefined; diff --git a/tests/baselines/reference/extractMethod/extractMethod29.ts b/tests/baselines/reference/extractMethod/extractMethod29.ts new file mode 100644 index 00000000000..aa7004d254e --- /dev/null +++ b/tests/baselines/reference/extractMethod/extractMethod29.ts @@ -0,0 +1,62 @@ +// ==ORIGINAL== +interface UnaryExpression { + kind: "Unary"; + operator: string; + operand: any; +} + +function parseUnaryExpression(operator: string): UnaryExpression { + return { + kind: "Unary", + operator, + operand: parsePrimaryExpression(), + }; +} + +function parsePrimaryExpression(): any { + throw "Not implemented"; +} +// ==SCOPE::inner function in function 'parseUnaryExpression'== +interface UnaryExpression { + kind: "Unary"; + operator: string; + operand: any; +} + +function parseUnaryExpression(operator: string): UnaryExpression { + return /*RENAME*/newFunction(); + + function newFunction() { + return { + kind: "Unary", + operator, + operand: parsePrimaryExpression(), + }; + } +} + +function parsePrimaryExpression(): any { + throw "Not implemented"; +} +// ==SCOPE::function in global scope== +interface UnaryExpression { + kind: "Unary"; + operator: string; + operand: any; +} + +function parseUnaryExpression(operator: string): UnaryExpression { + return /*RENAME*/newFunction(operator); +} + +function newFunction(operator: string) { + return { + kind: "Unary", + operator, + operand: parsePrimaryExpression(), + }; +} + +function parsePrimaryExpression(): any { + throw "Not implemented"; +} \ No newline at end of file