From 957def8e4257d2250a52590ff0f0ef885b7a5dbd Mon Sep 17 00:00:00 2001 From: XeroOl Date: Fri, 2 Jun 2023 20:58:02 -0500 Subject: [PATCH] Improve goto-definition --- TODO.md | 2 ++ src/fennel-ls/compiler.fnl | 15 ++++++++++++--- test/goto-definition-test.fnl | 25 ++++++++++++++++++------- test/test-project/baz.fnl | 1 - test/test-project/goto-definition.fnl | 10 ++++++++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/TODO.md b/TODO.md index 2c0aa29..40283ed 100644 --- a/TODO.md +++ b/TODO.md @@ -4,6 +4,8 @@ My current goal is to work on completions a little bit more. +- [ ] Fix crash-files.test2 + Here is my feature wishlist. I don't expect to ever get all of this done, but these are the sort of enhancements I am thinking about. - [X] Able to connect to a client - [ ] Support for UTF-8 characters that aren't just plain ASCII. (especially `λ`) (perhaps just tell the IDE that I want to communicate with utf-8 offsets) diff --git a/src/fennel-ls/compiler.fnl b/src/fennel-ls/compiler.fnl index 2afde06..237b5d5 100644 --- a/src/fennel-ls/compiler.fnl +++ b/src/fennel-ls/compiler.fnl @@ -161,12 +161,19 @@ later by fennel-ls.language to answer requests from the client." (where [_fn _name args] (fennel.sequence? args)) args _ [])) (each [_ argument (ipairs args)] - (define (sym :nil) argument scope))) ;; we say function arguments are set to nil + (define (sym :nil) argument scope))) ;; TODO for now, function arguments are set to nil (λ define-function [ast scope] ;; handle the definitions of a function (define-function-name ast scope)) + (λ compile-for [ast binding scope] + (define (sym :nil) binding scope)) + + (λ compile-each [ast bindings scope] + (each [i binding (ipairs bindings)] + (define (sym :nil) binding scope))) + (λ compile-fn [ast scope] (tset scopes ast scope) (define-function-args ast scope)) @@ -244,8 +251,10 @@ later by fennel-ls.language to answer requests from the client." ;; :chunk I don't know what this one is :assert-compile on-compile-error :parse-error on-parse-error - :customhook-early-do compile-do - :customhook-early-fn compile-fn} + :customhook-early-for compile-for + :customhook-early-each compile-each + :customhook-early-fn compile-fn + :customhook-early-do compile-do} scope (fennel.scope) opts {:filename file.uri :plugins [plugin] diff --git a/test/goto-definition-test.fnl b/test/goto-definition-test.fnl index 6733e37..bf3830d 100644 --- a/test/goto-definition-test.fnl +++ b/test/goto-definition-test.fnl @@ -7,10 +7,12 @@ (describe "jump to definition" + (var CLIENT nil) (fn check [request-file line char response-file start-line start-col end-line end-col] - (let [client (create-client) + (let [client (or CLIENT (create-client)) message (client:definition (.. ROOT-URI :/ request-file) line char) uri (.. ROOT-URI "/" response-file)] + (set CLIENT client) (is-matching message [{:jsonrpc "2.0" :id client.prev-id @@ -52,6 +54,9 @@ (it "can go to a function in another file when accessed by multisym" (check :goto-definition.fnl 7 7 :./foo.fnl 2 4 2 13)) + (it "can go to a function in another file imported via destructuring assignment" ;; WORKS, just needs a test case + (check :goto-definition.fnl 2 11 :./baz.fnl 0 4 0 9)) + (it "goes further if you go to definition on a binding" (check :goto-definition.fnl 31 12 :goto-definition.fnl 23 4 23 5)) @@ -72,9 +77,15 @@ (it "can go to `a.b` from an `a.b.c` symbol" (check :goto-definition.fnl 54 9 :goto-definition.fnl 53 13 53 25)) - ;; TODO - ;; (it "doesn't leak function arguments to the surrounding scope") - ;; (it "can go to a function in another file imported via destructuring assignment") ;; WORKS, just needs a test case + (it "doesn't leak function arguments to the surrounding scope" + (check :goto-definition.fnl 58 7 :goto-definition.fnl 53 7 53 8)) + + (it "can go to identifiers introduced by (for)" + (check :goto-definition.fnl 61 9 :goto-definition.fnl 60 6 60 7)) + + (it "can go to identifiers introduced by (each)" + (check :goto-definition.fnl 64 2 :goto-definition.fnl 63 7 63 8)) + ;; (it "can go through more than one extra file") ;; (it "will give up instead of freezing on recursive requires") ;; (it "finds the definition of in-file macros") @@ -87,7 +98,7 @@ ;; (it "finds (tset a :b) definitions") ;; (it "finds (setmetatable a {__index {:b def}) definitions") ;; (it "finds definitions into a function (fn foo [] (local x 10) {: x}) (let [result (foo)] (print result.x)) finds result.x") - ;; (it "finds basic setmetatable definitions with an __index function") - ;; (it "can return to callsite and go through a function's arguments when they're available") - ;; (it "can go to a function's reference OR read type inference comments when callsite isn't available (PICK ONE)") + ;; (it "finds definitions through a function (fn foo [{: y}] {:x y}) (let [result (foo {:y {}})] (print result.x)) finds result.x") + ;; (it "finds through setmetatable with an __index function") + ;; (it "can go to a function's references OR read type inference comments when callsite isn't available (PICK ONE)") ;; (it "can work with a custom fennelpath") ;; Wait until an options system is done diff --git a/test/test-project/baz.fnl b/test/test-project/baz.fnl index 1a92f8f..ad3e105 100644 --- a/test/test-project/baz.fnl +++ b/test/test-project/baz.fnl @@ -1,4 +1,3 @@ - (fn bazfn [] (print "you called bazfn")) diff --git a/test/test-project/goto-definition.fnl b/test/test-project/goto-definition.fnl index d050eb8..870534a 100644 --- a/test/test-project/goto-definition.fnl +++ b/test/test-project/goto-definition.fnl @@ -53,3 +53,13 @@ (local x {:y {:z (+ 1 1)}}) (print x.y.z) + +(fn other [x] + (print x)) +(print x) + +(for [i 1 10] + (other i)) + +(each [k {: v} (pairs x)] + k v)