From 25a0e900ba29a527ebfb62fafa277f05bfef8299 Mon Sep 17 00:00:00 2001 From: Grigory Date: Wed, 27 Nov 2024 02:48:51 +0500 Subject: [PATCH 1/9] fix(DocumentWatcher): use `Workspace.applyEdit` for applying changes --- src/DocumentWatcher.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/DocumentWatcher.ts b/src/DocumentWatcher.ts index fb0bbc6..aa349b3 100644 --- a/src/DocumentWatcher.ts +++ b/src/DocumentWatcher.ts @@ -8,6 +8,7 @@ import { TextEditorOptions, window, workspace, + WorkspaceEdit, } from 'vscode' import { InsertFinalNewline, @@ -81,12 +82,14 @@ export default class DocumentWatcher { e.document, e.reason, ) - e.waitUntil(transformations) - if (selections.length) { - const edits = await transformations - if (activeEditor && edits.length) { - activeEditor.selections = selections - } + + const workspaceEdit = new WorkspaceEdit() + const textEdits = await transformations + workspaceEdit.set(e.document.uri, textEdits) + await workspace.applyEdit(workspaceEdit) + + if (activeEditor && textEdits.length && selections.length) { + activeEditor.selections = selections } }), ) From 7e1baa0d903ec1ac774008eaa66a87d8b908bf53 Mon Sep 17 00:00:00 2001 From: Grigory Date: Sun, 1 Dec 2024 02:46:30 +0500 Subject: [PATCH 2/9] fix(DocumentWatcher): copy selections by value --- src/DocumentWatcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DocumentWatcher.ts b/src/DocumentWatcher.ts index aa349b3..3bb7907 100644 --- a/src/DocumentWatcher.ts +++ b/src/DocumentWatcher.ts @@ -76,7 +76,7 @@ export default class DocumentWatcher { const activeEditor = window.activeTextEditor const activeDoc = activeEditor?.document if (activeDoc && activeDoc === e.document && activeEditor) { - selections = activeEditor.selections + selections = [...activeEditor.selections] } const transformations = this.calculatePreSaveTransformations( e.document, From 7b7ab3321beaef0427e7d890e967878c3f64b792 Mon Sep 17 00:00:00 2001 From: Grigory Date: Thu, 30 Jan 2025 17:28:04 +0500 Subject: [PATCH 3/9] add test --- src/test/suite/index.test.ts | 61 ++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/test/suite/index.test.ts b/src/test/suite/index.test.ts index fa390d8..30c25c8 100644 --- a/src/test/suite/index.test.ts +++ b/src/test/suite/index.test.ts @@ -1,6 +1,13 @@ import * as assert from 'assert' import * as os from 'os' -import { Position, window, workspace, WorkspaceEdit } from 'vscode' +import { + Position, + window, + workspace, + WorkspaceEdit, + Selection, + TextDocument, +} from 'vscode' import { getFixturePath, getOptionsForFixture, wait } from '../testUtils' import * as utils from 'vscode-test-utils' @@ -284,6 +291,29 @@ suite('EditorConfig extension', function () { `editor has insertSpaces: ${options.insertSpaces}`, ) }) + + test('keep selection on format', async () => { + const obj = withSetting('insert_final_newline', 'true') + await obj.createDoc('bar') + assert(window.activeTextEditor, 'no active editor') + + const position = new Position(0, 3) + const selection = new Selection(position, position) + window.activeTextEditor.selection = selection + + await obj.saveText('foo') + + assert.strictEqual( + window.activeTextEditor.selection.start.line, + selection.start.line, + 'editor selection start line changed', + ) + assert.strictEqual( + window.activeTextEditor.selection.end.line, + selection.end.line, + 'editor selection end line changed', + ) + }) }) function withSetting( @@ -293,13 +323,12 @@ function withSetting( contents?: string } = {}, ) { + let doc: TextDocument | undefined return { - async getText() { - return (await createDoc(options.contents)).getText() - }, + doc, saveText(text: string) { return new Promise(async resolve => { - const doc = await createDoc(options.contents) + const doc = this.doc ?? (await this.createDoc(options.contents)) workspace.onDidChangeTextDocument(doc.save) workspace.onDidSaveTextDocument(savedDoc => { assert.strictEqual(savedDoc.isDirty, false, 'dirty saved doc') @@ -314,16 +343,16 @@ function withSetting( ) }) }, - } - - async function createDoc(contents = '') { - const uri = await utils.createFile( - contents, - getFixturePath([rule, value, 'test']), - ) - const doc = await workspace.openTextDocument(uri) - await window.showTextDocument(doc) - await wait(50) // wait for EditorConfig to apply new settings - return doc + async createDoc(contents = '') { + const uri = await utils.createFile( + contents, + getFixturePath([rule, value, Math.random().toString(36)]), + ) + const doc = await workspace.openTextDocument(uri) + this.doc = doc + await window.showTextDocument(doc) + await wait(50) // wait for EditorConfig to apply new settings + return doc + }, } } From 147493023f6c5edcb8f8163a763e7bee3421e57b Mon Sep 17 00:00:00 2001 From: Grigory Date: Thu, 30 Jan 2025 19:07:14 +0500 Subject: [PATCH 4/9] simplify test --- src/test/suite/index.test.ts | 50 +++++++++++++----------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/src/test/suite/index.test.ts b/src/test/suite/index.test.ts index 30c25c8..96c3902 100644 --- a/src/test/suite/index.test.ts +++ b/src/test/suite/index.test.ts @@ -1,13 +1,6 @@ import * as assert from 'assert' import * as os from 'os' -import { - Position, - window, - workspace, - WorkspaceEdit, - Selection, - TextDocument, -} from 'vscode' +import { Position, window, workspace, WorkspaceEdit, Selection } from 'vscode' import { getFixturePath, getOptionsForFixture, wait } from '../testUtils' import * as utils from 'vscode-test-utils' @@ -293,24 +286,17 @@ suite('EditorConfig extension', function () { }) test('keep selection on format', async () => { - const obj = withSetting('insert_final_newline', 'true') - await obj.createDoc('bar') + await withSetting('insert_final_newline', 'true').saveText('foobar') assert(window.activeTextEditor, 'no active editor') - const position = new Position(0, 3) - const selection = new Selection(position, position) - window.activeTextEditor.selection = selection - - await obj.saveText('foo') - assert.strictEqual( window.activeTextEditor.selection.start.line, - selection.start.line, + 0, 'editor selection start line changed', ) assert.strictEqual( window.activeTextEditor.selection.end.line, - selection.end.line, + 0, 'editor selection end line changed', ) }) @@ -323,12 +309,13 @@ function withSetting( contents?: string } = {}, ) { - let doc: TextDocument | undefined return { - doc, + async getText() { + return (await createDoc(options.contents)).getText() + }, saveText(text: string) { return new Promise(async resolve => { - const doc = this.doc ?? (await this.createDoc(options.contents)) + const doc = await createDoc(options.contents) workspace.onDidChangeTextDocument(doc.save) workspace.onDidSaveTextDocument(savedDoc => { assert.strictEqual(savedDoc.isDirty, false, 'dirty saved doc') @@ -343,16 +330,15 @@ function withSetting( ) }) }, - async createDoc(contents = '') { - const uri = await utils.createFile( - contents, - getFixturePath([rule, value, Math.random().toString(36)]), - ) - const doc = await workspace.openTextDocument(uri) - this.doc = doc - await window.showTextDocument(doc) - await wait(50) // wait for EditorConfig to apply new settings - return doc - }, + } + async function createDoc(contents = '') { + const uri = await utils.createFile( + contents, + getFixturePath([rule, value, Math.random().toString(36)]), + ) + const doc = await workspace.openTextDocument(uri) + await window.showTextDocument(doc) + await wait(50) // wait for EditorConfig to apply new settings + return doc } } From 4eb4e369fc6f3caf65f9d0ff40208aff78eadab8 Mon Sep 17 00:00:00 2001 From: Grigory Date: Thu, 30 Jan 2025 19:16:42 +0500 Subject: [PATCH 5/9] remove extra `Selection` import --- src/test/suite/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/suite/index.test.ts b/src/test/suite/index.test.ts index 96c3902..2cf5567 100644 --- a/src/test/suite/index.test.ts +++ b/src/test/suite/index.test.ts @@ -1,6 +1,6 @@ import * as assert from 'assert' import * as os from 'os' -import { Position, window, workspace, WorkspaceEdit, Selection } from 'vscode' +import { Position, window, workspace, WorkspaceEdit } from 'vscode' import { getFixturePath, getOptionsForFixture, wait } from '../testUtils' import * as utils from 'vscode-test-utils' From f9a2e3f49177c89e11da30bd82463a0ba85b10ba Mon Sep 17 00:00:00 2001 From: Grigory Date: Fri, 31 Jan 2025 00:59:34 +0500 Subject: [PATCH 6/9] use counter instead of random string for test file names --- src/test/suite/index.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/test/suite/index.test.ts b/src/test/suite/index.test.ts index 2cf5567..92a2916 100644 --- a/src/test/suite/index.test.ts +++ b/src/test/suite/index.test.ts @@ -334,11 +334,17 @@ function withSetting( async function createDoc(contents = '') { const uri = await utils.createFile( contents, - getFixturePath([rule, value, Math.random().toString(36)]), + generateFixturePath().next().value, ) const doc = await workspace.openTextDocument(uri) await window.showTextDocument(doc) await wait(50) // wait for EditorConfig to apply new settings return doc } + function* generateFixturePath(): Generator { + let index = 0 + while (true) { + yield getFixturePath([rule, value, `${test}-${index++}`]) + } + } } From 012a3775a98843c0df6441bc75a871b712f74df8 Mon Sep 17 00:00:00 2001 From: Grigory Date: Fri, 31 Jan 2025 02:26:46 +0500 Subject: [PATCH 7/9] whatever --- src/test/suite/index.test.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/test/suite/index.test.ts b/src/test/suite/index.test.ts index 92a2916..46389a9 100644 --- a/src/test/suite/index.test.ts +++ b/src/test/suite/index.test.ts @@ -286,7 +286,9 @@ suite('EditorConfig extension', function () { }) test('keep selection on format', async () => { - await withSetting('insert_final_newline', 'true').saveText('foobar') + await withSetting('insert_final_newline', 'true', { + fileName: 'test-selection', + }).saveText('foobar') assert(window.activeTextEditor, 'no active editor') assert.strictEqual( @@ -307,15 +309,16 @@ function withSetting( value: string, options: { contents?: string + fileName?: string } = {}, ) { return { async getText() { - return (await createDoc(options.contents)).getText() + return (await createDoc(options.contents, options.fileName)).getText() }, saveText(text: string) { return new Promise(async resolve => { - const doc = await createDoc(options.contents) + const doc = await createDoc(options.contents, options.fileName) workspace.onDidChangeTextDocument(doc.save) workspace.onDidSaveTextDocument(savedDoc => { assert.strictEqual(savedDoc.isDirty, false, 'dirty saved doc') @@ -331,20 +334,14 @@ function withSetting( }) }, } - async function createDoc(contents = '') { + async function createDoc(contents = '', name = 'test') { const uri = await utils.createFile( contents, - generateFixturePath().next().value, + getFixturePath([rule, value, name]), ) const doc = await workspace.openTextDocument(uri) await window.showTextDocument(doc) await wait(50) // wait for EditorConfig to apply new settings return doc } - function* generateFixturePath(): Generator { - let index = 0 - while (true) { - yield getFixturePath([rule, value, `${test}-${index++}`]) - } - } } From 3a0d693210c1bfc0f9a9dbb09643f74c49ec77bc Mon Sep 17 00:00:00 2001 From: Grigory Date: Fri, 31 Jan 2025 02:41:42 +0500 Subject: [PATCH 8/9] god i hate vscode --- src/test/suite/index.test.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/test/suite/index.test.ts b/src/test/suite/index.test.ts index 46389a9..a485035 100644 --- a/src/test/suite/index.test.ts +++ b/src/test/suite/index.test.ts @@ -1,6 +1,6 @@ import * as assert from 'assert' import * as os from 'os' -import { Position, window, workspace, WorkspaceEdit } from 'vscode' +import { Position, window, workspace, WorkspaceEdit, Uri } from 'vscode' import { getFixturePath, getOptionsForFixture, wait } from '../testUtils' import * as utils from 'vscode-test-utils' @@ -335,10 +335,15 @@ function withSetting( }, } async function createDoc(contents = '', name = 'test') { - const uri = await utils.createFile( - contents, - getFixturePath([rule, value, name]), - ) + const fixturePath = getFixturePath([rule, value, name]) + + try { + await workspace.fs.delete(Uri.file(fixturePath)) + } catch { + // ignore + } + + const uri = await utils.createFile(contents, fixturePath) const doc = await workspace.openTextDocument(uri) await window.showTextDocument(doc) await wait(50) // wait for EditorConfig to apply new settings From c5a203eb82c06d3e37024f12b6dba6e1d7e01ce7 Mon Sep 17 00:00:00 2001 From: Grigory Date: Fri, 31 Jan 2025 03:59:03 +0500 Subject: [PATCH 9/9] Update src/test/suite/index.test.ts Co-authored-by: Hong Xu --- src/test/suite/index.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/suite/index.test.ts b/src/test/suite/index.test.ts index a485035..635cb4a 100644 --- a/src/test/suite/index.test.ts +++ b/src/test/suite/index.test.ts @@ -291,6 +291,7 @@ suite('EditorConfig extension', function () { }).saveText('foobar') assert(window.activeTextEditor, 'no active editor') + // Before saving, the selection is on line 0. This should remain unchanged. assert.strictEqual( window.activeTextEditor.selection.start.line, 0,