Clean up love2d parser and restructure code

This commit is contained in:
Emma 2024-09-06 18:42:31 -04:00
parent 3816bd81cc
commit e1d3b7b257

View File

@ -5,21 +5,18 @@
(local require-love-api (local require-love-api
(partial require (.. love-api-build-directory :/love_api))) (partial require (.. love-api-build-directory :/love_api)))
(local stringify-table fennel.view)
; ;
; UTILS ; UTILS
; ----- ; -----
(fn merge [...] (fn build-lsp-value [name ?args ?docstring ?fields]
(let [arg-count (select "#" ...) "Takes ... and returns a table to be used with the LSP."
args [...]] (let [lsp-value {:binding name}
(if (= arg-count 0) ?metadata (or ?args ?docstring)]
{} (when ?metadata (set lsp-value.metadata {}))
(faccumulate [result {} i 1 arg-count] (when ?args (set lsp-value.metadata.fnl/arglist ?args))
(collect [k v (pairs (. args i)) &into result] (when ?docstring (set lsp-value.metadata.fnl/docstring ?docstring))
(if (?. result k) (when ?fields (set lsp-value.fields ?fields))
(values k (merge v (. result k))) lsp-value))
(values k v)))))))
(fn download-love-api-tooling! [] (fn download-love-api-tooling! []
"Clones the LÖVE-API git repository that contains tooling to scrape and "Clones the LÖVE-API git repository that contains tooling to scrape and
@ -28,62 +25,86 @@
(git-clone love-api-build-directory (git-clone love-api-build-directory
"https://github.com/love2d-community/love-api"))) "https://github.com/love2d-community/love-api")))
(fn build-lsp-value [name ?args ?docstring] (fn merge [...]
"Takes ... and returns a table to be used with the LSP." (let [arg-count (select "#" ...)
(let [lsp-value {:binding name :metadata {}}] args [...]]
(when ?args (set lsp-value.metadata.fnl/arglist ?args)) (if (= arg-count 0)
(when ?docstring (set lsp-value.metadata.fnl/docstring ?docstring)) {}
lsp-value)) (faccumulate [result {} i 1 arg-count]
(collect [k v (pairs (. args i)) &into result]
(values k v))))))
; ;
; PARSERS ; PARSERS
; ------- ; -------
(fn fn-arguments->names [arguments] (fn variant-arguments->names [arguments]
"Given an array of arguments, return all names as an array." "Given an array of arguments, return all names as an array."
(icollect [_i {:description _ : name :type _} (ipairs arguments)] (icollect [_i {:description _ : name :type _} (ipairs arguments)]
name)) name))
(fn fn-return->string [returns] (fn variant-return->string [returns]
"Given an array of arguments, return a formatted description." "Given an array of return values, return a formatted description."
(accumulate [x "\n\nReturns -" _i {: description : name :type return-type} (ipairs returns)] (accumulate [x "\n\nReturns -" _i {: description : name :type return-type} (ipairs returns)]
(.. x "\n" " * " name " (`" return-type "`) - " description))) (.. x "\n" " * " name " (`" return-type "`) - " description)))
(fn parse-fn-variant [variant] (fn parse-first-function-variant [[variant]]
"Given an array of fuction variants, return an object where the first variant "Given an array of fuction variants, format and return the first variant
is made the formatted LSP option, with any remaining variants being formatted for the LSP."
as a single description."
(collect [v-key v-value (pairs variant)] (collect [v-key v-value (pairs variant)]
(case v-key (case v-key
:returns (values :returns v-value) :returns (values :returns (variant-return->string v-value))
:arguments (values :args (fn-arguments->names v-value))))) :arguments (values :args (variant-arguments->names v-value)))))
(fn parse-doc-module-tbl [docs-tbl] (fn love-functions->lsp [docs-tbl prefix]
"Takes a LÖVE-API documentation table and generates a list of each "Given an array of documented functions for a LÖVE module, generate a table
key with values suitable for the Fennel LSP." for the Fennel LSP."
{:fields (collect [_i value (ipairs docs-tbl)] (collect [_i value (ipairs docs-tbl)]
(let [{: name : description} value (let [{: name : description} value
binding (.. prefix name)
?variants (?. value :variants) ?variants (?. value :variants)
first-variant (if ?variants first-variant (if ?variants
(parse-fn-variant (. ?variants 1)) (parse-first-function-variant ?variants)
nil) nil)
?args (?. first-variant :args) ?args (?. first-variant :args)
?returns (?. first-variant :returns) ?returns (or (?. first-variant :returns) "")
docstring (.. description docstring (.. description ?returns)]
(if ?returns (fn-return->string ?returns) ""))] (values name (build-lsp-value binding ?args docstring)))))
(values name (build-lsp-value name ?args docstring))))})
(fn love-api->root-lsp-tbl [love-api] (fn module-list->fields [modules ?prefix]
(let [love-doc-string (.. "LÖVE is a framework for making " "Given a list of LÖVE modules from the LÖVE-API Lua library, recursively
"2D games in the Lua programming language.") generate LSP data for Fennel."
love-docs (build-lsp-value :love nil love-doc-string) (collect [_i module (ipairs modules)]
love-functions (parse-doc-module-tbl love-api.functions) (let [{: name} module ; Other keys - :enum, :functions, :types
love-callbacks (parse-doc-module-tbl love-api.callbacks)] prefix (if ?prefix (.. ?prefix ".") "")
{:love (merge love-docs love-functions love-callbacks)})) binding (.. prefix name)
?docstring (?. module :description)
?functions (?. module :functions)
?modules (?. module :modules)
function-keys (if ?functions
(love-functions->lsp ?functions (.. binding "."))
{})
module-keys (if ?modules (module-list->fields ?modules binding) {})
fields (merge function-keys module-keys)]
(values name (build-lsp-value binding nil ?docstring fields)))))
(fn get-all-love-api-functions [love-api]
[(table.unpack love-api.functions) (table.unpack love-api.callbacks)])
(fn love-api->lsp [love-api]
"Given documentation for the entire LÖVE framework from the LÖVE-API Lua
library, generate the root LÖVE object suitable for the Fennel LSP."
(let [root-module {:description (.. "LÖVE is a framework for making 2D "
"games in the Lua programming language.")
:functions (get-all-love-api-functions love-api)
:modules love-api.modules
:name :love}]
(module-list->fields [root-module])))
(fn convert [] (fn convert []
"Convert LÖVE framework from Lua table to a configuration object
used by fennel-ls."
(download-love-api-tooling!) (download-love-api-tooling!)
(let [love-api (require-love-api) (let [love-api (require-love-api)]
root-lsp-tbl (love-api->root-lsp-tbl love-api)] (fennel.view (love-api->lsp love-api))))
(stringify-table root-lsp-tbl)))
{: convert} {: convert}