3333; ;
3434; ;; Code:
3535(require 'lsp-mode )
36- (require 'json )
36+ (require 'lsp-javascript )
37+ (require 'dash )
3738
3839(defgroup lsp-volar nil
3940 " Lsp support for vue3."
4041 :group 'lsp-mode
4142 :link '(url-link " https://github.com/vuejs/language-tools" )
4243 :package-version '(lsp-mode . " 9.0.0" ))
4344
44- (defcustom lsp-volar-take-over-mode nil
45- " Enable Take Over Mode."
46- :type 'boolean
45+ (defcustom lsp-volar-typescript-server-id 'ts-ls
46+ " The server id of the typescript language server to use."
4747 :group 'lsp-volar
48- :package-version '(lsp-mode . " 9.0.0" ))
48+ :package-version '(lsp-mode . " 9.0.1" )
49+ :type 'symbol )
4950
50- (defcustom lsp-volar-hybrid-mode t
51- " Enable Hybrid Mode."
52- :type 'boolean
53- :group 'lsp-volar
54- :package-version '(lsp-mode . " 9.0.1" ))
51+ (defcustom lsp-volar-support-vue2 nil
52+ " Whether to ping Volar's version to ~3.0 to support vue2.
5553
56- (defcustom lsp-volar-as-add-on nil
57- " Run volar LSP server alongside other LSP server(s)"
58- :type 'boolean
54+ Volar is dropping Vue 2 and vue-class-component Support in v3.1.
55+ Reference: https://github.com/vuejs/language-tools/discussions/5455"
5956 :group 'lsp-volar
60- :package-version '(lsp-mode . " 9.0.1" ))
61-
62- (defcustom lsp-volar-activate-file " .volarrc"
63- " A file with a custom name placed in WORKSPACE-ROOT is used to force enable
64- volar when there is no package.json in the WORKSPACE-ROOT."
65- :type 'string
66- :group 'lsp-volar
67- :package-version '(lsp-mode . " 9.0.0" ))
68-
69- (defconst lsp-volar--is-windows (memq system-type '(cygwin windows-nt ms-dos)))
70- (defun lsp-volar-get-typescript-tsdk-path ()
71- " Get tsserver lib*.d.ts directory path."
72- (if-let* ((package-path (lsp-package-path 'typescript ))
73- (system-tsdk-path (f-join (file-truename package-path)
74- (if lsp-volar--is-windows
75- " ../node_modules/typescript/lib"
76- " ../../lib" )))
77- ((file-exists-p system-tsdk-path)))
78- system-tsdk-path
79- (prog1 " "
80- (lsp--error " [lsp-volar] Typescript is not detected correctly. Please ensure the npm package typescript is installed in your project or system (npm install -g typescript), otherwise open an issue" ))))
81-
82- (lsp-dependency 'typescript
83- '(:system " tsserver" )
84- '(:npm :package " typescript"
85- :path " tsserver" ))
86-
87- (lsp-dependency 'volar-language-server
88- '(:system " vue-language-server" )
89- '(:npm :package " @vue/language-server" :path " vue-language-server" ))
90-
91- (lsp-register-custom-settings
92- '((" typescript.tsdk"
93- (lambda ()
94- (if-let* ((project-root (lsp-workspace-root))
95- (tsdk-path (f-join project-root " node_modules/typescript/lib" ))
96- ((file-exists-p tsdk-path)))
97- tsdk-path
98- (lsp-volar-get-typescript-tsdk-path)))
99- t )))
100-
101- (lsp-register-custom-settings
102- '((" vue.hybridMode" lsp-volar-hybrid-mode t )))
103-
104- (defun lsp-volar--vue-project-p (workspace-root )
105- " Check if the `Vue' package is present in the package.json file
106- in the WORKSPACE-ROOT."
107- (if-let* ((package-json (f-join workspace-root " package.json" ))
108- (exist (f-file-p package-json))
109- (config (json-read-file package-json))
110- (dependencies (alist-get 'dependencies config)))
111- (alist-get 'vue (append dependencies (alist-get 'devDependencies config)))
112- nil ))
57+ :package-version '(lsp-mode . " 9.0.1" )
58+ :type 'boolean )
11359
11460(defun lsp-volar--activate-p (filename &optional _ )
11561 " Check if the volar-language-server should be enabled base on FILENAME."
116- (if lsp-volar-take-over-mode
117- (or (or
118- (and (lsp-workspace-root) (lsp-volar--vue-project-p (lsp-workspace-root)))
119- (and (lsp-workspace-root) lsp-volar-activate-file (f-file-p (f-join (lsp-workspace-root) lsp-volar-activate-file))))
120- (or (or (string-match-p " \\ .mjs\\ |\\ .[jt]sx?\\ '" filename)
121- (and (derived-mode-p 'js-mode 'typescript-mode 'typescript-ts-mode )
122- (not (derived-mode-p 'json-mode ))))
123- (string= (file-name-extension filename) " vue" )))
124- (string= (file-name-extension filename) " vue" )))
62+ (and filename (string-suffix-p " .vue" filename)))
63+
64+ (lsp-dependency 'volar-language-server
65+ '(:npm :package " @vue/language-server" :path " vue-language-server"
66+ :version (lambda () (when lsp-volar-support-vue2 " ~3.0" )))
67+ '(:system " vue-language-server" ))
68+
69+ ; ; Set lsp-clients-typescript-plugins
70+ (condition-case nil
71+ (when-let* ((vue-language-server-path (lsp-package-path 'volar-language-server )))
72+ (let ((vue-plugin (list :name " @vue/typescript-plugin"
73+ :location (f-join vue-language-server-path " ../.." " lib/node_modules/@vue/language-server/" )
74+ :languages (vector " vue" )
75+ :configNamespace " typescript"
76+ :enableForWorkspaceTypeScriptVersions t )))
77+ (setq lsp-clients-typescript-plugins
78+ (vconcat lsp-clients-typescript-plugins (vector vue-plugin)))))
79+ (error nil ))
80+
81+ (defun lsp-volar--send-notify (workspace method params )
82+ " Send notification to WORKSPACE with METHOD PARAMS."
83+ (with-lsp-workspace workspace
84+ (let ((body (lsp--make-notification method params)))
85+ (lsp--send-no-wait body
86+ (lsp--workspace-proc lsp--cur-workspace)))))
87+
88+ (defun lsp-volar--tsserver-request-handler (volar-workspace params )
89+ " Handles `tsserver/request` notification from VOLAR-WORKSPACE.
90+ And forwarding PARAMS to the typescript LSP server.
91+
92+ Reference:
93+ - https://github.com/vuejs/language-tools/discussions/5456
94+ - https://github.com/vuejs/language-tools/wiki/Neovim#configuration"
95+ (if-let* ((ts-ls-workspace (lsp-find-workspace lsp-volar-typescript-server-id nil )))
96+ (with-lsp-workspace ts-ls-workspace
97+ (-let [[[id command payload]] params]
98+ (lsp-request-async
99+ " workspace/executeCommand"
100+ (list :command " typescript.tsserverRequest"
101+ :arguments (vector command payload))
102+ ; ; response callback
103+ (lambda (response )
104+ (let ((body (lsp-get response :body )))
105+ (lsp-volar--send-notify volar-workspace " tsserver/response" (vector (vector id body)))))
106+ ; ; error callback
107+ :error-handler (lambda (error-response )
108+ (lsp--warn " tsserver/request async error: %S" error-response)))))
109+ (lsp--error " [lsp-volar] Could not found `%s` lsp client, lsp-volar would not work without it" lsp-volar-typescript-server-id)))
125110
126111(lsp-register-client
127112 (make-lsp-client
@@ -131,13 +116,10 @@ in the WORKSPACE-ROOT."
131116 :activation-fn 'lsp-volar--activate-p
132117 :priority 0
133118 :multi-root nil
134- :add-on? lsp-volar-as-add-on
119+ :add-on? t ; ; work with typescript server
135120 :server-id 'vue-semantic-server
136- :initialization-options (lambda () (ht-merge (lsp-configuration-section " typescript" )
137- (lsp-configuration-section " vue" )
138- (ht (" serverMode" 0 )
139- (" diagnosticModel" 1 )
140- (" textDocumentSync" 2 ))))
121+ :initialization-options (lambda () (ht-merge (lsp-configuration-section " vue" )))
122+ :notification-handlers (ht (" tsserver/request" #'lsp-volar--tsserver-request-handler ))
141123 :initialized-fn (lambda (workspace )
142124 (with-lsp-workspace workspace
143125 (lsp--server-register-capability
@@ -146,12 +128,9 @@ in the WORKSPACE-ROOT."
146128 :method " workspace/didChangeWatchedFiles"
147129 :register-options? (lsp-make-did-change-watched-files-registration-options
148130 :watchers
149- `[,(lsp-make-file-system-watcher :glob-pattern " **/*.js" )
150- ,(lsp-make-file-system-watcher :glob-pattern " **/*.ts" )
151- ,(lsp-make-file-system-watcher :glob-pattern " **/*.vue" )
152- ,(lsp-make-file-system-watcher :glob-pattern " **/*.jsx" )
153- ,(lsp-make-file-system-watcher :glob-pattern " **/*.tsx" )
154- ,(lsp-make-file-system-watcher :glob-pattern " **/*.json" )])))))
131+ `[
132+ ,(lsp-make-file-system-watcher :glob-pattern " **/*.vue" )
133+ ])))))
155134 :download-server-fn (lambda (_client callback error-callback _update? )
156135 (lsp-package-ensure 'volar-language-server
157136 callback error-callback))))
0 commit comments