neoclide / coc-prettier

Prettier extension for coc.nvim.
MIT License
546 stars 48 forks source link

file content is stripped when formatting with folds closed #124

Open zanona opened 3 years ago

zanona commented 3 years ago

Related with #102, it seems that depending on the code structure coc-prettier will partially remove file contents instead of formatting whenever folding is enabled.

The file being test against is the following, however I had the same sort of behaviour with different structures, where the content is partially/fully stripped:

module.exports = function () {

return;
};

Please bear in mind this happens only with syntax folding enabled on load and running :CocCommand prettier.formatFile or through coc.preferences.formatOnSaveFiletypes

I have been able to reproduce this under a clean installation under a container with the following image:

FROM node:alpine
WORKDIR /root

RUN apk add vim git

# install coc.vim
RUN mkdir -p ~/.vim/pack/coc/start
RUN cd ~/.vim/pack/coc/start && git clone --depth 1 https://github.com/neoclide/coc.nvim.git

# define ~/.vimrc
RUN echo "set background=dark" >> ~/.vimrc
RUN echo "set foldmethod=syntax" >> ~/.vimrc
RUN echo "set foldlevelstart=0" >> ~/.vimrc
RUN echo "let javaScript_fold=1" >> ~/.vimrc

# prepare coc-prettier auto-install
RUN echo "let g:coc_global_extensions = [ 'coc-prettier' ]" >> ~/.vimrc

# add test file 
RUN printf 'module.exports = function(){\n\nreturn;\n};\n' > ~/test.js

To reproduce:

chemzqm commented 3 years ago

What do you get after format?

zanona commented 3 years ago

I'm afraid it erases the entire buffer, whereas the raw output for prettier cli correctly formats the code. See below.

asciicast

zanona commented 3 years ago

After some debugging, I could find that vim will somehow delete text which is replacing a fold without an empty character right after it. I've managed to patch the registerCommand method in a way it first adds an empty space after the last character of the document and then performs the format action. https://github.com/neoclide/coc-prettier/blob/905e83009386f1b79131e8728599aaae9ab32a30/src/index.ts#L143-L156

--- a/.config/coc/extensions/node_modules/coc-prettier/lib/index.js
+++ b/.config/coc/extensions/node_modules/coc-prettier/lib/index.js
@@ -2839,9 +2839,16 @@ var PrettierEditProvider = class {
     if (!document.uri.startsWith("untitled") && this._fileIsIgnored(fileName)) {
       return Promise.resolve([]);
     }
-    const code = await format(document.getText(), document, options);
+
+    let doc = await import_coc6.workspace.document;
+    await doc.applyEdits([{
+      range: fullDocumentRange(doc.textDocument),
+      newText: doc.content + ' '
+    }]);
+
+    const code = await format(doc.content, doc.textDocument, options);
     const edits = [{
-      range: fullDocumentRange(document),
+      range: fullDocumentRange(doc.textDocument),
       newText: code
     }];
     const {disableSuccessMessage} = getConfig();
@@ -2936,6 +2943,11 @@ async function activate(context) {
       import_coc6.window.showMessage(`Flag prettier.onlyUseLocalVersion is set, but prettier is not installed locally. No operation will be made.`, "warning");
       return;
     }
+
+   await document.applyEdits([{
+     range: fullDocumentRange(document.textDocument),
+     newText: document.content + ' '
+   }]);
     let edits = await format(document.content, document.textDocument, {}).then((code) => {
       if (code == null)
         return null;

Although, this doesn't feel like it's the best way to achieve this, so if somehow you could think on a better way to patch this, it would be really appreciated.