make multival definition tracking much better
there should now be no cases where multivals and table destructures are confused. ie, (local [_ x] (values 1 2)) and (local (_ x) [1 2]) are recognized as nonsense.
This commit is contained in:
parent
297f6c4fa9
commit
8b6d905450
@ -1,5 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
* Fix bug with renaming vars
|
||||
* Improve multival tracking
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Initial Features
|
||||
|
||||
@ -90,7 +90,6 @@ later by fennel-ls.language to answer requests from the client."
|
||||
(do ;; already exists
|
||||
(assert (= symbol (. references symbol :symbol)) (.. "the symbol should always be the same")))
|
||||
;; (assert (= target (. references symbol :target)) (.. "different targets: " (view target) (view (. references symbol :target)))))
|
||||
;; (print "old and new" ref-type (. references symbol :ref-type)))
|
||||
(let [ref {: symbol : target : ref-type}]
|
||||
(tset references symbol ref)
|
||||
(table.insert target.referenced-by ref))))))
|
||||
@ -108,7 +107,7 @@ later by fennel-ls.language to answer requests from the client."
|
||||
;; recursively explore the binding (which, in the general case, is a destructuring assignment)
|
||||
;; right now I'm not keeping track of *how* the symbol was destructured: just finding all the symbols for now.
|
||||
;; also, there's no logic for (values)
|
||||
(λ recurse [binding keys]
|
||||
(λ recurse [binding keys depth]
|
||||
(if (sym? binding)
|
||||
(let [definition
|
||||
{: binding
|
||||
@ -117,31 +116,33 @@ later by fennel-ls.language to answer requests from the client."
|
||||
:keys (if (< 0 (length keys))
|
||||
(fcollect [i 1 (length keys)]
|
||||
(. keys i)))
|
||||
:multival keys.multival
|
||||
:var? (?. ?opts :isvar)}]
|
||||
(tset (. definitions-by-scope scope) (tostring binding) definition)
|
||||
(tset definitions binding definition))
|
||||
(list? binding)
|
||||
(if (and (is-values? ?definition)
|
||||
(= (length binding)
|
||||
(- (length ?definition) 1)))
|
||||
(for [i 1 (length binding)]
|
||||
(define (. ?definition (+ i 1)) (. binding i) scope ?opts))
|
||||
(recurse (. binding 1) keys))
|
||||
(let [nested? (not= depth 0)]
|
||||
(if nested? (error (.. "I didn't expect to find a multival destructure in " (view binding) " at " (view keys))))
|
||||
(each [i child (ipairs binding)]
|
||||
(set keys.multival i)
|
||||
(recurse child keys (+ depth 1))
|
||||
(set keys.multival nil)))
|
||||
(table? binding)
|
||||
(accumulate [prev nil
|
||||
k v (iter binding)]
|
||||
(if (or (sym? k :&as) (sym? prev :&as))
|
||||
(recurse v keys)
|
||||
(or (sym? k :&) (sym? prev :&))
|
||||
;; currently the "rest" isn't counted as a binding
|
||||
nil
|
||||
(or (sym? v :&as) (sym? v :&))
|
||||
v
|
||||
key child (iter binding)]
|
||||
(if (or (sym? key :&as) (sym? prev :&as))
|
||||
;; if its &as, just keep the keys the same
|
||||
(recurse child keys (+ depth 1))
|
||||
(or (sym? key :&) (sym? prev :&))
|
||||
;; currently the "rest" param is defined to []
|
||||
(define [] child scope ?opts)
|
||||
(or (sym? child :&as) (sym? child :&))
|
||||
child
|
||||
(do
|
||||
(table.insert keys k)
|
||||
(recurse v keys)
|
||||
(table.insert keys key)
|
||||
(recurse child keys (+ depth 1))
|
||||
(table.remove keys))))))
|
||||
(recurse binding []))
|
||||
(recurse binding [] 0))
|
||||
|
||||
(λ mutate [_?definition binding scope]
|
||||
(λ recurse [binding keys]
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
The high level analysis system that does deep searches following
|
||||
the data provided by compiler.fnl."
|
||||
|
||||
(local {: sym? : list? : sequence? : varg? : sym &as fennel} (require :fennel))
|
||||
(local {: sym? : list? : sequence? : varg? : sym : view} (require :fennel))
|
||||
(local utils (require :fennel-ls.utils))
|
||||
(local state (require :fennel-ls.state))
|
||||
|
||||
@ -34,18 +34,28 @@ the data provided by compiler.fnl."
|
||||
(λ stack-add-multisym! [stack symbol]
|
||||
(stack-add-split! stack (utils.multi-sym-split symbol)))
|
||||
|
||||
(λ search-multival [self file ast stack ?multival opts]
|
||||
(let [multival (or ?multival 1)]
|
||||
(if (= 1 multival)
|
||||
(search-ast self file ast stack opts)
|
||||
(sym? ast) (values nil file) ;; BASE CASE !!
|
||||
(list? ast) (if (sym? (. ast 1) :values)
|
||||
(search-ast self file (. ast (+ 1 multival)) stack opts)
|
||||
(values nil file)) ;; GIVING UP !!
|
||||
(= :table (type ast)) (values nil file)))) ;; GIVING UP !!
|
||||
|
||||
(λ search-assignment [self file assignment stack opts]
|
||||
(assert assignment.target (.. "WRONG TYPE" (fennel.traceback)))
|
||||
(let [{:target {:binding _
|
||||
:definition ?definition
|
||||
:keys ?keys
|
||||
:multival ?multival
|
||||
:fields ?fields}} assignment]
|
||||
(if (and (= 0 (length stack)) opts.stop-early?)
|
||||
(values assignment.target file) ;; BASE CASE!!
|
||||
;; search a virtual field from :fields
|
||||
(and (not= 0 (length stack)) (?. ?fields (. stack (length stack))))
|
||||
(search-assignment self file {:target (. ?fields (table.remove stack))} stack opts)
|
||||
(search-ast self file ?definition (stack-add-keys! stack ?keys) opts))))
|
||||
(search-multival self file ?definition (stack-add-keys! stack ?keys) ?multival opts))))
|
||||
|
||||
(λ search-symbol [self file symbol stack opts]
|
||||
(if (= symbol -nil-)
|
||||
@ -84,7 +94,7 @@ the data provided by compiler.fnl."
|
||||
(where [-setmetatable- tbl _mt])
|
||||
(search-ast self file tbl stack opts)
|
||||
|
||||
;; functions evaluate to "themselves"
|
||||
;; fn marks a function literal
|
||||
[-fn-]
|
||||
(values {:definition call} file) ;; BASE CASE !!
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
(.. "file://" ROOT-PATH))
|
||||
|
||||
(local default-params
|
||||
{:capabilities {}
|
||||
{:capabilities {:general {:positionEncodings [:utf-8]}}
|
||||
:clientInfo {:name "Neovim" :version "0.7.2"}
|
||||
:initializationOptions {}
|
||||
:processId 16245
|
||||
|
||||
@ -104,6 +104,15 @@
|
||||
_response (c:definition :foo.fnl 1 8)]
|
||||
nil))
|
||||
|
||||
(it "can go through multival destructures"
|
||||
(let [c (doto (create-client)
|
||||
(: :open-file! :foo.fnl "(local [x y] (values [1 2] [3 4]))\n(local (a b) (values {:x y : y} {: x : y}))\n(print b.x a)"))
|
||||
[find_b] (c:definition :foo.fnl 2 9)]
|
||||
;; it finds the first `x` symbol
|
||||
(print (view find_b))
|
||||
(is.same find_b.result.range {:start {:line 0 :character 8} :end {:line 0 :character 9}})
|
||||
nil))
|
||||
|
||||
;; (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")
|
||||
|
||||
@ -37,18 +37,22 @@
|
||||
(check-rename "(fn [{: x}] x)" 0 8 :foo "(fn [{: foo}] foo)")
|
||||
(check-rename "(fn [{:x x}] x)" 0 9 :foo "(fn [{:x foo}] foo)"))
|
||||
|
||||
(it "renames a sym inside of lambda"
|
||||
(check-rename "(λ [foo] (print foo))" 0 6 :something
|
||||
"(λ [something] (print something))"))
|
||||
(it "renames a sym inside of lambda"
|
||||
(check-rename "(λ [foo] (print foo))" 0 6 :something
|
||||
"(λ [something] (print something))"))
|
||||
|
||||
(it "renames a sym inside of set"
|
||||
(check-rename "(var x 10)\n(set x 20)" 1 6 :something
|
||||
"(var something 10)\n(set something 20)"))
|
||||
(it "renames a sym inside of set"
|
||||
(check-rename "(var x 10)\n(set x 20)" 1 6 :something
|
||||
"(var something 10)\n(set something 20)"))
|
||||
|
||||
(it "renames a sym inside of set 2"
|
||||
(check-rename "(var x 10)\n(var m 0)\n(set (m x) (values 10 20))" 2 8 :something
|
||||
"(var something 10)\n(var m 0)\n(set (m something) (values 10 20))"))
|
||||
(it "renames a sym inside of set 2"
|
||||
(check-rename "(var x 10)\n(var m 0)\n(set (m x) (values 10 20))" 2 8 :something
|
||||
"(var something 10)\n(var m 0)\n(set (m something) (values 10 20))"))
|
||||
|
||||
(it "renames a sym inside of macro that uses multiple times"
|
||||
(check-rename "(var x 10)\n(doto x (set 20) (set 30))" 1 6 :something
|
||||
"(var something 10)\n(doto something (set 20) (set 30))")))
|
||||
(it "renames a sym inside of set 3"
|
||||
(check-rename "(var (x y) 10)\n(set (x y) 10)" 1 8 :something
|
||||
"(var (x something) 10)\n(set (x something) 10)"))
|
||||
|
||||
(it "renames a sym inside of macro that uses multiple times"
|
||||
(check-rename "(var x 10)\n(doto x (set 20) (set 30))" 1 6 :something
|
||||
"(var something 10)\n(doto something (set 20) (set 30))")))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user