En mi extensión, quiero editar el documento en algunas ediciones de documentos específicas.
Mi caso de uso real es un poco complicado, así que he creado un ejemplo mínimo. El siguiente código escucha cualquier edición de documento. Si la palabra "hola" existe en la edición (es decir, el usuario pegó algún código que contiene la palabra "hola"), reemplazamos el rango de cambio con el texto pegado, pero lo ponemos en mayúsculas.
También registramos en console.log si la edición fue exitosa y cualquier motivo potencial por el que se rechazó la edición.
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), ); } } }); Un ejemplo práctico sería seleccionar algún texto en un documento y pegar el texto const hello = 5; . Como era de esperar, la extensión reemplaza el texto con CONST HELLO = 5; y registra SUCCESS: true .
Pero cuando pego un texto que se formatea automáticamente, me encuentro con problemas. Si tuviera que pegar:
const hello = 5; const lol = 10; const lmao = 20;Incluyendo todos los espacios en blanco/pestañas, luego vscode quiere "formatear" o corregir mis líneas, es decir, eliminar el espacio en blanco. Entonces el texto resultante será:
const hello = 5; const lol = 10; const lmao = 20; La extensión intenta hacerlo en mayúsculas pero solo imprime SUCCESS: false . No se registra ninguna razón en absoluto; la función de rechazo no se ejecuta.
¿Por qué la edición no tiene éxito? ¿Debo esperar las otras ediciones de alguna manera o seguir intentando la edición hasta que tenga éxito? ¿Estoy registrando el rechazo incorrectamente?
Una solución es simplemente "seguir intentándolo de nuevo". No me gusta esta solución, pero es una solución de todos modos, y actualmente funciona para mi caso de uso.
async function makeReplaceEdit(range: vscode.Range, text: string, maxRetries = 10) { for (let i = 0; i <= maxRetries; i++) { const editor = vscode.window.activeTextEditor; if (!editor) return; const success = await editor.edit(editBuilder => { editBuilder.replace( range, text ); }, { undoStopBefore: false, undoStopAfter: false }); if (success) break; } }; 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"); } });En caso de que ayude, aquí está el código que uso: me pareció mejor tener editBuilder fuera del ciclo. Creo que puedes adaptarlo para tus propósitos:
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 } });