From 21bd635123273141581098eb2501e9ee946e53b0 Mon Sep 17 00:00:00 2001 From: XeroOl Date: Thu, 29 Jun 2023 12:23:42 -0500 Subject: [PATCH] =?UTF-8?q?treat=20lambda=20and=20=CE=BB=20as=20function?= =?UTF-8?q?=20definitions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO.md | 6 ++++++ src/fennel-ls/compiler.fnl | 9 +++++++-- src/fennel-ls/handlers.fnl | 1 - src/fennel-ls/state.fnl | 2 +- test/diagnostic-test.fnl | 14 ++++++++++++++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/TODO.md b/TODO.md index e6354c3..e5861ca 100644 --- a/TODO.md +++ b/TODO.md @@ -58,6 +58,12 @@ Here is my feature wishlist. I don't expect to ever get all of this done, but th - [ ] `do`/`values` with only one inner form - [ ] redundant `do` as the last/only item in a form that accepts a "body" - [ ] `var` forms that could be `local` + - [ ] Arity checking + - [ ] Too many args (assuming there is no ... argument) + - [ ] Too few args (assuming the last argument is statically countable, and also account for ?optional arguments) + - [ ] I need to also make it work for built-in functions + - [ ] warn if an optional arg is present, but no call ever passes the arg + - [ ] Code that matches the shape of `accumulate` or `icollect` or `collect`?? or other macros?? - [ ] Dead code (I'm not sure what sort of things cause dead code) - [ ] Unused fields (difficult) - [ ] unification in a `match` pattern (difficult) diff --git a/src/fennel-ls/compiler.fnl b/src/fennel-ls/compiler.fnl index d4ba213..c15e8bd 100644 --- a/src/fennel-ls/compiler.fnl +++ b/src/fennel-ls/compiler.fnl @@ -12,6 +12,8 @@ later by fennel-ls.language to answer requests from the client." ;; because fennel doesn't allow 'require in a runtime file (local -require- (sym :require)) (local -fn- (sym :fn)) +(local -lambda- (sym :lambda)) +(local -λ- (sym :λ)) (λ ast->macro-ast [ast] [(fennel.list (sym :eval-compiler) @@ -49,7 +51,8 @@ later by fennel-ls.language to answer requests from the client." diagnostics {} ; [diagnostic] references {} ; symbol -> references scopes {} ; ast -> scope - require-calls {}]; ast -> boolean (does this ast start with the symbol `require) + require-calls {} ; ast -> boolean (does this ast start with the symbol `require) + calls {}]; array of all lists (λ find-definition [name ?scope] (when ?scope @@ -183,13 +186,14 @@ later by fennel-ls.language to answer requests from the client." (tset scopes ast scope)) (λ call [ast scope] + (tset calls ast (. ast 1)) (tset scopes ast scope) ;; Most calls aren't interesting, but here's the list of the ones that are: (case ast ;; This cannot be done through the :fn feature of the compiler plugin system ;; because it needs to be called *before* the body of the function is processed. ;; TODO check if hashfn needs to be here - (where [(= -fn-)]) + (where (or [(= -fn-)] [(= -lambda-)] [(= -λ-)] false)) ;; TODO, this false pattern should not ever match, and should be removed once I update fennel (define-function ast scope) (where [(= -require-) _modname]) (tset require-calls ast true) @@ -291,6 +295,7 @@ later by fennel-ls.language to answer requests from the client." ; ;; base case??? (set file.ast ast) + (set file.calls calls) (set file.scope scope) (set file.scopes scopes) (set file.definitions definitions) diff --git a/src/fennel-ls/handlers.fnl b/src/fennel-ls/handlers.fnl index eeeaf00..dcc6cbb 100644 --- a/src/fennel-ls/handlers.fnl +++ b/src/fennel-ls/handlers.fnl @@ -5,7 +5,6 @@ Every time the client sends a message, it gets handled by a function in the corr (ie, a textDocument/didChange notification will call notifications.textDocument/didChange and a textDocument/defintion request will call requests.textDocument/definition)" -(local {: pos->byte : apply-changes} (require :fennel-ls.utils)) (local diagnostics (require :fennel-ls.diagnostics)) (local message (require :fennel-ls.message)) (local state (require :fennel-ls.state)) diff --git a/src/fennel-ls/state.fnl b/src/fennel-ls/state.fnl index 8d16423..6189e43 100644 --- a/src/fennel-ls/state.fnl +++ b/src/fennel-ls/state.fnl @@ -22,7 +22,7 @@ in the \"self\" object." file))) (λ get-by-path [self path] - (get-by-uri (utils.path->uri path))) + (get-by-uri self (utils.path->uri path))) (λ get-by-module [self module] ;; check the cache diff --git a/test/diagnostic-test.fnl b/test/diagnostic-test.fnl index e7231d2..5b4abe0 100644 --- a/test/diagnostic-test.fnl +++ b/test/diagnostic-test.fnl @@ -81,6 +81,20 @@ "not found") _ (error "did not match")))) + ; (it "warns about unused functions" + ; (let [self (create-client) + ; responses (self:open-file! filename "(fn x [])")] + ; (match responses + ; [{:params {: diagnostics}}] + ; (is (find [i v (ipairs diagnostics)] + ; (match v + ; {:message "unused definition: x" + ; :range {:start {:character 7 :line 0} + ; :end {:character 8 :line 0}}} + ; v)) + ; "not found") + ; _ (error "did not match")))) + (it "does not warn if a field is used" (let [self (create-client) responses (self:open-file! filename "(fn [abc] (set abc.xyz 10))")]