Better completions! lazy documentation, deduplicated editRange. I have no tests for these completions >:^)

This commit is contained in:
XeroOl 2025-04-26 16:29:36 -05:00
parent 75839a2f13
commit 39fdd0c282
5 changed files with 38 additions and 16 deletions

View File

@ -221,12 +221,13 @@ find the definition `10`, but if `opts.stop-early?` is set, it would find
(assert (= (type name) :string) "search-name-and-scope needs a string") (assert (= (type name) :string) "search-name-and-scope needs a string")
(let [split (utils.multi-sym-split name) (let [split (utils.multi-sym-split name)
stack (stack-add-split! [] split) stack (stack-add-split! [] split)
base-name (. split 1)
opts (or ?opts {})] opts (or ?opts {})]
(case (docs.get-builtin server (. split 1)) (case (docs.get-builtin server base-name)
metadata (search-document server metadata stack opts) metadata (search-document server metadata stack opts)
_ (case (find-local-definition file name scope) _ (case (find-local-definition file base-name scope)
def (search-val server file def.definition (stack-add-keys! stack def.keys) opts) def (search-val server file def.definition (stack-add-keys! stack def.keys) opts)
_ (case (docs.get-global server (. split 1)) _ (case (docs.get-global server base-name)
metadata (search-document server metadata stack opts)))))) metadata (search-document server metadata stack opts))))))
(λ past? [?ast byte] (λ past? [?ast byte]

View File

@ -26,7 +26,7 @@
seen {}] seen {}]
(fn add-completion! [name definition ?kind] (fn add-completion! [name definition ?kind]
(table.insert results (format.completion-item-format name definition range ?kind))) (table.insert results (format.completion-item-format server name definition range ?kind)))
(fn add-completion-recursively! [name definition] (fn add-completion-recursively! [name definition]
"add the completion. also recursively adds the fields' completions" "add the completion. also recursively adds the fields' completions"
@ -101,6 +101,20 @@
(io.stderr:write "BAD!!!! undocumented special: " (tostring special) "\n") (io.stderr:write "BAD!!!! undocumented special: " (tostring special) "\n")
{:label special})))) {:label special}))))
(set scope scope.parent)) (set scope scope.parent))
results)) (if server.can-do-good-completions?
{:itemDefaults {:editRange range :data {: uri : byte}}
:items results}
results)))
{: textDocument/completion} (fn completionItem/resolve [server _send completion-item]
(let [{: uri : byte} completion-item.data
file (files.get-by-uri server uri)
(_symbol parents) (analyzer.find-symbol file.ast byte)
scope (or (accumulate [?find nil _ parent (ipairs parents) &until ?find]
(. file.scopes parent))
file.scope)]
(case (analyzer.search-name-and-scope server file completion-item.label scope)
result (doto completion-item (tset :documentation (format.hover-format result))))))
{: textDocument/completion
: completionItem/resolve}

View File

@ -96,6 +96,12 @@ However, when not an option, fennel-ls will fall back to positionEncoding=\"utf-
(set server.macro-modules {}) (set server.macro-modules {})
(set server.root-uri params.rootUri) (set server.root-uri params.rootUri)
(set server.position-encoding (choose-position-encoding params)) (set server.position-encoding (choose-position-encoding params))
(set server.can-do-good-completions?
;; if client supports CompletionClientCapabilites.completionList.itemDefaults.editRange
;; and CompletionClientCapabilites.completionList.itemDefaults.data
(case (?. params :capabilities :textDocument :completion :completionList :itemDefaults)
completion-item-defaults (and (accumulate [found nil _ v (ipairs completion-item-defaults) &until found] (= v :editRange))
(accumulate [found nil _ v (ipairs completion-item-defaults) &until found] (= v :data)))))
(reload server)) (reload server))
(λ validate [{: configuration} invalid] (λ validate [{: configuration} invalid]

View File

@ -172,15 +172,14 @@ fntype is one of fn or λ or lambda"
:Snippet 15 :Color 16 :File 17 :Reference 18 :Folder 19 :EnumMember 20 :Snippet 15 :Color 16 :File 17 :Reference 18 :Folder 19 :EnumMember 20
:Constant 21 :Struct 22 :Event 23 :Operator 24 :TypeParameter 25}) :Constant 21 :Struct 22 :Event 23 :Operator 24 :TypeParameter 25})
(λ completion-item-format [name definition range ?kind] (λ completion-item-format [server name definition range ?kind]
"Makes a completion item" "Makes a completion item"
{:label name {:label name
:documentation (hover-format definition) :documentation (when (not server.can-do-good-completions?) (hover-format definition))
:filterText name :textEdit (when (not server.can-do-good-completions?) {:newText name : range})
:textEdit {:newText name : range} :kind (or (when ?kind (. kinds ?kind))
:kind (or (if ?kind (. kinds ?kind))
(. kinds (?. definition :metadata :fls/itemKind)) (. kinds (?. definition :metadata :fls/itemKind))
(if (or (?. definition :metadata :fnl/arglist) (when (or (?. definition :metadata :fnl/arglist)
(?. (analyze-fn definition.definition)) :fntype) (?. (analyze-fn definition.definition)) :fntype)
(if (name:find ":") kinds.Method kinds.Function)))}) (if (name:find ":") kinds.Method kinds.Function)))})

View File

@ -35,7 +35,7 @@ Every time the client sends a message, it gets handled by a function in the corr
:textDocumentSync {:openClose true :change 2} :textDocumentSync {:openClose true :change 2}
;; :notebookDocumentSync nil ;; :notebookDocumentSync nil
:completionProvider {:workDoneProgress false :completionProvider {:workDoneProgress false
:resolveProvider false :resolveProvider server.can-do-good-completions?
:triggerCharacters ["(" "[" "{"] :triggerCharacters ["(" "[" "{"]
:completionItem {:labelDetailsSupport false}} :completionItem {:labelDetailsSupport false}}
:hoverProvider {:workDoneProgress false} :hoverProvider {:workDoneProgress false}
@ -162,7 +162,9 @@ Every time the client sends a message, it gets handled by a function in the corr
symbol)} symbol)}
(catch _ nil)))) (catch _ nil))))
(set requests.textDocument/completion (. (require :fennel-ls.completions) :textDocument/completion)) (set {:textDocument/completion requests.textDocument/completion
:completionItem/resolve requests.completionItem/resolve}
(require :fennel-ls.completions))
(λ requests.textDocument/rename [server _send {: position :textDocument {: uri} :newName new-name}] (λ requests.textDocument/rename [server _send {: position :textDocument {: uri} :newName new-name}]
(let [file (files.get-by-uri server uri) (let [file (files.get-by-uri server uri)