diff --git a/src/fennel-ls/analyzer.fnl b/src/fennel-ls/analyzer.fnl index 87be246..b62c4d1 100644 --- a/src/fennel-ls/analyzer.fnl +++ b/src/fennel-ls/analyzer.fnl @@ -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") (let [split (utils.multi-sym-split name) stack (stack-add-split! [] split) + base-name (. split 1) opts (or ?opts {})] - (case (docs.get-builtin server (. split 1)) + (case (docs.get-builtin server base-name) 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) - _ (case (docs.get-global server (. split 1)) + _ (case (docs.get-global server base-name) metadata (search-document server metadata stack opts)))))) (λ past? [?ast byte] diff --git a/src/fennel-ls/completions.fnl b/src/fennel-ls/completions.fnl index 2bd3245..c6d3544 100644 --- a/src/fennel-ls/completions.fnl +++ b/src/fennel-ls/completions.fnl @@ -26,7 +26,7 @@ seen {}] (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] "add the completion. also recursively adds the fields' completions" @@ -101,6 +101,20 @@ (io.stderr:write "BAD!!!! undocumented special: " (tostring special) "\n") {:label special})))) (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} diff --git a/src/fennel-ls/config.fnl b/src/fennel-ls/config.fnl index 55b5659..83096da 100644 --- a/src/fennel-ls/config.fnl +++ b/src/fennel-ls/config.fnl @@ -96,6 +96,12 @@ However, when not an option, fennel-ls will fall back to positionEncoding=\"utf- (set server.macro-modules {}) (set server.root-uri params.rootUri) (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)) (λ validate [{: configuration} invalid] diff --git a/src/fennel-ls/formatter.fnl b/src/fennel-ls/formatter.fnl index 430bd5b..3b1cd4c 100644 --- a/src/fennel-ls/formatter.fnl +++ b/src/fennel-ls/formatter.fnl @@ -172,17 +172,16 @@ fntype is one of fn or λ or lambda" :Snippet 15 :Color 16 :File 17 :Reference 18 :Folder 19 :EnumMember 20 :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" {:label name - :documentation (hover-format definition) - :filterText name - :textEdit {:newText name : range} - :kind (or (if ?kind (. kinds ?kind)) + :documentation (when (not server.can-do-good-completions?) (hover-format definition)) + :textEdit (when (not server.can-do-good-completions?) {:newText name : range}) + :kind (or (when ?kind (. kinds ?kind)) (. kinds (?. definition :metadata :fls/itemKind)) - (if (or (?. definition :metadata :fnl/arglist) - (?. (analyze-fn definition.definition)) :fntype) - (if (name:find ":") kinds.Method kinds.Function)))}) + (when (or (?. definition :metadata :fnl/arglist) + (?. (analyze-fn definition.definition)) :fntype) + (if (name:find ":") kinds.Method kinds.Function)))}) {: signature-help-format : hover-format diff --git a/src/fennel-ls/handlers.fnl b/src/fennel-ls/handlers.fnl index 683e97f..3fb6d37 100644 --- a/src/fennel-ls/handlers.fnl +++ b/src/fennel-ls/handlers.fnl @@ -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} ;; :notebookDocumentSync nil :completionProvider {:workDoneProgress false - :resolveProvider false + :resolveProvider server.can-do-good-completions? :triggerCharacters ["(" "[" "{"] :completionItem {:labelDetailsSupport 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)} (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}] (let [file (files.get-by-uri server uri)