Skip to content

Create a new pull request by comparing changes across two branches #1034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/services/refactors/inlineVariable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
isNumericLiteral,
isObjectLiteralExpression,
isPropertyAccessExpression,
isShorthandPropertyAssignment,
isTypeQueryNode,
isVariableDeclarationInVariableStatement,
isVariableStatement,
Expand Down Expand Up @@ -102,7 +103,6 @@ registerRefactor(refactorName, {

getEditsForAction(context, actionName) {
Debug.assert(actionName === refactorName, "Unexpected refactor invoked");

const { file, program, startPosition } = context;

// tryWithReferenceToken is true below since here we're already performing the refactor.
Expand Down Expand Up @@ -189,9 +189,10 @@ function isDeclarationExported(declaration: InitializedVariableDeclaration): boo
function getReferenceNodes(declaration: InitializedVariableDeclaration, checker: TypeChecker, file: SourceFile): Identifier[] | undefined {
const references: Identifier[] = [];
const cannotInline = FindAllReferences.Core.eachSymbolReferenceInFile(declaration.name as Identifier, checker, file, ref => {
// Only inline if all references are reads. Else we might end up with an invalid scenario like:
// const y = x++ + 1 -> const y = 2++ + 1
if (FindAllReferences.isWriteAccessForReference(ref)) {
// Only inline if all references are reads, or if it includes a shorthand property assignment.
// Else we might end up with an invalid scenario like:
// const y = x++ + 1 -> const y = 2++ + 1,
if (FindAllReferences.isWriteAccessForReference(ref) && !isShorthandPropertyAssignment(ref.parent)) {
return true;
}

Expand All @@ -216,7 +217,7 @@ function getReferenceNodes(declaration: InitializedVariableDeclaration, checker:
return references.length === 0 || cannotInline ? undefined : references;
}

function getReplacementExpression(reference: Node, replacement: Expression): Expression {
function getReplacementExpression(reference: Node, replacement: Expression) {
// Make sure each reference site gets its own copy of the replacement node.
replacement = getSynthesizedDeepClone(replacement);
const { parent } = reference;
Expand Down Expand Up @@ -244,5 +245,13 @@ function getReplacementExpression(reference: Node, replacement: Expression): Exp
return factory.createParenthesizedExpression(replacement);
}

// Inline shorthand property assignment
// E.g.:
// const x = 1;
// const y = { x }; -> const y = { x: 1 };
if (isIdentifier(reference) && isShorthandPropertyAssignment(parent)) {
return factory.createPropertyAssignment(reference, replacement);
}

return replacement;
}
13 changes: 13 additions & 0 deletions tests/cases/fourslash/inlineVariableShorthandPropertyAssignment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/// <reference path="fourslash.ts" />

////const foo = 1;
////const bar = { /*a*/foo/*b*/ };

goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Inline variable",
actionName: "Inline variable",
actionDescription: "Inline variable",
newContent: "const bar = { foo: 1 };",
triggerReason: "invoked",
});