fix documentation for macros, and fix completion item kind

This commit is contained in:
XeroOl 2025-04-23 23:32:17 -05:00
parent 3f1c2ea361
commit 5bb3f76050
3 changed files with 63 additions and 63 deletions

View File

@ -5,13 +5,7 @@
(local fennel (require :fennel)) (local fennel (require :fennel))
(local message (require :fennel-ls.message)) (local message (require :fennel-ls.message))
(local format (require :fennel-ls.formatter)) (local format (require :fennel-ls.formatter))
(local {:metadata METADATA} (require :fennel.compiler))
;; CompletionItemKind
(local _kinds
{:Text 1 :Method 2 :Function 3 :Constructor 4 :Field 5 :Variable 6 :Class 7
:Interface 8 :Module 9 :Property 10 :Unit 11 :Value 12 :Enum 13 :Keyword 14
:Snippet 15 :Color 16 :File 17 :Reference 18 :Folder 19 :EnumMember 20
:Constant 21 :Struct 22 :Event 23 :Operator 24 :TypeParameter 25})
(λ textDocument/completion [server _send {: position :textDocument {: uri}}] (λ textDocument/completion [server _send {: position :textDocument {: uri}}]
;; get the file ;; get the file
@ -31,51 +25,46 @@
results [] results []
seen {}] seen {}]
(fn add-completion [definition name] (fn add-completion! [name definition ?kind]
(table.insert results (table.insert results (format.completion-item-format name definition range ?kind)))
(doto (format.completion-item-format name definition)
(tset :filterText name)
(tset :textEdit {:newText name : range}))))
(fn add-completion-recursively [definition name] (fn add-completion-recursively! [name definition]
"add the completion. also recursively adds the fields' completions" "add the completion. also recursively adds the fields' completions"
(when (not (. seen definition))
(set (. seen definition) true) (fn thing [field def]
(add-completion definition name) "TODO name this thing"
(when (= (type definition.definition) :string) (if (or (= :self (tostring (?. def :metadata :fnl/arglist 1)))
(each [key value (pairs (-> (docs.get-global server :string) (. :fields)))]
(add-completion-recursively value (.. name ":" key))))
(when (fennel.table? definition.definition)
(each [field value (pairs definition.definition)]
(when (= (type field) :string)
(case (analyzer.search-ast server definition.file value [] {})
def (if (or (= :self (tostring (?. def :metadata :fnl/arglist 1)))
(and (fennel.list? def.definition) (and (fennel.list? def.definition)
;; TODO check that arg is called `self`
(or (and (fennel.sym? (. def.definition 1) "fn") (or (and (fennel.sym? (. def.definition 1) "fn")
(fennel.sym? (?. def.definition 2 1) "self")) (fennel.sym? (?. def.definition 2 1) "self"))
(and (fennel.sym? (. def.definition 1) "λ") (and (fennel.sym? (. def.definition 1) "λ")
(fennel.sym? (?. def.definition 2 1) "self"))))) (fennel.sym? (?. def.definition 2 1) "self")))))
(add-completion-recursively def (.. name ":" field)) (add-completion-recursively! (.. name ":" field) def)
(add-completion-recursively def (.. name "." field))) (add-completion-recursively! (.. name "." field) def)))
(when (not (. seen definition))
(set (. seen definition) true)
(add-completion! name definition)
(when (= (type definition.definition) :string)
(each [key value (pairs (-> (docs.get-global server :string) (. :fields)))]
(add-completion-recursively! (.. name ":" key) value)))
(when (fennel.table? definition.definition)
(each [field value (pairs definition.definition)]
(when (= (type field) :string)
(case (analyzer.search-ast server definition.file value [] {})
;; TODO deduplicate code! copy 1
def (thing field def)
_ (do _ (do
(io.stderr:write "BAD!!!! undocumented field: " (tostring field) "\n") (io.stderr:write "BAD!!!! undocumented field: " (tostring field) "\n")
{:label field}))))) {:label field})))))
(when definition.fields (when definition.fields
(each [field value (pairs definition.fields)] (each [field def (pairs definition.fields)]
(when (= (type field) :string) (when (= (type field) :string)
(if (or (= :self (tostring (?. value :metadata :fnl/arglist 1))) ;; TODO deduplicate code! copy 2
(and (fennel.list? value.definition) (thing field def))))
;; TODO check that arg is called `self`
(or (and (fennel.sym? (. value.definition 1) "fn")
(fennel.sym? (?. value.definition 2 1) "self"))
(and (fennel.sym? (. value.definition 1) "λ")
(fennel.sym? (?. value.definition 2 1) "self")))))
(add-completion-recursively value (.. name ":" field))
(add-completion-recursively value (.. name "." field))))))
(set (. seen definition) false))) (set (. seen definition) false)))
;; end yield ;; endfn add-completion-recursively
(local seen-manglings {}) (local seen-manglings {})
@ -85,11 +74,11 @@
(case (analyzer.search-name-and-scope server file global* scope) (case (analyzer.search-name-and-scope server file global* scope)
def (if (and (= :_G (tostring global*)) def (if (and (= :_G (tostring global*))
(not (: (tostring ?symbol) :match "_G[:.]"))) (not (: (tostring ?symbol) :match "_G[:.]")))
(add-completion def global*) (add-completion! global* def)
(add-completion-recursively def global*)) (add-completion-recursively! global* def))
_ (do _ (do
(io.stderr:write "BAD!!!! undocumented global: " (tostring global*) "\n") (io.stderr:write "BAD!!!! undocumented global: " (tostring global*) "\n")
{:label global*})))) (add-completion! global* {})))))
(var scope scope) (var scope scope)
@ -98,16 +87,19 @@
(when (not (. seen-manglings mangling)) (when (not (. seen-manglings mangling))
(set (. seen-manglings mangling) true) (set (. seen-manglings mangling) true)
(case (analyzer.search-name-and-scope server file mangling scope) (case (analyzer.search-name-and-scope server file mangling scope)
def (add-completion-recursively def mangling) def (add-completion-recursively! mangling def)
_ (add-completion-recursively {} mangling)))) _ (add-completion-recursively! mangling {}))))
(when in-call-position? (when in-call-position?
(each [macro* (pairs scope.macros)] (each [macro* macro-value (pairs scope.macros)]
(table.insert results {:label macro* :filterText macro* :textEdit {:newText macro* : range}})) (add-completion! macro*
{:binding macro*
:metadata (. METADATA macro-value)}
:Keyword))
(each [special (pairs scope.specials)] (each [special (pairs scope.specials)]
(case (analyzer.search-name-and-scope server file special scope) (case (analyzer.search-name-and-scope server file special scope)
def (add-completion-recursively def special) def (add-completion! special def :Operator)
_ (do _ (do
(io.stderr:write "BAD!!!! undocumented special: " (tostring special) "\n") (io.stderr:write "BAD!!!! undocumented special: " (tostring special) "\n")
{:label special})))) {:label special}))))

