Home > Blockchain >  VSCode API: Editor.edit editbuilder.replace fails without reason (possibly due to formatting?)
VSCode API: Editor.edit editbuilder.replace fails without reason (possibly due to formatting?)

Time:04-26

In my extension I want to edit the document on a few specific document edits.

My actual use case is a bit complicated so I have created a minimal example. The code below listens for any document edit. If the word "hello" exists in the edit (i.e. the user pasted some code that contains the word "hello") then we replace the change range with the pasted text but just make it upper case.

We also console.log if the edit was successful, and any potential reason the edit was rejected.

vscode.workspace.onDidChangeTextDocument(event => {
    for (const change of event.contentChanges) {
        if (change.text.includes("hello")) {
            activeEditor.edit(editBuilder => {
                editBuilder.replace(change.range, change.text.toUpperCase());
            }).then(
                value => console.log("SUCCESS: " value),
                reason => console.log("FAIL REASON: " reason),
            );
        }
    }
});

A working example would be selecting some text in a document and pasting in the text const hello = 5;. As expected, the extension replaces the text with CONST HELLO = 5; and logs SUCCESS: true.

But when I paste in some text that automatically get formatted I run into problems. If I were to paste in:

    const hello = 5;
    const lol = 10;
    const lmao = 20;

Including all the whitespaces/tabs, then vscode wants to "format" or correct my lines, i.e. remove the whitespace. So the resulting text will be:

const hello = 5;
const lol = 10;
const lmao = 20;

The extension tries to make it uppercase still but only prints SUCCESS: false. No reason is logged at all; the reject function is not executed.

Why does the edit not succeed? Should I await the other edits somehow or keep re-trying the edit until it succeeds? Am I logging the rejection incorrectly?

CodePudding user response:

In case it helps, here is code I use - I found it better to have the editBuilder outside the loop. I think you can adapt it for your purposes:

    editor.edit( (editBuilder) => {

      // put your for (const change of event.contentChanges) {} here

      for (const match of matches) {
        resolvedReplace = variables.buildReplace(args, "replace", match, editor.selection, null, index);

        const matchStartPos = document.positionAt(match.index);
        const matchEndPos = document.positionAt(match.index   match[0].length);
        const matchRange = new vscode.Range(matchStartPos, matchEndPos);

        editBuilder.replace(matchRange, resolvedReplace);
      }
    }).then(success => {
        if (!success) {
            return;
        }
        if (success) {  ... do something here if you need to }
    });

CodePudding user response:

One solution is just to "keep trying again". I do not like this solution, but it is a solution nevertheless, and it currently works for my use-case.

    function makeReplaceEdit(range: vscode.Range, text: string) {
        const editor = vscode.window.activeTextEditor;
        if (!editor) return;

        editor.edit(editBuilder => {
            editBuilder.replace(
                range,
                text
            );
        }).then(
            success => {
                console.log("SUCCESS: "   success);
                if (!success) makeReplaceEdit(range, text); // If failed, try again
            }
        );
    };

    vscode.workspace.onDidChangeTextDocument((event) => {

        // See if any change contained "hello"        
        let foundHello = false;
        for (const change of event.contentChanges) {
            if (change.text.includes("hello")) {
                foundHello = true;
            }
        }

        if (foundHello) {
            console.log("inside1");
            const editor = vscode.window.activeTextEditor;
            if (!editor) return;
            makeReplaceEdit(editor.document.lineAt(0).range, "Change");
        }
    });
  • Related