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
### 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
### 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)
_ {: label :kind kinds.Field})))))
{: metadata : fields}
(icollect [label info (pairs fields)]
(formatter.completion-item-format label info))
(let [_metadata metadata]
(icollect [label info (pairs fields)]
(formatter.completion-item-format label info)))
_ nil)))
(λ 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})
?completions (scope-completion self file byte ?symbol parents)]
(if ?completions
(each [_ completion (ipairs ?completions)]
(set completion.textEdit {:newText completion.label :range input-range})))
?completions)
(let [?completions (utils.uniq-by ?completions #$.label)]
(each [_ completion (ipairs ?completions)]
(set completion.textEdit {:newText completion.label :range input-range}))
?completions)))
;; completion from field
[_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))
(λ 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"
(let [result []]
(let [result []
seen {}]
(each [_ new-item (ipairs list)]
(if (not (accumulate [any? nil
_ seen-item (ipairs result)
&until any?]
(eq? seen-item new-item)))
(table.insert result new-item)))
(let [key (key-fn new-item)]
(when (not (. seen key))
(tset seen key true)
(table.insert result new-item))))
result))
(λ split-spaces [str]

View File

@ -54,18 +54,20 @@
"from: " (view file-contents) "\n"
(view (. completions i) {:escape-newlines? true})))))
(each [_ e (ipairs expected)]
(let [i (find completions e)]
(faith.is i (.. "Didn't get completion: " (view e) "\n"
"from: " (view file-contents) "\n"
(if (= (type e) :table)
(let [candidate (find completions {:label e.label})]
(if candidate
(.. "Candidate that didn't match:\n"
(view (. completions candidate)
{:escape-newlines? true}))
""))
"")))))))
(if (= (type expected) :table)
(each [_ e (ipairs expected)]
(let [i (find completions e)]
(faith.is i (.. "Didn't get completion: " (view e) "\n"
"from: " (view file-contents) "\n"
(if (= (type e) :table)
(let [candidate (find completions {:label e.label})]
(if candidate
(.. "Candidate that didn't match:\n"
(view (. completions candidate)
{:escape-newlines? true}))
""))
"")))))
(expected completions))))
(fn test-global []
;; TODO shouldn't this kind be Function?
@ -103,6 +105,13 @@
bar 20
_ fo|" [:foo :bar] [])
(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)
(fn test-builtin []