Test changes, and fennel-ls now properly negotiates for utf-8 encoding
Unfortunately, fennel-ls still doesn't respect utf-16 rules if the negotiations fail.
This commit is contained in:
parent
95245726e1
commit
cd37e05e54
@ -64,6 +64,7 @@ Every time the client sends a message, it gets handled by a function in the corr
|
||||
(λ requests.initialize [self send params]
|
||||
(state.init-state self params)
|
||||
{:capabilities capabilities
|
||||
:positionEncoding self.position-encoding
|
||||
:serverInfo {:name "fennel-ls" :version "0.0.0"}})
|
||||
|
||||
(λ requests.textDocument/definition [self send {: position :textDocument {: uri}}]
|
||||
|
||||
@ -100,10 +100,27 @@ in the \"self\" object."
|
||||
(λ make-configuration [?c]
|
||||
(make-configuration-from-template default-configuration ?c))
|
||||
|
||||
(λ choose-position-encoding [init-params]
|
||||
"fennel-ls natively uses utf-8, so ideally we will choose positionEncoding=utf-8.
|
||||
However, fennel-ls can fall back to positionEncoding=utf-16 (with a performance hit)."
|
||||
(let [?position-encodings (?. init-params :capabilities :general :positionEncodings)
|
||||
utf8?
|
||||
(if (= (type ?position-encodings) :table)
|
||||
(accumulate [utf-8? false
|
||||
_ encoding (ipairs ?position-encodings)]
|
||||
(or (= encoding :utf-8)
|
||||
(= encoding :utf8)))
|
||||
false)]
|
||||
(if utf8?
|
||||
:utf-8
|
||||
:utf-16)))
|
||||
|
||||
|
||||
(λ init-state [self params]
|
||||
(set self.files {})
|
||||
(set self.modules {})
|
||||
(set self.root-uri params.rootUri)
|
||||
(set self.position-encoding (choose-position-encoding params))
|
||||
(set self.configuration (make-configuration)))
|
||||
|
||||
(λ write-configuration [self ?configuration]
|
||||
|
||||
61
test/capabilities-test.fnl
Normal file
61
test/capabilities-test.fnl
Normal file
@ -0,0 +1,61 @@
|
||||
(import-macros {: is-matching : is-casing : describe : it : before-each} :test)
|
||||
(local {: view} (require :fennel))
|
||||
|
||||
(local is (require :test.is))
|
||||
(local {: ROOT-URI
|
||||
: ROOT-PATH
|
||||
: create-client} (require :test.mock-client))
|
||||
|
||||
(fn default [tbl field value]
|
||||
(when (= nil (. tbl field))
|
||||
(tset tbl field value)))
|
||||
|
||||
(fn client-initialization [params]
|
||||
(default params :clientInfo {:name "xerool's mock client" :version "9000"}) ;; not necessary, but why not have some fun?
|
||||
(default params :rootPath ROOT-PATH) ;; deprecated, TODO delete
|
||||
(default params :rootUri ROOT-URI) ;; deprecated, TODO delete
|
||||
{default params :workspaceFolders [{:name "my cool space" :uri ROOT-URI}]}
|
||||
(default params :capabilities {})
|
||||
(default params :trace "off") ;; | "messages" | "verbose"
|
||||
;; :initializationOptions {}) ;; LspAny
|
||||
;; :processId nil
|
||||
;; :locale "en" ;; I don't support languages/translations as of now
|
||||
params)
|
||||
|
||||
(describe "capabilities negotiations"
|
||||
|
||||
; (it "chooses utf-16"
|
||||
; (let [(self [response])
|
||||
; (create-client
|
||||
; {:params
|
||||
; (client-initialization
|
||||
; {:capabilities
|
||||
; {:general
|
||||
; {:positionEncodings
|
||||
; [:utf-16]}}})})]
|
||||
; (is.equal :utf-16 (. response :result :positionEncoding))
|
||||
; (self:open-file! "foo.fnl" "(let [𐐀𐐀 100] 𐐀𐐀)")
|
||||
; (let [[response] (self:definition "foo.fnl" 0 16)]
|
||||
; (is.equal 6 response.result.range.start.character)
|
||||
; (is.equal 10 response.result.range.end.character))))
|
||||
|
||||
(it "chooses utf-8 if at all possible"
|
||||
(let [(self [response])
|
||||
(create-client
|
||||
{:params
|
||||
(client-initialization
|
||||
{:capabilities
|
||||
{:general
|
||||
{:positionEncodings
|
||||
[:utf-16 :utf-8]}}})})]
|
||||
(is.equal :utf-8 (. response :result :positionEncoding))
|
||||
(self:open-file! "foo.fnl" "(let [𐐀𐐀 100] 𐐀𐐀)")
|
||||
(let [[response] (self:definition "foo.fnl" 0 20)]
|
||||
(is.equal 6 response.result.range.start.character)
|
||||
(is.equal 14 response.result.range.end.character)))))
|
||||
|
||||
(it "falls back to utf-16"
|
||||
(let [(self [response]) (create-client {:params (client-initialization {})})]
|
||||
(is.equal :utf-16 (. response :result :positionEncoding))))
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
(require :test.capabilities-test)
|
||||
(require :test.completion-test)
|
||||
(require :test.diagnostic-test)
|
||||
(require :test.goto-definition-test)
|
||||
|
||||
@ -64,7 +64,7 @@ function lust.it(name, fn)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if has(arg, "--quit-at-first-test") then os.exit(1) end
|
||||
end
|
||||
|
||||
|
||||
@ -6,14 +6,11 @@
|
||||
(: :read :*a)
|
||||
(: :sub 1 -2) ;; take off newline
|
||||
(.. "/test/test-project")))
|
||||
|
||||
(local ROOT-URI
|
||||
(.. "file://" ROOT-PATH))
|
||||
|
||||
(local initialization-message
|
||||
{:id 1
|
||||
:jsonrpc "2.0"
|
||||
:method "initialize"
|
||||
:params
|
||||
(local default-params
|
||||
{:capabilities {}
|
||||
:clientInfo {:name "Neovim" :version "0.7.2"}
|
||||
:initializationOptions {}
|
||||
@ -22,17 +19,23 @@
|
||||
:rootUri ROOT-URI
|
||||
:trace "off"
|
||||
:workspaceFolders [{:name ROOT-PATH
|
||||
:uri ROOT-URI}]}})
|
||||
:uri ROOT-URI}]})
|
||||
|
||||
(local mt {})
|
||||
(fn create-client [?config]
|
||||
(let [self (doto {:server [] :prev-id 1} (setmetatable mt))]
|
||||
(dispatch.handle* self.server initialization-message)
|
||||
(if ?config
|
||||
(dispatch.handle* self.server {:jsonrpc "2.0"
|
||||
:method :workspace/didChangeConfiguration
|
||||
:params {:settings ?config}}))
|
||||
self))
|
||||
(fn create-client [?opts]
|
||||
(let [self (doto {:server [] :prev-id 1} (setmetatable mt))
|
||||
initialize {:id 1
|
||||
:jsonrpc "2.0"
|
||||
:method "initialize"
|
||||
:params (or (?. ?opts :params) default-params)}
|
||||
result (dispatch.handle* self.server initialize)]
|
||||
(case (?. ?opts :settings)
|
||||
settings
|
||||
(dispatch.handle* self.server
|
||||
{:jsonrpc "2.0"
|
||||
:method :workspace/didChangeConfiguration
|
||||
:params {: settings}}))
|
||||
(values self result)))
|
||||
|
||||
(fn next-id! [self]
|
||||
(set self.prev-id (+ self.prev-id 1))
|
||||
@ -80,4 +83,5 @@
|
||||
: references})
|
||||
|
||||
{: create-client
|
||||
: ROOT-URI}
|
||||
: ROOT-URI
|
||||
: ROOT-PATH}
|
||||
|
||||
@ -26,6 +26,22 @@
|
||||
(check-references "(let [x 10] x)" 0 6
|
||||
[{:uri filename :range (message.pos->range 0 12 0 13)}]))
|
||||
|
||||
(let [x 10] x x x)
|
||||
(it "finds multiple reference from let"
|
||||
(check-references "(let [x 10] x x x)" 0 6
|
||||
[{:uri filename :range (message.pos->range 0 12 0 13)}
|
||||
{:uri filename :range (message.pos->range 0 14 0 15)}
|
||||
{:uri filename :range (message.pos->range 0 16 0 17)}]))
|
||||
|
||||
(it "finds a reference from fn"
|
||||
(check-references "(fn x []) x" 0 10
|
||||
[{:uri filename :range (message.pos->range 0 10 0 11)}]))
|
||||
|
||||
; (it "finds a reference from fn"
|
||||
; (check-references "(fn x []) x" 0 4
|
||||
; [{:uri filename :range (message.pos->range 0 10 0 11)}]))
|
||||
|
||||
|
||||
(it "doesn't crash here"
|
||||
(check-references "(let [x nil] x.y)" 0 14
|
||||
nil)))
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
(import-macros {: is-matching : describe : it : before-each} :test)
|
||||
(local is (require :test.is))
|
||||
(local {: view} (require :fennel))
|
||||
|
||||
(local {: ROOT-URI
|
||||
: create-client} (require :test.mock-client))
|
||||
|
||||
(describe "settings"
|
||||
(it "can set the path"
|
||||
(let [client (doto (create-client {:fennel-ls {:fennel-path "./?/?.fnl"}})
|
||||
(let [client (doto (create-client {:settings {:fennel-ls {:fennel-path "./?/?.fnl"}}})
|
||||
(: :open-file! (.. ROOT-URI :/test.fnl) "(local {: this-is-in-modname} (require :modname))"))
|
||||
result (client:definition (.. ROOT-URI :/test.fnl) 0 12)]
|
||||
(is-matching
|
||||
@ -15,9 +16,9 @@
|
||||
"error message")))
|
||||
|
||||
(it "can set the macro path"
|
||||
(let [client (create-client {:fennel-ls {:macro-path "./?/?.fnl"}})
|
||||
(let [client (create-client {:settings {:fennel-ls {:macro-path "./?/?.fnl"}}})
|
||||
responses (client:open-file! (.. ROOT-URI :/test.fnl) "(import-macros {: this-is-in-modname} :modname)")]
|
||||
(assert (not (. responses 1 :params 1)) "if the import-macros fails it generates a diagnostic (for now at least)")))
|
||||
(assert (not (. responses 1 :params :diagnostics 1)) "if the import-macros fails it generates a diagnostic (for now at least)")))
|
||||
|
||||
;; (it "recompiles modules if the macro files are modified)"
|
||||
|
||||
@ -38,7 +39,7 @@
|
||||
|
||||
;; I suspect this test will fail when I put warnings for module return type
|
||||
(it "can disable some lints"
|
||||
(let [client (create-client {:fennel-ls {:checks {:unused-definition false}}})
|
||||
(let [client (create-client {:settings {:fennel-ls {:checks {:unused-definition false}}}})
|
||||
responses (client:open-file! (.. ROOT-URI :/test.fnl) "(local x 10)")]
|
||||
(is-matching responses
|
||||
[{:method :textDocument/publishDiagnostics
|
||||
|
||||
Loading…
Reference in New Issue
Block a user