No duplicate scope completions

This commit is contained in:
XeroOl 2024-04-30 21:42:00 -05:00
parent 343777d301
commit 944f57cc08
4 changed files with 47 additions and 24 deletions

View File

@ -1,5 +1,17 @@
# Changelog # Changelog
### Features
* Better results when syntax errors are present.
### Bug Fixes
* Solved a case where there were duplicate completion candidates
* Special workaround for Eglot to be able to complete multisyms.
To be honest, this isn't even Eglot's fault; the LSP specification leaves it ambiguous
[Eglot's issue](https://github.com/joaotavora/eglot/issues/402)
[LSP's issue](https://github.com/microsoft/language-server-protocol/issues/648)
[fennel-mode can't fix it on their end](https://git.sr.ht/~technomancy/fennel-mode/commit/188ee04e86792cd4bce75d52b9603cc833b63b48)
## 0.1.2 ## 0.1.2
### Features ### Features

View File

@ -176,8 +176,9 @@ Every time the client sends a message, it gets handled by a function in the corr
def (formatter.completion-item-format label def) def (formatter.completion-item-format label def)
_ {: label :kind kinds.Field}))))) _ {: label :kind kinds.Field})))))
{: metadata : fields} {: metadata : fields}
(let [_metadata metadata]
(icollect [label info (pairs fields)] (icollect [label info (pairs fields)]
(formatter.completion-item-format label info)) (formatter.completion-item-format label info)))
_ nil))) _ nil)))
(λ requests.textDocument/completion [self send {: position :textDocument {: uri}}] (λ requests.textDocument/completion [self send {: position :textDocument {: uri}}]
@ -191,9 +192,10 @@ Every time the client sends a message, it gets handled by a function in the corr
(let [input-range (if ?symbol (message.multisym->range self file ?symbol -1) {:start position :end position}) (let [input-range (if ?symbol (message.multisym->range self file ?symbol -1) {:start position :end position})
?completions (scope-completion self file byte ?symbol parents)] ?completions (scope-completion self file byte ?symbol parents)]
(if ?completions (if ?completions
(let [?completions (utils.uniq-by ?completions #$.label)]
(each [_ completion (ipairs ?completions)] (each [_ completion (ipairs ?completions)]
(set completion.textEdit {:newText completion.label :range input-range}))) (set completion.textEdit {:newText completion.label :range input-range}))
?completions) ?completions)))
;; completion from field ;; completion from field
[_a _b &as split] [_a _b &as split]

View File

@ -170,15 +170,15 @@ WARNING: this is only used in the test code, not in the real language server"
(λ type= [val typ] (λ type= [val typ]
(= (type val) typ)) (= (type val) typ))
(λ uniq-by [list eq?] (λ uniq-by [list key-fn]
"I know the big O of this is bad, but we'll come back to it if it's a performance problem" "I know the big O of this is bad, but we'll come back to it if it's a performance problem"
(let [result []] (let [result []
seen {}]
(each [_ new-item (ipairs list)] (each [_ new-item (ipairs list)]
(if (not (accumulate [any? nil (let [key (key-fn new-item)]
_ seen-item (ipairs result) (when (not (. seen key))
&until any?] (tset seen key true)
(eq? seen-item new-item))) (table.insert result new-item))))
(table.insert result new-item)))
result)) result))
(λ split-spaces [str] (λ split-spaces [str]

View File

@ -54,6 +54,7 @@
"from: " (view file-contents) "\n" "from: " (view file-contents) "\n"
(view (. completions i) {:escape-newlines? true}))))) (view (. completions i) {:escape-newlines? true})))))
(if (= (type expected) :table)
(each [_ e (ipairs expected)] (each [_ e (ipairs expected)]
(let [i (find completions e)] (let [i (find completions e)]
(faith.is i (.. "Didn't get completion: " (view e) "\n" (faith.is i (.. "Didn't get completion: " (view e) "\n"
@ -65,7 +66,8 @@
(view (. completions candidate) (view (. completions candidate)
{:escape-newlines? true})) {:escape-newlines? true}))
"")) ""))
""))))))) "")))))
(expected completions))))
(fn test-global [] (fn test-global []
;; TODO shouldn't this kind be Function? ;; TODO shouldn't this kind be Function?
@ -103,6 +105,13 @@
bar 20 bar 20
_ fo|" [:foo :bar] []) _ fo|" [:foo :bar] [])
(check "(local x {:field 100})\n(if x.fi" [:field] []) (check "(local x {:field 100})\n(if x.fi" [:field] [])
(check "(let [x 10] (let [x 10] x"
(fn [completions]
(faith.= 1 (accumulate [number-of-x 0 _ completion (ipairs completions)]
(if (= completion.label :x)
(+ number-of-x 1)
number-of-x))))
[])
nil) nil)
(fn test-builtin [] (fn test-builtin []