diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 53adfac26b3..e0276708b74 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -204,7 +204,9 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { function insertAccessor(changeTracker: textChanges.ChangeTracker, file: SourceFile, accessor: AccessorDeclaration, declaration: AcceptedDeclaration, container: ContainerDeclaration) { isParameterPropertyDeclaration(declaration) ? changeTracker.insertNodeAtClassStart(file, container, accessor) - : changeTracker.insertNodeAfter(file, declaration, accessor); + : isPropertyAssignment(declaration) + ? changeTracker.insertNodeAfterComma(file, declaration, accessor) + : changeTracker.insertNodeAfter(file, declaration, accessor); } function updateReadonlyPropertyInitializerStatementConstructor(changeTracker: textChanges.ChangeTracker, context: RefactorContext, constructor: ConstructorDeclaration, fieldName: AcceptedNameType, originalName: AcceptedNameType) { diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 37d760ac8f5..3994259a640 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -320,10 +320,14 @@ namespace ts.textChanges { return this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options); } + private nextCommaToken (sourceFile: SourceFile, node: Node): Node | undefined { + const next = findNextToken(node, node.parent, sourceFile); + return next && next.kind === SyntaxKind.CommaToken ? next : undefined; + } + public replacePropertyAssignment(sourceFile: SourceFile, oldNode: PropertyAssignment, newNode: PropertyAssignment) { - return this.replaceNode(sourceFile, oldNode, newNode, { - suffix: "," + this.newLineCharacter - }); + const suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ("," + this.newLineCharacter); + return this.replaceNode(sourceFile, oldNode, newNode, { suffix }); } private insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}) { @@ -465,6 +469,11 @@ namespace ts.textChanges { } } + public insertNodeAfterComma(sourceFile: SourceFile, after: Node, newNode: Node): void { + const endPosition = this.insertNodeAfterWorker(sourceFile, this.nextCommaToken(sourceFile, after) || after, newNode); + this.insertNodeAt(sourceFile, endPosition, newNode, this.getInsertNodeAfterOptions(sourceFile, after)); + } + public insertNodeAfter(sourceFile: SourceFile, after: Node, newNode: Node): void { const endPosition = this.insertNodeAfterWorker(sourceFile, after, newNode); this.insertNodeAt(sourceFile, endPosition, newNode, this.getInsertNodeAfterOptions(sourceFile, after)); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts new file mode 100644 index 00000000000..d745aa2412d --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts @@ -0,0 +1,21 @@ +/// + +//// const A = { +//// /*a*/a/*b*/: 1, +//// }; + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Generate 'get' and 'set' accessors", + actionName: "Generate 'get' and 'set' accessors", + actionDescription: "Generate 'get' and 'set' accessors", + newContent: `const A = { + /*RENAME*/_a: 1, + get a() { + return this._a; + }, + set a(value) { + this._a = value; + }, +};`, +});