From 0641b1b098c6e80c36cf0846df044ca5342aa940 Mon Sep 17 00:00:00 2001 From: XeroOl Date: Wed, 2 Jul 2025 19:11:10 -0500 Subject: [PATCH] simplify completions --- src/fennel-ls/analyzer.fnl | 28 +++++++++++------------ src/fennel-ls/compiler.fnl | 3 --- src/fennel-ls/completion.fnl | 43 ++++++++++++------------------------ test/completion.fnl | 4 ++++ 4 files changed, 31 insertions(+), 47 deletions(-) diff --git a/src/fennel-ls/analyzer.fnl b/src/fennel-ls/analyzer.fnl index e4aa221..08e8062 100644 --- a/src/fennel-ls/analyzer.fnl +++ b/src/fennel-ls/analyzer.fnl @@ -77,18 +77,18 @@ find the definition `10`, but if `opts.stop-early?` is set, it would find "searches for the definition of the ast, adjusted to 1 value" (search-multival server file ?ast stack 1 opts)) -(λ search-assignment [server file assignment stack opts] - (let [{:target {:binding _ - :definition ?definition - :keys ?keys - :multival ?multival - :fields ?fields}} assignment] +(λ search-definition [server file definition stack opts] + (let [{:binding _ + :definition ?definition + :keys ?keys + :multival ?multival + :fields ?fields} definition] (if (and (= 0 (length stack)) opts.stop-early?) - assignment.target ;; BASE CASE!! + definition ;; BASE CASE!! ;; :fields (and (not= 0 (length stack)) (?. ?fields (. stack (length stack)))) - (search-assignment server file {:target (. ?fields (table.remove stack))} stack opts) + (search-definition server file (. ?fields (table.remove stack)) stack opts) ;; This case is hard to explain. ;; Under these conditions, search-multival is planning on returning {:definition ?definition : file} @@ -101,7 +101,7 @@ find the definition `10`, but if `opts.stop-early?` is set, it would find (= 1 (or 1 ?multival)) (not (sym? ?definition)) (= 0 (length stack))) - assignment.target + definition (search-multival server file ?definition (stack-add-keys! stack ?keys) (or ?multival 1) opts)))) @@ -109,7 +109,7 @@ find the definition `10`, but if `opts.stop-early?` is set, it would find (if ref.target.metadata (search-document server ref.target stack opts) ref.target.binding - (search-assignment server file ref stack opts))) + (search-definition server file ref.target stack opts))) (λ search-symbol [server file symbol stack opts] (if (= (tostring symbol) :nil) @@ -237,7 +237,7 @@ initialization-opts: {:stack ?list[ast] (case (docs.get-builtin server base-name) metadata (search-document server metadata stack opts) _ (case (find-local-definition file base-name scope) - def (search-val server file def.definition (stack-add-keys! stack def.keys) opts) + def (search-definition server file def [] opts) _ (case (docs.get-global server base-name) metadata (search-document server metadata stack opts)))))) @@ -328,13 +328,11 @@ returns the called symbol and the number of the argument closest to byte" (catch _ nil))) (λ find-definition [server file symbol ?byte] - (if (. file.definitions symbol) - (. file.definitions symbol) + (or (. file.definitions symbol) (search server file symbol {:stop-early? false} {:byte ?byte}))) (λ find-nearest-definition [server file symbol ?byte] - (if (. file.definitions symbol) - (. file.definitions symbol) + (or (. file.definitions symbol) (search server file symbol {:stop-early? true} {:byte ?byte}))) {: find-symbol diff --git a/src/fennel-ls/compiler.fnl b/src/fennel-ls/compiler.fnl index 463c974..b545c25 100644 --- a/src/fennel-ls/compiler.fnl +++ b/src/fennel-ls/compiler.fnl @@ -65,9 +65,6 @@ identifiers are declared / referenced in which places." (λ line+byte->range [server file line byte] (let [line (- line 1) - ;; some errors in fennel erroneously say column -1 - ;; try compiling "(do\n" to see what I mean - byte (math.max 0 byte) position (utils.pos->position file.text line byte server.position-encoding)] {:start position :end position})) diff --git a/src/fennel-ls/completion.fnl b/src/fennel-ls/completion.fnl index e9005fb..539d468 100644 --- a/src/fennel-ls/completion.fnl +++ b/src/fennel-ls/completion.fnl @@ -1,10 +1,10 @@ (local files (require :fennel-ls.files)) (local utils (require :fennel-ls.utils)) (local analyzer (require :fennel-ls.analyzer)) -(local docs (require :fennel-ls.docs)) (local fennel (require :fennel)) (local message (require :fennel-ls.message)) (local format (require :fennel-ls.formatter)) +(local navigate (require :fennel-ls.navigate)) (local {:metadata METADATA} (require :fennel.compiler)) (λ textDocument/completion [server _send {: position :textDocument {: uri}}] @@ -30,37 +30,22 @@ (fn add-completion-recursively! [name definition] "add the completion. also recursively adds the fields' completions" - - (fn add-field-recursively! [field def] - "TODO name this thing" - (if (or (= :self (tostring (?. def :metadata :fnl/arglist 1))) - (and (fennel.list? def.definition) - (or (and (fennel.sym? (. def.definition 1) "fn") - (fennel.sym? (?. def.definition 2 1) "self")) - (and (fennel.sym? (. def.definition 1) "λ") - (fennel.sym? (?. def.definition 2 1) "self"))))) - (add-completion-recursively! (.. name ":" field) def) - (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 server definition.file value {} {}) - def (add-field-recursively! field def) - _ (do - (io.stderr:write "BAD!!!! undocumented field: " (tostring field) "\n") - {:label field}))))) - (when definition.fields - (each [field def (pairs definition.fields)] - (when (= (type field) :string) - (add-field-recursively! field def)))) - + (each [field def ?string-method (navigate.iter-fields server definition)] + (if (or (= :self (tostring (?. def :metadata :fnl/arglist 1))) + ?string-method + (and (fennel.list? def.definition) + (or (fennel.sym? (. def.definition 1) "fn") + (fennel.sym? (. def.definition 1) "λ")) + (or (and (fennel.table? (. def.definition 2)) + (fennel.sym? (. def.definition 2 1) "self")) + (and (fennel.sym? (. def.definition 2)) + (fennel.table? (. def.definition 3)) + (fennel.sym? (?. def.definition 3 1) "self"))))) + (add-completion-recursively! (.. name ":" field) def) + (add-completion-recursively! (.. name "." field) def))) (set (. seen definition) false))) (local seen-manglings {}) diff --git a/test/completion.fnl b/test/completion.fnl index da97d02..aebe81f 100644 --- a/test/completion.fnl +++ b/test/completion.fnl @@ -119,6 +119,10 @@ ;; stretchy completions (check "(local x {:field 100})\n(if fi" [:x.field] []) (check "(local x {:field {:deep 100}})\n(if de" [:x.field.deep] []) + (check "(local t {:field (fn [foo] nil)})\n(t|" [:t.field] []) + (check "(local t {:field (fn [self] nil)})\n(t|" [:t:field] []) + (check "(local t {})\n(fn t.field [foo] nil)})\n(t|" [:t.field] []) + (check "(local t {})\n(fn t.field [self] nil)})\n(t|" [:t:field] []) nil) (fn test-builtin []