microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
162.64k stars 28.67k forks source link

`Format after saving` scenario does not work with Format On Save. We cannot even just save files. #90273

Closed tamuratak closed 3 years ago

tamuratak commented 4 years ago

Version: 1.42.0 Commit: ae08d5460b5a45169385ff3fd44208f431992451 Date: 2020-02-06T10:51:33.119Z Electron: 6.1.6 Chrome: 76.0.3809.146 Node.js: 12.4.0 V8: 7.6.303.31-electron.0 OS: Darwin x64 17.7.0 Steps to Reproduce:

  1. Enable Format On Save.
  2. Execute the following extension example.
  3. Edit a text file and save it.
  4. Cancel the notificationSave Participants.
  5. We cannot even save the text document.

Let me explain to what the following extension example corresponds. Let us consider to implement DocumentFormattingEditProvider with a CLI program. The code would be typically

provideDocumentFormattingEdits(document: vscode.TextDocument): vscode.ProviderResult<vscode.TextEdit[]> {
  return new Promise((resolve, reject) => {
     document.save().then(() => {
     // call the CLI program which outputs a formatted result to a temporary file.
     // We create  vscode.TextEdit[] from the temporary file, and return it.
     })
  })
}

The following extension example corresponds the case that the CLI program fails formatting. If the formatting fails, the text document remains dirty and cannot be saved.

Does this issue occur when all extensions are disabled?: Yes

import * as vscode from 'vscode';
import { DocumentFormattingEditProvider } from 'vscode';

class Formatter implements DocumentFormattingEditProvider {
    provideDocumentFormattingEdits(document: vscode.TextDocument): vscode.ProviderResult<vscode.TextEdit[]> {
        return new Promise((resolve, reject) => {
            document.save().then(() => {
                resolve(undefined)
            })
        })
    }
}

export function activate(context: vscode.ExtensionContext) {
    console.log('Congratulations, your extension "helloworld-sample" is now active!');

    let disposable = vscode.commands.registerCommand('extension.helloWorld', () => {
        vscode.window.showInformationMessage('Hello World!');
    });

    vscode.languages.registerDocumentFormattingEditProvider(
        { scheme: 'file' },
        new Formatter()
    )
    context.subscriptions.push(disposable);
}

export function deactivate() { }

Feb-08-2020 12-11-17

jrieken commented 4 years ago

We cannot even save the text document.

That I cannot reproduce, for me after cancelling the file is being saved but I believe I understand what's happening here:

However, cancellation should be independent from this and simply ignore the formatter (or any other save participant) once cancelled and it will proceed saving (which is also what my testing shows).

jrieken commented 4 years ago

The behaviour has always been like that but with the changes done for 1.42 this has become visible only now... If you run the same extension with 1.41 you'll see these messages in the window-log

[2020-02-10 09:49:42.606] [renderer3] [warning] Aborted format on save after 750ms
[2020-02-10 09:49:42.607] [renderer3] [trace] doSave(5) - before write() {"$mid":1,"fsPath":"/Users/jrieken/Code/_samples/devfest/foo/test.txt","external":"file:///Users/jrieken/Code/_samples/devfest/foo/test.txt","path":"/Users/jrieken/Code/_samples/devfest/foo/test.txt","scheme":"file"}

What's new is

Let us consider to implement DocumentFormattingEditProvider with a CLI program.

The culprit is saving a document while it's being saved - this doesn't and didn't work... We understand the problem of shelling out to another program but won't it work for you if you save the file into a temporary file and invoke the CLI tools on that?

tamuratak commented 4 years ago

I would like to confirm that you are saying that

  1. We should not use document.save() in provideDocumentFormattingEdits.
  2. Save the current document to a temporary file with document.getText().

If so, that's reasonable. I agree with you.

jrieken commented 4 years ago

Yes, your summary is correct and you making those changes is the best way out of this right now.

bvwells commented 4 years ago

I seem to also be encountering this issue. I have found that on the latest version there is a difference in behaviour depending on whether the Cancel button or Cross button is selected in the running save participants dialogue.

For me, pressing the cancel button will result in the file being saved, whereas the cancel button leaves the file in a state where it cannot be saved.

Just wondering if others are also seeing this behaviour...

Version: 1.43.0 (user setup) Commit: 78a4c91400152c0f27ba4d363eb56d2835f9903a Date: 2020-03-09T19:47:57.235Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.17134

bvwells commented 4 years ago

Looks like the cross button on the saving participants toast is gone in the latest version. So all good.

jrieken commented 3 years ago

Closing without further changes in VS Code. Also, extensions cannot successfully save a file while it is being saved but that's to be expected.