幫助lsp-mode用上Emacs 27的json-parse-string

Debian系apt install libjansson-dev

Emacs 27預設啓用--with-json,如果configure時找到libjansson.so就會有json-serialize json-parse-string等native serialization/deserialization函式。

git clone https://github.com/emacs-mirror/emacs # git://git.sv.gnu.org/emacs.git
cd emacs
./configure --with-modules --with-xml2
make -j
% readelf -d src/emacs | grep jansson
 0x0000000000000001 (NEEDED)             Shared library: [libjansson.so.4]

這個有望改善lsp-mode的性能,詳見 https://github.com/emacs-lsp/lsp-mode/issues/210

改寫lsp-mode/lsp-io.el用上json-parse-string不麻煩:

(eval-when-compile
  (if (fboundp 'json-parse-string)
      (define-inline lsp--read-json (str)
        (inline-quote
         (json-parse-string ,str :false-object :json-false :null-object nil)))
    (define-inline lsp--read-json (str)
        (inline-quote
         (let* ((json-array-type 'list)      ;;;;;;;;; 'vector is the default
                (json-object-type 'hash-table)
                (json-false nil))
           (json-read-from-string ,str))))))

我的elisp不好,大家應該有更好的辦法。

但難點可能是json-parse-string把JSON array表示爲vector,而現在用的lsp--read-json表示爲list,一些地方用dolist來處理deserialize後的結果,會報錯。

大家來幫忙把這些地方改成list/vector agnostic的,或者只用vector?

5 个赞
;;; How to coerce to list
(append [1 good "a" 4 5 t] nil)
;; => (1 good "a" 4 5 t)

感謝。

lsp-mode 的改動 https://github.com/emacs-lsp/lsp-mode/pull/418/files

希望沒弄錯。emacs-ccls我改好了。lsp-ui 感覺會困難…… 修好了

可能這樣就基本好了?歡迎測試~

json-parse-string 不能像 json-read-from-string 那样支持 let-binding json-array-type 么?

刚刚试了下,json-parse-string 不支持 json-array-type,但能指定 object/null/false 的类型,或许可以提个 Feature Request。

這裏幾個JSON數據結構表示爲elisp有幾種方法,感覺需要調研下。

比如JSON Object在eglot jsonrpc似乎用plist表示,lsp-mode是hash-table

如果用plist的化,nil兼職用作null可能就不好,因爲值域衝突。

JSON Object 转换的类型可以定制,比如用 plist 表示:

(let ((json-object-type 'plist))
  (json-read-from-string "{\"name\": \"Emacs\"}"))
;; => (:name "Emacs")

(json-parse-string "{\"name\": \"Emacs\"}"
                   :object-type 'plist)
;; => (:name "Emacs")

但是 json-parse-string 缺少一个类似 json-array-type 的选项,正如我的上一个回复所说。

我并不清楚 lsp-mode 和 eglot 那边什么状况。

給lsp-mode PR了,Add lsp--json-array-use-vector. If set, use default json-array-type vector and use json-parse-string if exists by MaskRay · Pull Request #425 · emacs-lsp/lsp-mode · GitHub

但這種eval-when-compile寫法不對,該怎麼辦呢?

我并不认为这种写法有问题。what’s your concern?

lsp-mode的travis報錯……

换成 eval-and-compile。估计 Travis build 没有 byte compile 还是怎么着的

@netjune @yicao 你們可以類似https://github.com/MaskRay/emacs-ccls/commit/378a5fefcc198e7e28a5b48499b3d17b4ef26a11改一下emacs-cquery

否則json-array-type 還原成vector cquery semantic highlighting、codeAction等就壞了

@LdBeth 感謝,eval-and-compile => " All checks have passed"

请问emacs27.1还是27.0 以上啊。我只找到了27.0

刚刚提交了个 Bug: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=32793

1 个赞

我覺得用vector表示JSON array是大勢所趨……這個有沒有影響不大。

主要倒不是哪个好,新的明明就比 json.el 少一个功能。