记录一次修复 lsp-mode 和 LanguageServer.jl 问题的过程

记录一次修复 lsp-mode 和 LanguageServer.jl 问题的过程

想要试试在 emacs 上写 julia,结果一上来就遇到了问题。
查看了一下 customize
env

一开始以为是这里的问题。修改成 1.5 之后重新启动。结果还是不行。

查看了stderr的报错信息:

ERROR: MethodError: no method matching LanguageServer.FoldingRangeCapabilities(::Nothing)
Closest candidates are:
  LanguageServer.FoldingRangeCapabilities(::Any, !Matched::Any, !Matched::Any) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/protocol/initialize.jl:132
  LanguageServer.FoldingRangeCapabilities(!Matched::Union{Missing, Bool}, !Matched::Union{Missing, Int64}, !Matched::Union{Missing, Bool}) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/protocol/initialize.jl:132
  LanguageServer.FoldingRangeCapabilities(!Matched::Dict) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/protocol/protocol.jl:37
Stacktrace:
 [1] LanguageServer.TextDocumentClientCapabilities(::Dict{String,Any}) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/protocol/protocol.jl:37
 [2] LanguageServer.ClientCapabilities(::Dict{String,Any}) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/protocol/protocol.jl:37
 [3] LanguageServer.InitializeParams(::Dict{String,Any}) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/protocol/initialize.jl:183
 [4] parse_params(::Type{Val{:initialize}}, ::Dict{String,Any}) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/requests/init.jl:125
 [5] parse(::Type{LanguageServer.JSONRPC.Request}, ::Dict{String,Any}) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/jsonrpc.jl:46
 [6] run(::LanguageServerInstance) at /Users/tamasgal/.julia/packages/LanguageServer/35vuR/src/languageserverinstance.jl:231
 [7] top-level scope at none:1

Process julia-ls stderr finished

PS:懒得去还原自己的错误了,这里是issue里那个人报错信息。

MethodError: no method matching LanguageServer.FoldingRangeCapabilities这个issue里找到了错误的解决方案

在emacs里进行如下设置:

(setq lsp-enable-folding t)
(setq lsp-folding-range-limit 100)

总之还是lsp-mode的默认设置存在问题。

满怀希望重起emacs

然后…

ERROR: MethodError: no method matching Union{Int64, String}(::String)ERROR: 
Stacktrace:TypeError: in new, expected Array{Symbol,1}, got Nothing

Stacktrace: [1] LanguageServer.InitializeParams
( [1] deserialize::(Dict{String,Any}):: at Serialization/home/gkraemer/progs/julia/lsp-julia/languageserver/LanguageServer/src/protocol/initialize.jl:111.Serializer{IOStream}, 
 [2] parse_params::(DataType):: at Type/home/gkraemer/progs/julia/julia-1.4/usr/share/julia/stdlib/v1.4/Serialization/src/Serialization.jl:1315{Val{:initialize}}, 
 [2] handle_deserialize::(Dict{String,Any}):: at Serialization/home/gkraemer/progs/julia/lsp-julia/languageserver/LanguageServer/src/requests/init.jl:123.Serializer{IOStream}, 
 [3] parse::(Int32):: at Type/home/gkraemer/progs/julia/julia-1.4/usr/share/julia/stdlib/v1.4/Serialization/src/Serialization.jl:799{LanguageServer.JSONRPC.Request}, 
 [3] deserialize::(Dict{String,Any}):: at Serialization/home/gkraemer/progs/julia/lsp-julia/languageserver/LanguageServer/src/jsonrpc.jl:46.Serializer{IOStream}, 
 [4] run::(DataType):: at LanguageServerInstance/home/gkraemer/progs/julia/julia-1.4/usr/share/julia/stdlib/v1.4/Serialization/src/Serialization.jl:1309)
 at  [4] /home/gkraemer/progs/julia/lsp-julia/languageserver/LanguageServer/src/languageserverinstance.jl:236handle_deserialize
( [5] top-level scope:: at Serializationnone:1.
Serializer
Process julia-ls stderr finished

看上去跟之前的好像一样?也是方法的参数类型不匹配?

同样是翻找了issue,似乎情况不大一样,这回问题出在LanguageServer.jl

似乎是,在LanguageServer.jl里有一句ProgressToken = Union{Int, String},而Initial的时候会去构造包含ProgressToken的一个结构体,但是ProgressToken却没有ProgressToken()这个构造方法(因为它只是类型别名)

我也是初学julia不是很明白这是怎么回事,希望能有大佬帮我解释一下。

然后一个pr把所有的ProgressToken都替换成了Union{Int, String},这样就不会调用ProgressToken()这个不存在的构造方法了。

但是我应该把julia的包都更新到最新了才对,怎么还存在这个问题?

先是捣鼓了一下emacs里的这个设置。我用的是doom,如果你也遇到同样的问题最好检查一下,这个设置可能是.emacs.d/.local/straight/build/lsp-julia/languageserver/,这个版本比较底,也许是跟前面的1.0是配套的…

lsp-julia-package-dir

设置成nil后就会使用juli安装的版本。但是问题依然存在。

冷静下来以后,我进入了.julia/package/LanguageServer目录下翻找源码。搞了半天,这个pr还在dev分支里,stable还没有改。洗达卡奶依,只好手动复制dev的文件夹覆盖。

重新启动emacs…
image-20201020154800497

Oh!!!

2 个赞

Union 就是说这个东西可能是这几种类型之一。具体来说这里的 ProgressToken 代表可能是整数或字符串,使用默认的构造器,那它给你返回哪种类型呢?所以无法直接构造。

Union 中类型的实例都是这个 Union 的实例。这里具体表现为,ProgressToken 可以接受一个整数或字符串。

julia> 1 |> typeof
Int64

julia> "a" |> typeof
String

julia> ProgressToken = Union{Int, String}
Union{Int64, String}

julia> 1 isa ProgressToken
true

julia> "a" isa ProgressToken
true
1 个赞

学到了!感谢赐教!

关于 lsp-julia 的配置代码能贴一份吗,我现在想用这个插件,就是开不起来