last working in middle of refactor
This commit is contained in:
parent
d3f6d95c09
commit
68bad4eaba
@ -61,9 +61,6 @@ are declared / referenced in which places."
|
||||
{:start position :end position}))
|
||||
|
||||
|
||||
(λ is-values? [?ast]
|
||||
(and (list? ?ast) (= (sym :values) (. ?ast 1))))
|
||||
|
||||
(λ compile [{:configuration {: macro-path} : root-uri &as self} file]
|
||||
"Compile the file, and record all the useful information from the compiler into the file object"
|
||||
;; The useful information being recorded:
|
||||
@ -144,7 +141,8 @@ are declared / referenced in which places."
|
||||
(fcollect [i 1 (length keys)]
|
||||
(. keys i)))
|
||||
:multival ?multival
|
||||
:var? (?. ?opts :isvar)}]
|
||||
:var? (?. ?opts :isvar)
|
||||
: file}]
|
||||
(tset (. definitions-by-scope scope) (tostring symbol) definition)
|
||||
(tset definitions symbol definition)))))
|
||||
|
||||
@ -173,7 +171,8 @@ are declared / referenced in which places."
|
||||
(set target.fields (or target.fields {}))
|
||||
(tset target.fields field
|
||||
{:binding multisym
|
||||
:definition ast}))))
|
||||
:definition ast
|
||||
:file file}))))
|
||||
;; ;; referenced-by inherits from all other symbols
|
||||
;; :referenced-by (or (?. definitions multisym :referenced-by) [])}))))
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(local capabilities
|
||||
{:textDocumentSync {:openClose true :change 2}
|
||||
;; :notebookDocumentSync nil
|
||||
:completionProvider {:workDoneProgress false} ;; TODO
|
||||
:completionProvider {:workDoneProgress false}
|
||||
:hoverProvider {:workDoneProgress false
|
||||
:resolveProvider false
|
||||
:triggerCharacters ["(" "[" "{" "." ":" "\""]
|
||||
@ -79,8 +79,8 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(language.search-ast self file parent [] {:stop-early? true})
|
||||
;; regular symbol
|
||||
(language.search-main self file symbol {:stop-early? true} byte))
|
||||
(result result-file)
|
||||
(message.range-and-uri self result-file (or result.binding result.definition))
|
||||
result
|
||||
(message.range-and-uri self result.file (or result.binding result.definition))
|
||||
(catch _ nil))))
|
||||
|
||||
(λ requests.textDocument/references [self send {: position
|
||||
@ -91,12 +91,12 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(case-try (language.find-symbol file.ast byte)
|
||||
symbol
|
||||
(language.find-nearest-definition self file symbol byte)
|
||||
(where (definition def-file) (not= definition.referenced-by nil))
|
||||
(where definition (not= definition.referenced-by nil))
|
||||
(let [result (icollect [_ {: symbol} (ipairs definition.referenced-by)]
|
||||
(message.range-and-uri self def-file symbol))]
|
||||
(message.range-and-uri self definition.file symbol))]
|
||||
(if ?include-declaration?
|
||||
(table.insert result
|
||||
(message.range-and-uri self def-file definition.binding)))
|
||||
(message.range-and-uri self definition.file definition.binding)))
|
||||
|
||||
;; TODO don't include duplicates
|
||||
result)
|
||||
@ -157,7 +157,7 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(let [stack (fcollect [i (- (length split) 1) 2 -1]
|
||||
(. split i))]
|
||||
(case (language.search-assignment self file ref stack {})
|
||||
({: definition} file)
|
||||
{: definition : file}
|
||||
(case (values definition (type definition))
|
||||
;; fields of a string are hardcoded to "string"
|
||||
(_str :string) (icollect [label _ (pairs string)]
|
||||
@ -203,20 +203,20 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
symbol
|
||||
(language.find-nearest-definition self file symbol symbol.bytestart)
|
||||
;; TODO we are assuming that every reference is in the same file
|
||||
(where (definition def-file) (not= definition.referenced-by nil))
|
||||
(where definition (not= definition.referenced-by nil))
|
||||
(let [usages (icollect [_ {: symbol} (ipairs definition.referenced-by)
|
||||
&into [{:range (message.multisym->range self def-file definition.binding 1)
|
||||
&into [{:range (message.multisym->range self definition.file definition.binding 1)
|
||||
:newText new-name}]]
|
||||
(if (and (. file.lexical symbol)
|
||||
(not (rawequal symbol definition.binding)))
|
||||
{:newText new-name
|
||||
:range (message.multisym->range self def-file symbol 1)}))]
|
||||
:range (message.multisym->range self definition.file symbol 1)}))]
|
||||
|
||||
;; NOTE: I don't care about encoding here because we just need the relative positions
|
||||
(table.sort usages
|
||||
#(> (utils.position->byte def-file.text $1.range.start :utf-8)
|
||||
(utils.position->byte def-file.text $2.range.start :utf-8)))
|
||||
{:changes {def-file.uri usages}})
|
||||
#(> (utils.position->byte definition.file.text $1.range.start :utf-8)
|
||||
(utils.position->byte definition.file.text $2.range.start :utf-8)))
|
||||
{:changes {definition.file.uri usages}})
|
||||
(catch _ nil))))
|
||||
|
||||
(λ notifications.textDocument/didChange [self send {: contentChanges :textDocument {: uri}}]
|
||||
|
||||
@ -18,22 +18,13 @@ definitions backward.
|
||||
As of now, there's no caching, but that could be a way to improve performance.
|
||||
"
|
||||
|
||||
(local {: sym? : list? : sequence? : varg? : sym : view} (require :fennel))
|
||||
(local {: sym? : list? : sequence? : varg? : sym} (require :fennel))
|
||||
(local utils (require :fennel-ls.utils))
|
||||
(local state (require :fennel-ls.state))
|
||||
|
||||
(local get-ast-info utils.get-ast-info)
|
||||
|
||||
(local -require- (sym :require))
|
||||
(local -dot- (sym :.))
|
||||
(local -do- (sym :do))
|
||||
(local -let- (sym :let))
|
||||
(local -fn- (sym :fn))
|
||||
(local -nil- (sym :nil))
|
||||
(local -values- (sym :nil))
|
||||
(local -setmetatable- (sym :setmetatable))
|
||||
|
||||
(var search-ast nil) ;; all of the search functions are mutually recursive
|
||||
(var search-multival nil) ;; all of the search functions are mutually recursive
|
||||
|
||||
(λ stack-add-keys! [stack ?keys]
|
||||
"add the keys to the end of the stack in reverse order"
|
||||
@ -51,38 +42,9 @@ As of now, there's no caching, but that could be a way to improve performance.
|
||||
(λ 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
|
||||
;; we're looking at a (values), just solve it now
|
||||
(list? ast)
|
||||
(let [call (. ast 1)]
|
||||
(if
|
||||
(sym? call :do)
|
||||
(search-multival self file (. ast (length ast)) stack multival opts)
|
||||
(sym? call :values)
|
||||
;; (values x y z)
|
||||
;; len 3
|
||||
;; multival 2
|
||||
(let [len (- (length ast) 1)]
|
||||
(if (< multival len)
|
||||
(search-multival self file (. ast (+ 1 multival)) stack nil opts)
|
||||
(search-multival self file (. ast (+ len 1)) stack (+ multival (- len) 1) opts)))
|
||||
;; we're looking for value number 1 anyway
|
||||
(= 1 multival)
|
||||
(search-ast self file ast stack opts) ;; this goes to search-list but indirectly
|
||||
|
||||
(values nil file))) ;; GIVING UP !!
|
||||
|
||||
;; we're looking for value number 1 anyway
|
||||
(= 1 multival)
|
||||
(search-ast self file ast stack opts)
|
||||
|
||||
;; other cases
|
||||
(sym? ast) (values nil file) ;; BASE CASE !!
|
||||
;; (varg? ast) something
|
||||
(= :table (type ast)) (values nil file) ;; BASE CASE !!
|
||||
(values nil file)))) ;; supposed to be unreachable !!
|
||||
(λ search-val [self file ast stack opts]
|
||||
"searches for the definition of the ast, adjusted to 1 value"
|
||||
(search-multival self file ast stack 1 opts))
|
||||
|
||||
(λ search-assignment [self file assignment stack opts]
|
||||
(let [{:target {:binding _
|
||||
@ -91,69 +53,71 @@ As of now, there's no caching, but that could be a way to improve performance.
|
||||
:multival ?multival
|
||||
:fields ?fields}} assignment]
|
||||
(if (and (= 0 (length stack)) opts.stop-early?)
|
||||
(values assignment.target file) ;; BASE CASE!!
|
||||
assignment.target ;; 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-multival self file ?definition (stack-add-keys! stack ?keys) ?multival opts))))
|
||||
(search-multival self file ?definition (stack-add-keys! stack ?keys) (or ?multival 1) opts))))
|
||||
|
||||
(λ search-symbol [self file symbol stack opts]
|
||||
(if (= symbol -nil-)
|
||||
(values {:definition symbol} file) ;; BASE CASE !!
|
||||
(if (= (tostring symbol) :nil)
|
||||
{:definition symbol : file}
|
||||
;; TODO globals
|
||||
(case (. file.references symbol)
|
||||
to (search-assignment self file to (stack-add-multisym! stack symbol) opts))))
|
||||
|
||||
(λ search-table [self file tbl stack opts]
|
||||
(if (. tbl (. stack (length stack)))
|
||||
(search-ast self file (. tbl (table.remove stack)) stack opts)
|
||||
(search-val self file (. tbl (table.remove stack)) stack opts)
|
||||
(= 0 (length stack))
|
||||
(values {:definition tbl} file) ;; BASE CASE !!
|
||||
{:definition tbl : file} ;; BASE CASE !!
|
||||
nil)) ;; BASE CASE Give up
|
||||
|
||||
(λ search-list [self file call stack opts]
|
||||
(match call
|
||||
[-require- mod]
|
||||
(when (= :string (type mod))
|
||||
(let [newfile (state.get-by-module self mod)]
|
||||
(when newfile
|
||||
(let [newitem (. newfile.ast (length newfile.ast))]
|
||||
(search-ast self newfile newitem stack (doto opts (tset :searched-through-require true)))))))
|
||||
(λ search-list [self file call stack multival opts]
|
||||
(let [head (. call 1)]
|
||||
(if (sym? head)
|
||||
(case (tostring head)
|
||||
(where (or :do :let))
|
||||
(search-multival self file (. call (length call)) stack multival opts)
|
||||
:values
|
||||
(let [len (- (length call) 1)]
|
||||
(if (< multival len)
|
||||
(search-val self file (. call (+ 1 multival)) stack opts)
|
||||
(search-multival self file (. call (+ len 1)) stack (+ multival (- len) 1) opts)))
|
||||
:require
|
||||
(let [mod (. call 2)]
|
||||
(if (= multival 1)
|
||||
(when (= :string (type mod))
|
||||
(let [newfile (state.get-by-module self mod)]
|
||||
(when newfile
|
||||
(let [newitem (. newfile.ast (length newfile.ast))]
|
||||
(search-val self newfile newitem stack (doto opts (tset :searched-through-require true)))))))))
|
||||
"."
|
||||
(if (= multival 1)
|
||||
(let [[_ & rest] call]
|
||||
(search-val self file (. call 2) (stack-add-split! stack rest) opts)))
|
||||
;; TODO assume-function-name analyze-metatable
|
||||
:setmetatable
|
||||
(search-val self file (. call 2) stack opts)
|
||||
|
||||
;; A . form indexes into item 1 with the other items
|
||||
(where [-dot- & split] (. split 1))
|
||||
(search-ast self file (. split 1) (stack-add-split! stack split) opts)
|
||||
(where (or :fn :lambda :λ))
|
||||
(if (= multival 1)
|
||||
{:definition call : file}) ;; BASE CASE !!
|
||||
;; TODO expand-macros
|
||||
|
||||
;; A do block returns the last form
|
||||
(where [-do- & body] (. body 1))
|
||||
(search-ast self file (. body (length body)) stack opts)
|
||||
_
|
||||
(if (and (= multival 1) (= 0 (length stack)))
|
||||
{:definition call : file}))))) ;; BASE CASE!!
|
||||
|
||||
(where [-let- _binding & body] (. body 1))
|
||||
(search-ast self file (. body (length body)) stack opts)
|
||||
|
||||
(where [-values- first])
|
||||
(search-ast self file first stack opts)
|
||||
|
||||
;; TODO care about the setmetatable call
|
||||
(where [-setmetatable- tbl _mt])
|
||||
(search-ast self file tbl stack opts)
|
||||
|
||||
;; fn marks a function literal
|
||||
(where [fn*] (or (sym? fn* :fn) (sym? fn* :lambda) (sym? fn* :λ)))
|
||||
(values {:definition call} file) ;; BASE CASE !!
|
||||
|
||||
;; if we don't know, give up
|
||||
_
|
||||
(if (= 0 (length stack))
|
||||
(values {:definition call} file)))) ;; BASE CASE!!
|
||||
|
||||
(set search-ast
|
||||
(λ [self file item stack opts]
|
||||
(if
|
||||
(sym? item) (search-symbol self file item stack opts)
|
||||
(list? item) (search-list self file item stack opts)
|
||||
(= :table (type item)) (search-table self file item stack opts)
|
||||
(= 0 (length stack)) (values {:definition item} file)))) ;; BASE CASE !!
|
||||
;; (error (.. "I don't know what to do with " (view item))))))
|
||||
(set search-multival
|
||||
(λ [self file ast stack multival opts]
|
||||
(if (list? ast) (search-list self file ast stack multival opts)
|
||||
(varg? ast) nil ;; TODO function-args
|
||||
(= 1 multival)
|
||||
(if (sym? ast) (search-symbol self file ast stack opts)
|
||||
(= :table (type ast)) (search-table self file ast stack opts)
|
||||
(= 0 (length stack)) {:definition ast : file}) ;; BASE CASE !!
|
||||
nil)))
|
||||
|
||||
(local {:metadata METADATA
|
||||
:scopes {:global {:specials SPECIALS
|
||||
@ -181,12 +145,11 @@ If stop-early?, search-main will find the definition of `b` in (local b a).
|
||||
Otherwise, it would continue and find the value 1.
|
||||
|
||||
Returns:
|
||||
(values
|
||||
{:binding <where the symbol is bound. this would be the name of the function or variable>
|
||||
:definition <the best known definition>
|
||||
:keys <which part of the definition to look into. this can only possibly be present if stop-early?>
|
||||
:fields <other known fields which aren't part of the definition>}
|
||||
file)
|
||||
:fields <other known fields which aren't lexically part of the definition>
|
||||
: file}
|
||||
"
|
||||
|
||||
;; The stack is the multi-sym parts still to search
|
||||
@ -200,7 +163,7 @@ Returns:
|
||||
_ (case (. file.references symbol)
|
||||
ref (search-assignment self file ref stack opts)
|
||||
_ (case (. file.definitions symbol)
|
||||
def (search-multival self file def.definition (stack-add-keys! stack def.keys) def.multival opts)))))))
|
||||
def (search-multival self file def.definition (stack-add-keys! stack def.keys) (or def.multival 1) opts)))))))
|
||||
|
||||
(λ find-local-definition [file name ?scope]
|
||||
(when ?scope
|
||||
@ -221,7 +184,7 @@ Returns:
|
||||
_ (case (global-info self name)
|
||||
global-item global-item
|
||||
_ (case (find-local-definition file name scope)
|
||||
def (search-ast self file def.definition (stack-add-keys! stack def.keys) (or ?opts {})))))))
|
||||
def (search-val self file def.definition (stack-add-keys! stack def.keys) (or ?opts {})))))))
|
||||
|
||||
(λ _past? [?ast byte]
|
||||
;; check if a byte is past an ast object
|
||||
@ -281,7 +244,7 @@ Returns:
|
||||
|
||||
(λ find-nearest-definition [self file symbol ?byte]
|
||||
(if (. file.definitions symbol)
|
||||
(values (. file.definitions symbol) file)
|
||||
(. file.definitions symbol)
|
||||
(search-main self file symbol {:stop-early? true} ?byte)))
|
||||
|
||||
{: find-symbol
|
||||
@ -289,4 +252,4 @@ Returns:
|
||||
: search-main
|
||||
: search-assignment
|
||||
: search-name-and-scope
|
||||
: search-ast}
|
||||
:search-ast search-val}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user