Big refactoring
This commit is contained in:
parent
bb13e9b809
commit
f610201b9d
@ -14,7 +14,7 @@ Features / To Do List / Things I would enjoy patches for:
|
|||||||
- [ ] directly on require statements
|
- [ ] directly on require statements
|
||||||
- [X] for definitions in the same file
|
- [X] for definitions in the same file
|
||||||
- [ ] for definitions in other files
|
- [ ] for definitions in other files
|
||||||
- [ ] follows multisyms through table constructor
|
- [X] follows multisyms through table constructor
|
||||||
- [ ] follows multisyms through mutations (difficult)
|
- [ ] follows multisyms through mutations (difficult)
|
||||||
- [ ] for methods/metamethods (difficult, in the general case may require type annotations or some insane global type inference logic)
|
- [ ] for methods/metamethods (difficult, in the general case may require type annotations or some insane global type inference logic)
|
||||||
- [ ] into lua files (maybe cheeseable with antifennel if it has --correlate?)
|
- [ ] into lua files (maybe cheeseable with antifennel if it has --correlate?)
|
||||||
|
|||||||
@ -1,15 +1,12 @@
|
|||||||
(local fennel (require :fennel))
|
(local core (require :fennel-ls.core))
|
||||||
(local dispatch (require :fennel-ls.dispatch))
|
|
||||||
(local json-rpc (require :fennel-ls.json-rpc))
|
(local json-rpc (require :fennel-ls.json-rpc))
|
||||||
(local {: log} (require :fennel-ls.log))
|
|
||||||
|
|
||||||
(λ main-loop [in out]
|
(λ main-loop [in out]
|
||||||
(local send (partial json-rpc.write out))
|
(local send (partial json-rpc.write out))
|
||||||
(local state [])
|
(local state [])
|
||||||
(while true
|
(while true
|
||||||
(let [msg (json-rpc.read in)]
|
(let [msg (json-rpc.read in)]
|
||||||
;; (log msg)
|
(core.handle state send msg))))
|
||||||
(dispatch.handle state send msg))))
|
|
||||||
|
|
||||||
(λ main []
|
(λ main []
|
||||||
(main-loop
|
(main-loop
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
(local fennel (require :fennel))
|
(local fennel (require :fennel))
|
||||||
|
(local fennelutils (require :fennel.utils))
|
||||||
|
(local utils (require :fennel-ls.utils))
|
||||||
(local insert table.insert)
|
(local insert table.insert)
|
||||||
|
|
||||||
|
(local sym? fennel.sym?)
|
||||||
|
(local list? fennel.list?)
|
||||||
|
|
||||||
;; words surrounded by - are symbols,
|
;; words surrounded by - are symbols,
|
||||||
;; because fennel doesn't allow 'require in a runtime file
|
;; because fennel doesn't allow 'require in a runtime file
|
||||||
(local -require- (fennel.sym :require))
|
(local -require- (fennel.sym :require))
|
||||||
@ -8,6 +13,33 @@
|
|||||||
(local -λ- (fennel.sym :λ))
|
(local -λ- (fennel.sym :λ))
|
||||||
(local -lambda- (fennel.sym :lambda))
|
(local -lambda- (fennel.sym :lambda))
|
||||||
|
|
||||||
|
(λ contains? [?ast byte]
|
||||||
|
;; check if an ast contains a byte
|
||||||
|
(and (= (type ?ast) :table)
|
||||||
|
(utils.get-ast-info ?ast :bytestart)
|
||||||
|
(utils.get-ast-info ?ast :byteend)
|
||||||
|
(<= (utils.get-ast-info ?ast :bytestart)
|
||||||
|
byte
|
||||||
|
(+ 1 (utils.get-ast-info ?ast :byteend)))))
|
||||||
|
|
||||||
|
(λ does-not-contain? [?ast byte]
|
||||||
|
;; check if a byte is in range of the ast
|
||||||
|
(and (= (type ?ast) :table)
|
||||||
|
(utils.get-ast-info ?ast :bytestart)
|
||||||
|
(utils.get-ast-info ?ast :byteend)
|
||||||
|
(not
|
||||||
|
(<= (utils.get-ast-info ?ast :bytestart)
|
||||||
|
byte
|
||||||
|
(+ 1 (utils.get-ast-info ?ast :byteend))))))
|
||||||
|
|
||||||
|
|
||||||
|
(λ past? [?ast byte]
|
||||||
|
;; check if a byte is past an ast object
|
||||||
|
(and (= (type ?ast) :table)
|
||||||
|
(utils.get-ast-info ?ast :bytestart)
|
||||||
|
(< byte (utils.get-ast-info ?ast :bytestart))
|
||||||
|
false))
|
||||||
|
|
||||||
(λ multisym? [t]
|
(λ multisym? [t]
|
||||||
;; check if t is a symbol with multiple parts, eg. foo.bar.baz
|
;; check if t is a symbol with multiple parts, eg. foo.bar.baz
|
||||||
(and (fennel.sym? t)
|
(and (fennel.sym? t)
|
||||||
@ -126,5 +158,66 @@
|
|||||||
(set file.ast ast))
|
(set file.ast ast))
|
||||||
;; (set file.analyzed? true))
|
;; (set file.analyzed? true))
|
||||||
|
|
||||||
|
(var
|
||||||
|
(search-assignment
|
||||||
|
search-symbol
|
||||||
|
search)
|
||||||
|
nil)
|
||||||
|
|
||||||
{: analyze}
|
(set search-assignment
|
||||||
|
(λ search-assignment [self file binding ?definition stack]
|
||||||
|
(if (= 0 (length stack))
|
||||||
|
binding
|
||||||
|
;; TODO sift down the binding
|
||||||
|
(search self file ?definition stack))))
|
||||||
|
|
||||||
|
(set search-symbol
|
||||||
|
(λ search-symbol [self file symbol stack]
|
||||||
|
(let [split (utils.multi-sym-split symbol)]
|
||||||
|
(for [i (length split) 2 -1]
|
||||||
|
(table.insert stack (. split i))))
|
||||||
|
(match (. file.references symbol)
|
||||||
|
to (search-assignment self file to.binding to.definition stack)
|
||||||
|
nil nil)))
|
||||||
|
|
||||||
|
(set search
|
||||||
|
(λ search [self file item stack]
|
||||||
|
(if (fennelutils.table? item)
|
||||||
|
(if (. item (. stack (length stack)))
|
||||||
|
(search self file (. item (table.remove stack)) stack)
|
||||||
|
nil)
|
||||||
|
(sym? item)
|
||||||
|
(search-symbol self file item stack)
|
||||||
|
;; TODO
|
||||||
|
;; functioncall (continue searching in body)
|
||||||
|
;; require call (search in the new module)
|
||||||
|
:else (error (.. "I don't know what to do with " (fennel.view item))))))
|
||||||
|
|
||||||
|
(λ find-symbol [ast byte ?recursively-called]
|
||||||
|
(if (not= :table (type ast))
|
||||||
|
nil
|
||||||
|
(does-not-contain? ast byte)
|
||||||
|
nil
|
||||||
|
(sym? ast)
|
||||||
|
ast
|
||||||
|
(or (not ?recursively-called)
|
||||||
|
(fennel.list? ast)
|
||||||
|
(fennel.sequence? ast))
|
||||||
|
;; TODO binary search
|
||||||
|
(accumulate
|
||||||
|
[result nil
|
||||||
|
_ v (ipairs ast)
|
||||||
|
&until (or result (past? v byte))]
|
||||||
|
(find-symbol v byte true))
|
||||||
|
:else
|
||||||
|
(accumulate
|
||||||
|
[result nil
|
||||||
|
k v (pairs ast)
|
||||||
|
&until result]
|
||||||
|
(or
|
||||||
|
(find-symbol k byte true)
|
||||||
|
(find-symbol v byte true)))))
|
||||||
|
|
||||||
|
{: analyze
|
||||||
|
: find-symbol
|
||||||
|
: search-symbol}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
"Dispatch
|
"core
|
||||||
This module is responsible for deciding which code to call in response
|
This module is responsible for deciding which code to call in response
|
||||||
to a given LSP request from the client.
|
to a given LSP request from the client.
|
||||||
|
|
||||||
@ -7,12 +7,12 @@ In general, this involves:
|
|||||||
* determining the type of the message
|
* determining the type of the message
|
||||||
* calling the appropriate handler"
|
* calling the appropriate handler"
|
||||||
|
|
||||||
(local handlers (require :fennel-ls.the-actual-code))
|
(local handlers (require :fennel-ls.handlers))
|
||||||
(local message (require :fennel-ls.message))
|
(local message (require :fennel-ls.message))
|
||||||
|
|
||||||
(λ handle-request [self send id method ?params]
|
(λ handle-request [self send id method ?params]
|
||||||
"Call the appropriate request handler.
|
;; Call the appropriate request handler.
|
||||||
The return value of the request is sent back to the server."
|
;; The return value of the request is sent back to the server.
|
||||||
(match (. handlers.requests method)
|
(match (. handlers.requests method)
|
||||||
callback
|
callback
|
||||||
(match (callback self send ?params)
|
(match (callback self send ?params)
|
||||||
@ -26,15 +26,15 @@ The return value of the request is sent back to the server."
|
|||||||
id))))
|
id))))
|
||||||
|
|
||||||
(λ handle-response [self send id result]
|
(λ handle-response [self send id result]
|
||||||
"I don't care about responses yet"
|
;; I don't care about responses yet
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(λ handle-bad-response [self send id err]
|
(λ handle-bad-response [self send id err]
|
||||||
"Handle a message indicating an error. Right now, it just crashes the server."
|
;; Handle a message indicating an error. Right now, it just crashes the server.
|
||||||
(error (.. "oopsie: " err.code)))
|
(error (.. "oopsie: " err.code)))
|
||||||
|
|
||||||
(λ handle-notification [self send method ?params]
|
(λ handle-notification [self send method ?params]
|
||||||
"Call the appropriate notification handler."
|
;; Call the appropriate notification handler.
|
||||||
(match (. handlers.notifications method)
|
(match (. handlers.notifications method)
|
||||||
callback (callback self send ?params)))
|
callback (callback self send ?params)))
|
||||||
;; Silent error for unknown notifications
|
;; Silent error for unknown notifications
|
||||||
@ -1,19 +1,14 @@
|
|||||||
"The actual code
|
"Big dispatch
|
||||||
You finally made it. Here is the main code that implements the language server protocol
|
You finally made it. Here is the main code that implements the language server protocol
|
||||||
|
|
||||||
Every time the client sends a message, it gets handled by a function in the corresponding table type.
|
Every time the client sends a message, it gets handled by a function in the corresponding table type.
|
||||||
(ie, a textDocument/didChange notification will call notifications.textDocument/didChange
|
(ie, a textDocument/didChange notification will call notifications.textDocument/didChange
|
||||||
and a textDocument/defintion request will call requests.textDocument/didChange)"
|
and a textDocument/defintion request will call requests.textDocument/didChange)"
|
||||||
(local fennel (require :fennel))
|
(local utils (require :fennel-ls.utils))
|
||||||
(local sym? fennel.sym?)
|
(local message (require :fennel-ls.message))
|
||||||
(local list? fennel.list?)
|
|
||||||
(local fennelutils (require :fennel.utils))
|
|
||||||
|
|
||||||
(local parser (require :fennel-ls.parser))
|
|
||||||
(local util (require :fennel-ls.util))
|
|
||||||
(local mod (require :fennel-ls.mod))
|
|
||||||
(local {: log} (require :fennel-ls.log))
|
|
||||||
(local state (require :fennel-ls.state))
|
(local state (require :fennel-ls.state))
|
||||||
|
(local analyze (require :fennel-ls.analyze))
|
||||||
|
|
||||||
(local requests [])
|
(local requests [])
|
||||||
(local notifications [])
|
(local notifications [])
|
||||||
@ -64,81 +59,19 @@ Every time the client sends a message, it gets handled by a function in the corr
|
|||||||
{:capabilities capabilities
|
{:capabilities capabilities
|
||||||
:serverInfo {:name "fennel-ls" :version "0.0.0"}})
|
:serverInfo {:name "fennel-ls" :version "0.0.0"}})
|
||||||
|
|
||||||
;; These three functions are mutually recursive
|
|
||||||
(var
|
|
||||||
(search-assignment
|
|
||||||
search-symbol
|
|
||||||
search)
|
|
||||||
nil)
|
|
||||||
|
|
||||||
(set search-assignment
|
|
||||||
(λ search-assignment [self file binding ?definition stack]
|
|
||||||
(if (= 0 (length stack))
|
|
||||||
binding
|
|
||||||
;; TODO sift down the binding
|
|
||||||
(search self file ?definition stack))))
|
|
||||||
|
|
||||||
(set search-symbol
|
|
||||||
(λ search-symbol [self file symbol stack]
|
|
||||||
(let [split (util.multi-sym-split symbol)]
|
|
||||||
(for [i (length split) 2 -1]
|
|
||||||
(table.insert stack (. split i))))
|
|
||||||
(match (. file.references symbol)
|
|
||||||
to (search-assignment self file to.binding to.definition stack)
|
|
||||||
nil nil)))
|
|
||||||
|
|
||||||
(set search
|
|
||||||
(λ search [self file item stack]
|
|
||||||
(if (fennelutils.table? item)
|
|
||||||
(if (. item (. stack (length stack)))
|
|
||||||
(search self file (. item (table.remove stack)) stack)
|
|
||||||
nil)
|
|
||||||
(sym? item)
|
|
||||||
(search-symbol self file item stack)
|
|
||||||
;; TODO
|
|
||||||
;; functioncall (continue searching in body)
|
|
||||||
;; require call (search in the new module)
|
|
||||||
:else (error (.. "I don't know what to do with " (fennel.view item))))))
|
|
||||||
|
|
||||||
(λ find-symbol [ast byte ?recursively-called]
|
|
||||||
(if (not= :table (type ast))
|
|
||||||
nil
|
|
||||||
(parser.does-not-contain? ast byte)
|
|
||||||
nil
|
|
||||||
(sym? ast)
|
|
||||||
ast
|
|
||||||
(or (not ?recursively-called)
|
|
||||||
(fennel.list? ast)
|
|
||||||
(fennel.sequence? ast))
|
|
||||||
;; TODO binary search
|
|
||||||
(accumulate
|
|
||||||
[result nil
|
|
||||||
_ v (ipairs ast)
|
|
||||||
&until (or result (parser.past? v byte))]
|
|
||||||
(find-symbol v byte true))
|
|
||||||
:else
|
|
||||||
(accumulate
|
|
||||||
[result nil
|
|
||||||
k v (pairs ast)
|
|
||||||
&until result]
|
|
||||||
(or
|
|
||||||
(find-symbol k byte true)
|
|
||||||
(find-symbol v byte true)))))
|
|
||||||
|
|
||||||
(λ requests.textDocument/definition [self send {: position :textDocument {: uri}}]
|
(λ requests.textDocument/definition [self send {: position :textDocument {: uri}}]
|
||||||
(local file (state.get-by-uri self uri))
|
(local file (state.get-by-uri self uri))
|
||||||
(local byte (util.pos->byte file.text position.line position.character))
|
(local byte (utils.pos->byte file.text position.line position.character))
|
||||||
(match (find-symbol file.ast byte)
|
(match (analyze.find-symbol file.ast byte)
|
||||||
symbol
|
symbol
|
||||||
(match (search-symbol self file symbol [])
|
(match (analyze.search-symbol self file symbol [])
|
||||||
definition
|
definition
|
||||||
{:range (parser.range file.text definition)
|
{:range (message.range file.text definition)
|
||||||
:uri uri})))
|
:uri uri})))
|
||||||
|
|
||||||
(λ notifications.textDocument/didChange [self send {: contentChanges :textDocument {: uri}}]
|
(λ notifications.textDocument/didChange [self send {: contentChanges :textDocument {: uri}}]
|
||||||
(local file (state.get-by-uri self uri))
|
(local file (state.get-by-uri self uri))
|
||||||
(assert file.open?)
|
(assert file.open?)
|
||||||
(util.apply-changes (. self.files uri) contentChanges))
|
(utils.apply-changes (. self.files uri) contentChanges))
|
||||||
|
|
||||||
(λ notifications.textDocument/didOpen [self send {:textDocument {: languageId : text : uri}}]
|
(λ notifications.textDocument/didOpen [self send {:textDocument {: languageId : text : uri}}]
|
||||||
(local file (state.set-uri-contents self uri text))
|
(local file (state.set-uri-contents self uri text))
|
||||||
@ -1,20 +0,0 @@
|
|||||||
"Log
|
|
||||||
In the Language Server Protocol, io.stdout is used to send messages to the client.
|
|
||||||
Because of this, I need another way to do print-debugging."
|
|
||||||
|
|
||||||
(local fennel (require :fennel))
|
|
||||||
(local disable-logs false)
|
|
||||||
(if disable-logs
|
|
||||||
{:log #nil}
|
|
||||||
(let [logdocument (io.open "/tmp/fennel.log" "w")]
|
|
||||||
(assert logdocument)
|
|
||||||
(fn log [...]
|
|
||||||
(let [args []]
|
|
||||||
(for [i 1 (select :# ...)]
|
|
||||||
(table.insert args
|
|
||||||
(let [item (select i ...)]
|
|
||||||
(match (values item (type item))
|
|
||||||
(str :string) str
|
|
||||||
?any (fennel.view ?any)))))
|
|
||||||
(logdocument:write (table.concat args) "\n")))
|
|
||||||
{: log}))
|
|
||||||
@ -4,6 +4,7 @@ that may need to be sent to the client.
|
|||||||
|
|
||||||
I have them all here because I have a feeling I am conflating missing fields with null fields,
|
I have them all here because I have a feeling I am conflating missing fields with null fields,
|
||||||
and I want to have one location to look to fix this in the future."
|
and I want to have one location to look to fix this in the future."
|
||||||
|
(local utils (require :fennel-ls.utils))
|
||||||
|
|
||||||
(local error-codes
|
(local error-codes
|
||||||
{;; JSON-RPC errors
|
{;; JSON-RPC errors
|
||||||
@ -43,8 +44,18 @@ and I want to have one location to look to fix this in the future."
|
|||||||
: id
|
: id
|
||||||
:result ?result})
|
:result ?result})
|
||||||
|
|
||||||
|
(λ range [text ?ast]
|
||||||
|
"create a LSP range representing the span of an AST object"
|
||||||
|
(if (= (type ?ast) :table)
|
||||||
|
(match (values (utils.get-ast-info ?ast :bytestart) (utils.get-ast-info ?ast :byteend))
|
||||||
|
(i j)
|
||||||
|
(let [(start-line start-col) (utils.byte->pos text i)
|
||||||
|
(end-line end-col) (utils.byte->pos text (+ j 1))]
|
||||||
|
{:start {:line start-line :character start-col}
|
||||||
|
:end {:line end-line :character end-col}}))))
|
||||||
|
|
||||||
{: create-notification
|
{: create-notification
|
||||||
: create-request
|
: create-request
|
||||||
: create-response
|
: create-response
|
||||||
: create-error}
|
: create-error
|
||||||
|
: range}
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
(local fennel (require :fennel))
|
|
||||||
(local util (require :fennel-ls.util))
|
|
||||||
|
|
||||||
(λ get-ast-info [?ast info]
|
|
||||||
;; find a given key of info from an AST object
|
|
||||||
(or (?. (getmetatable ?ast) info)
|
|
||||||
(. ?ast info)))
|
|
||||||
|
|
||||||
(λ contains? [?ast byte]
|
|
||||||
"check if a byte is in range of the AST object"
|
|
||||||
(and (= (type ?ast) :table)
|
|
||||||
(get-ast-info ?ast :bytestart)
|
|
||||||
(get-ast-info ?ast :byteend)
|
|
||||||
(<= (get-ast-info ?ast :bytestart)
|
|
||||||
byte
|
|
||||||
(+ 1 (get-ast-info ?ast :byteend)))))
|
|
||||||
|
|
||||||
(λ does-not-contain? [?ast byte]
|
|
||||||
"check if a byte is in range of the AST object"
|
|
||||||
(and (= (type ?ast) :table)
|
|
||||||
(get-ast-info ?ast :bytestart)
|
|
||||||
(get-ast-info ?ast :byteend)
|
|
||||||
(not
|
|
||||||
(<= (get-ast-info ?ast :bytestart)
|
|
||||||
byte
|
|
||||||
(+ 1 (get-ast-info ?ast :byteend))))))
|
|
||||||
|
|
||||||
|
|
||||||
(λ past? [?ast byte]
|
|
||||||
"check if a byte is past the range of the AST object"
|
|
||||||
(and (= (type ?ast) :table)
|
|
||||||
(get-ast-info ?ast :bytestart)
|
|
||||||
(< byte (get-ast-info ?ast :bytestart))
|
|
||||||
false))
|
|
||||||
|
|
||||||
(λ range [text ?ast]
|
|
||||||
"create a LSP range representing the span of an AST object"
|
|
||||||
(if (= (type ?ast) :table)
|
|
||||||
(match (values (get-ast-info ?ast :bytestart) (get-ast-info ?ast :byteend))
|
|
||||||
(i j)
|
|
||||||
(let [(start-line start-col) (util.byte->pos text i)
|
|
||||||
(end-line end-col) (util.byte->pos text (+ j 1))]
|
|
||||||
{:start {:line start-line :character start-col}
|
|
||||||
:end {:line end-line :character end-col}}))))
|
|
||||||
|
|
||||||
{: contains?
|
|
||||||
: does-not-contain?
|
|
||||||
: past?
|
|
||||||
: range}
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
"Mod
|
"Searcher
|
||||||
This file has all the logic needed to take the name of a module and find the corresponding URI.
|
This file has all the logic needed to take the name of a module and find the corresponding URI.
|
||||||
I suspect this file is going to be gone after a bit of refactoring."
|
I suspect this file is going to be gone after a bit of refactoring."
|
||||||
|
|
||||||
(local fennel (require :fennel))
|
(local fennel (require :fennel))
|
||||||
(local util (require :fennel-ls.util))
|
(local utils (require :fennel-ls.utils))
|
||||||
|
|
||||||
"works on my machine >:)"
|
"works on my machine >:)"
|
||||||
(local luapath "?.lua;src/?.lua")
|
(local luapath "?.lua;src/?.lua")
|
||||||
@ -36,13 +36,13 @@ I suspect this file is going to be gone after a bit of refactoring."
|
|||||||
(if (is_absolute path)
|
(if (is_absolute path)
|
||||||
(table.insert result path)
|
(table.insert result path)
|
||||||
(each [_ workspace (ipairs (or ?workspaces []))]
|
(each [_ workspace (ipairs (or ?workspaces []))]
|
||||||
(table.insert result (join (util.uri->path workspace) path)))))
|
(table.insert result (join (utils.uri->path workspace) path)))))
|
||||||
(table.concat result ";")))
|
(table.concat result ";")))
|
||||||
|
|
||||||
(λ lookup [{: root-uri} mod]
|
(λ lookup [{: root-uri} mod]
|
||||||
(match (or (fennel.searchModule mod (add-workspaces-to-path luapath [root-uri]))
|
(match (or (fennel.searchModule mod (add-workspaces-to-path luapath [root-uri]))
|
||||||
(fennel.searchModule mod (add-workspaces-to-path fennelpath [root-uri])))
|
(fennel.searchModule mod (add-workspaces-to-path fennelpath [root-uri])))
|
||||||
modname (util.path->uri modname)
|
modname (utils.path->uri modname)
|
||||||
nil nil))
|
nil nil))
|
||||||
|
|
||||||
{: lookup}
|
{: lookup}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
(local util (require :fennel-ls.util))
|
(local utils (require :fennel-ls.utils))
|
||||||
(local mod (require :fennel-ls.mod))
|
(local searcher (require :fennel-ls.searcher))
|
||||||
|
|
||||||
(local {: analyze} (require :fennel-ls.plugin))
|
(local {: analyze} (require :fennel-ls.analyze))
|
||||||
|
|
||||||
(λ init-state [self params]
|
(λ init-state [self params]
|
||||||
(set self.files {})
|
(set self.files {})
|
||||||
@ -9,7 +9,7 @@
|
|||||||
(set self.root-uri params.rootUri))
|
(set self.root-uri params.rootUri))
|
||||||
|
|
||||||
(λ read-file [uri]
|
(λ read-file [uri]
|
||||||
(with-open [fd (io.open (util.uri->path uri))]
|
(with-open [fd (io.open (utils.uri->path uri))]
|
||||||
{:uri uri
|
{:uri uri
|
||||||
:text (fd:read :*a)}))
|
:text (fd:read :*a)}))
|
||||||
|
|
||||||
@ -26,7 +26,7 @@
|
|||||||
;; if the cached uri isn't found, clear the cache and try again
|
;; if the cached uri isn't found, clear the cache and try again
|
||||||
(do (tset self.modules module nil)
|
(do (tset self.modules module nil)
|
||||||
(get-by-module self module)))
|
(get-by-module self module)))
|
||||||
nil (let [uri (mod.lookup self module)]
|
nil (let [uri (searcher.lookup self module)]
|
||||||
(tset self.modules module uri)
|
(tset self.modules module uri)
|
||||||
(get-by-uri self uri))))
|
(get-by-uri self uri))))
|
||||||
|
|
||||||
|
|||||||
@ -70,6 +70,11 @@ These functions are all pure functions, which makes me happy."
|
|||||||
{: text}
|
{: text}
|
||||||
text)))
|
text)))
|
||||||
|
|
||||||
|
(λ get-ast-info [?ast info]
|
||||||
|
;; find a given key of info from an AST object
|
||||||
|
(or (?. (getmetatable ?ast) info)
|
||||||
|
(. ?ast info)))
|
||||||
|
|
||||||
(fn multi-sym-split [sym ?offset]
|
(fn multi-sym-split [sym ?offset]
|
||||||
(local sym (tostring sym))
|
(local sym (tostring sym))
|
||||||
(local offset (or ?offset (length sym)))
|
(local offset (or ?offset (length sym)))
|
||||||
@ -84,4 +89,5 @@ These functions are all pure functions, which makes me happy."
|
|||||||
: pos->byte
|
: pos->byte
|
||||||
: byte->pos
|
: byte->pos
|
||||||
: apply-changes
|
: apply-changes
|
||||||
: multi-sym-split}
|
: multi-sym-split
|
||||||
|
: get-ast-info}
|
||||||
@ -5,14 +5,14 @@
|
|||||||
(local {: ROOT-URI
|
(local {: ROOT-URI
|
||||||
: setup-server} (require :test.util))
|
: setup-server} (require :test.util))
|
||||||
|
|
||||||
(local dispatch (require :fennel-ls.dispatch))
|
(local core (require :fennel-ls.core))
|
||||||
(local message (require :fennel-ls.message))
|
(local message (require :fennel-ls.message))
|
||||||
|
|
||||||
(describe "jump to definition"
|
(describe "jump to definition"
|
||||||
|
|
||||||
(fn check [request-file line char response-file start-line start-col end-line end-col]
|
(fn check [request-file line char response-file start-line start-col end-line end-col]
|
||||||
(local state (doto [] setup-server))
|
(local state (doto [] setup-server))
|
||||||
(let [message (dispatch.handle* state
|
(let [message (core.handle* state
|
||||||
(message.create-request 2 "textDocument/definition"
|
(message.create-request 2 "textDocument/definition"
|
||||||
{:position {:character char :line line}
|
{:position {:character char :line line}
|
||||||
:textDocument {:uri (.. ROOT-URI "/" request-file)}}))
|
:textDocument {:uri (.. ROOT-URI "/" request-file)}}))
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
(local is (require :luassert))
|
(local is (require :luassert))
|
||||||
|
|
||||||
(local {: ROOT-PATH : ROOT-URI} (require :test.util))
|
(local {: ROOT-PATH : ROOT-URI} (require :test.util))
|
||||||
(local dispatch (require :fennel-ls.dispatch))
|
(local core (require :fennel-ls.core))
|
||||||
|
|
||||||
(local server-initialize-message
|
(local server-initialize-message
|
||||||
{:id 1
|
{:id 1
|
||||||
@ -22,7 +22,7 @@
|
|||||||
(describe "language server"
|
(describe "language server"
|
||||||
(it "responds to initialize"
|
(it "responds to initialize"
|
||||||
(is-matching
|
(is-matching
|
||||||
(dispatch.handle* [] server-initialize-message)
|
(core.handle* [] server-initialize-message)
|
||||||
[{:jsonrpc "2.0" :id 1
|
[{:jsonrpc "2.0" :id 1
|
||||||
:result {:capabilities {}
|
:result {:capabilities {}
|
||||||
:serverInfo {:name "fennel-ls" : version}}}])))
|
:serverInfo {:name "fennel-ls" : version}}}])))
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
(local is (require :luassert))
|
(local is (require :luassert))
|
||||||
|
|
||||||
(local fennel (require :fennel))
|
(local fennel (require :fennel))
|
||||||
(local {: multi-sym-split} (require :fennel-ls.util))
|
(local {: multi-sym-split} (require :fennel-ls.utils))
|
||||||
|
|
||||||
(describe "multi-sym-split"
|
(describe "multi-sym-split"
|
||||||
(it "should be 1 on regular syms"
|
(it "should be 1 on regular syms"
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
(local is (require :luassert))
|
(local is (require :luassert))
|
||||||
|
|
||||||
(local fennel (require :fennel))
|
(local fennel (require :fennel))
|
||||||
(local util (require :fennel-ls.util))
|
(local utils (require :fennel-ls.utils))
|
||||||
|
|
||||||
(describe "util"
|
(describe "utils"
|
||||||
|
|
||||||
;; fixme:
|
;; fixme:
|
||||||
;; test for errors on out of bounds
|
;; test for errors on out of bounds
|
||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
(it "updates the start of a line"
|
(it "updates the start of a line"
|
||||||
(is.equal
|
(is.equal
|
||||||
(util.apply-changes
|
(utils.apply-changes
|
||||||
"replace beginning"
|
"replace beginning"
|
||||||
[{:range (range 0 0 0 7)
|
[{:range (range 0 0 0 7)
|
||||||
:text "the"}])
|
:text "the"}])
|
||||||
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
(it "updates the end of a line"
|
(it "updates the end of a line"
|
||||||
(is.equal
|
(is.equal
|
||||||
(util.apply-changes
|
(utils.apply-changes
|
||||||
"first line\nsecond line\nreplace end"
|
"first line\nsecond line\nreplace end"
|
||||||
[{:range (range 2 7 2 11)
|
[{:range (range 2 7 2 11)
|
||||||
:text "ment"}])
|
:text "ment"}])
|
||||||
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
(it "replaces a line"
|
(it "replaces a line"
|
||||||
(is.equal
|
(is.equal
|
||||||
(util.apply-changes
|
(utils.apply-changes
|
||||||
"replace all"
|
"replace all"
|
||||||
[{:range (range 0 0 0 11)
|
[{:range (range 0 0 0 11)
|
||||||
:text "new string"}])
|
:text "new string"}])
|
||||||
@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
(it "can handle substituting things"
|
(it "can handle substituting things"
|
||||||
(is.equal
|
(is.equal
|
||||||
(util.apply-changes
|
(utils.apply-changes
|
||||||
"replace beginning"
|
"replace beginning"
|
||||||
[{:range {:start {:line 0 :character 0}
|
[{:range {:start {:line 0 :character 0}
|
||||||
:end {:line 0 :character 7}}
|
:end {:line 0 :character 7}}
|
||||||
@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
(it "can handle replacing everything"
|
(it "can handle replacing everything"
|
||||||
(is.equal
|
(is.equal
|
||||||
(util.apply-changes
|
(utils.apply-changes
|
||||||
"this is the\nold file"
|
"this is the\nold file"
|
||||||
[{:text "And this is the\nnew file"}])
|
[{:text "And this is the\nnew file"}])
|
||||||
"And this is the\nnew file"))))
|
"And this is the\nnew file"))))
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
(local dispatch (require :fennel-ls.dispatch))
|
(local core (require :fennel-ls.core))
|
||||||
|
|
||||||
(local ROOT-PATH
|
(local ROOT-PATH
|
||||||
(-> (io.popen "pwd")
|
(-> (io.popen "pwd")
|
||||||
@ -24,6 +24,6 @@
|
|||||||
:uri ROOT-URI}]}})
|
:uri ROOT-URI}]}})
|
||||||
|
|
||||||
(fn setup-server [state]
|
(fn setup-server [state]
|
||||||
(dispatch.handle* state initialization-message))
|
(core.handle* state initialization-message))
|
||||||
|
|
||||||
{: ROOT-URI : setup-server}
|
{: ROOT-URI : setup-server}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user