aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/util.lua
diff options
context:
space:
mode:
authorNicolas Hillegeer <nicolas@hillegeer.com>2021-12-15 15:47:11 +0100
committerGitHub <noreply@github.com>2021-12-15 07:47:11 -0700
commit5ba45a7cd6d178fbe9463499d13f40dd9eca54e4 (patch)
tree3cb1e32afd5b8b0d69bc476c4d56c50db24119a5 /runtime/lua/vim/lsp/util.lua
parent14ffcd190d61f12af29571c83bbcf07e8f127e54 (diff)
downloadrneovim-5ba45a7cd6d178fbe9463499d13f40dd9eca54e4.tar.gz
rneovim-5ba45a7cd6d178fbe9463499d13f40dd9eca54e4.tar.bz2
rneovim-5ba45a7cd6d178fbe9463499d13f40dd9eca54e4.zip
fix(quickfix): avoid O(N^2) when filling from string typval (#16654)
When filling a quickfix/loclist from a string-typed VimL variable, the complexity is O(N^2) in the number of lines in the variable. The problem is caused by using `xstrlcpy(3)` to copy the characters from the current position up to the next newline into the quickfix/loclist buffer in a loop. strlcpy(3) returns the length of `src`, so by necessity it has to compute `strlen(src)`. This means scanning the full rest of the typval on every iteration while only copying a small fraction (up to the next '\n'). This is not a problem whenever the srclen-to-copylen ratio is close to 1, which it usually is. But not in this case. Since we already calculated exactly how many bytes we want to copy, we should be using memcpy(3). This problem is not present in Vim, as it uses `vim_strncpy`, a `strncpy(3)`-alike, which stops at either `\0` or `n`, whichever comes first. The quickfix/loclist window can be filled using a: 1. File (used by commands like :grep/:make/... to source directly from their errorfile) 2. Buffer (used by :cbuffer and its variants) 3. Typval a. String (used by :cexpr and its variants) b. List of strings (used by setqflist(), setloclist(), :cepxr and its variants) This commit optimizes case (3a), especially when the typval is a long string. The pathological path is triggered by (e.g.) :grep enhancements as found in https://gist.github.com/romainl/56f0c28ef953ffc157f36cc495947ab3: function! Grep(...) return system(join([&grepprg] + a:000), ' ')) endfunction :cgetexpr Grep('foo') It would've been better for Neovim to use `systemlist` here, before this commit.
Diffstat (limited to 'runtime/lua/vim/lsp/util.lua')
0 files changed, 0 insertions, 0 deletions