View File

@ -172,15 +172,17 @@ 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 [label result] (λ completion-item-format [name definition range ?kind]
"Makes a completion item" "Makes a completion item"
(doto {:label name
(case (analyze-fn result.definition) :documentation (hover-format definition)
{:fntype _} {: label :filterText name
:kind (if (label:find ":") kinds.Method kinds.Function)} :textEdit {:newText name : range}
_ {: label :kind (or (if ?kind (. kinds ?kind))
:kind (. kinds (?. result :metadata :fls/itemKind))}) (. kinds (?. definition :metadata :fls/itemKind))
(tset :documentation (hover-format result)))) (if (or (?. definition :metadata :fnl/arglist)
(?. (analyze-fn definition.definition)) :fntype)
(if (name:find ":") kinds.Method kinds.Function)))})
{: signature-help-format {: signature-help-format
: hover-format : hover-format

View File

@ -199,6 +199,13 @@
;; builtin macros ;; builtin macros
{:label :-?> {:label :-?>
:kind kinds.Keyword :kind kinds.Keyword
:documentation true}
;; builtin globals
{:label :table
:kind kinds.Module
:documentation true}
{:label :_G
:kind kinds.Variable
:documentation true}] :documentation true}]
[{:documentation #(= nil $) :label #(not (. things-that-are-allowed-to-have-missing-docs $))} [{:documentation #(= nil $) :label #(not (. things-that-are-allowed-to-have-missing-docs $))}
{:kind #(= nil $) :label #(not (. things-that-are-allowed-to-have-missing-docs $))} {:kind #(= nil $) :label #(not (. things-that-are-allowed-to-have-missing-docs $))}
@ -210,26 +217,25 @@
t {: x}] t {: x}]
(t." (t."
[:x] [:x]
[:_G [{:documentation #(= nil $)}
{:documentation #(= nil $)}
{:kind #(= nil $)} {:kind #(= nil $)}
{:label #(= nil $)}]) {:label #(= nil $)}])
(check "(let [x :hi] (check "(let [x :hi]
(x.|))" (x:|))"
[:gsub [:x:gsub
:gmatch :x:match
:match :x:match
:sub :x:sub
:len :x:len
:find] :x:find]
[{:documentation #(= nil $)}]) [{:documentation #(= nil $)}])
nil) nil)
(fn test-module [] (fn test-module []
(check "(coroutine.y|" (check "(coroutine.y|"
[{:label "yield" [{:label "coroutine.yield"
:documentation #(and $.value ($.value:find "```fnl\n(coroutine.yield ...)\n```" 1 true))}] :documentation #(and $.value ($.value:find "```fnl\n(coroutine.yield ...)\n```" 1 true))}]
[{:documentation #(= nil $)}]) [{:documentation #(= nil $)}])
(check "(local c coroutine) (check "(local c coroutine)
@ -238,10 +244,10 @@
[{:documentation #(= nil $)}]) [{:documentation #(= nil $)}])
(check "(local t table) (check "(local t table)
(t.i" (t.i"
["insert"] ["table.insert" "t.insert"]
[{:documentation #(= nil $)}]) [{:documentation #(= nil $)}])
(check "debug.deb|" (check "debug.deb|"
[{:label "debug" [{:label "debug.debug"
:documentation #(and $.value ($.value:find "```fnl\n(debug.debug)\n```" 1 true))}] :documentation #(and $.value ($.value:find "```fnl\n(debug.debug)\n```" 1 true))}]
[]) [])
nil) nil)