Describe the bug
The Powershell language server works. It even suggests code actions. However, trying to execute a code action causes No workspace could handle workspace/executeCommand. It does not happen in other language servers
To Reproduce
lsp-start-plain.elcd somewherecd with Set-Locaiton. Try to execute itExpected behavior
Execution should succeed
Which Language Server did you use
Powershell. Code actions seem to work on other language servers.
OS
macOS 10.15
Error callstack
Debugger entered--Lisp error: (error "No workspace could handle workspace/executeCommand")
signal(error ("No workspace could handle workspace/executeCommand"))
error("No workspace could handle %s" "workspace/executeCommand")
(if target-workspaces (let* ((start-time (current-time)) (method (plist-get body :method)) (workspaces-count (length target-workspaces)) (async-callback (lsp--create-async-callback workspaces-count callback mode method no-merge cancel-token)) (error-async-callback (lsp--create-async-callback workspaces-count (or error-callback (lsp--create-default-error-handler method)) mode method nil cancel-token)) (id (setq lsp-last-id (1+ lsp-last-id))) (body (plist-put body :id id))) (if cancel-token (progn (puthash cancel-token (cons id target-workspaces) lsp--cancelable-requests))) (seq-do (function (lambda (workspace) (let ((lsp--cur-workspace workspace)) (if lsp-print-io (progn ...)) (let (...) (puthash id ... ...) (lsp--send-no-wait message ...))))) target-workspaces) body) (error "No workspace could handle %s" (plist-get body :method)))
(let* ((target-workspaces (and t (lsp--find-workspaces-for body)))) (if target-workspaces (let* ((start-time (current-time)) (method (plist-get body :method)) (workspaces-count (length target-workspaces)) (async-callback (lsp--create-async-callback workspaces-count callback mode method no-merge cancel-token)) (error-async-callback (lsp--create-async-callback workspaces-count (or error-callback (lsp--create-default-error-handler method)) mode method nil cancel-token)) (id (setq lsp-last-id (1+ lsp-last-id))) (body (plist-put body :id id))) (if cancel-token (progn (puthash cancel-token (cons id target-workspaces) lsp--cancelable-requests))) (seq-do (function (lambda (workspace) (let (...) (if lsp-print-io ...) (let ... ... ...)))) target-workspaces) body) (error "No workspace could handle %s" (plist-get body :method))))
lsp--send-request-async((:jsonrpc "2.0" :method "workspace/executeCommand" :params (:command "PowerShell.ApplyCodeActionEdits" :arguments [#<hash-table equal 8/65 0x41a98edd>])) (closure ((resp-error) (resp-result) (expected-time . 1574944437.157068) (send-time . 1574944427.157068) (no-merge) (no-wait) (--cl-rest--) (params :command "PowerShell.ApplyCodeActionEdits" :arguments [#<hash-table equal 8/65 0x41a98edd>]) (method . "workspace/executeCommand") cl-struct-lsp--log-entry-tags cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags lsp-mode-menu cl-struct-lsp--folding-range-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp-watch-tags cl-struct-lsp--client-tags lsp--log-lines t) (res) (setq resp-result (or res :finished))) detached (closure ((resp-error) (resp-result) (expected-time . 1574944437.157068) (send-time . 1574944427.157068) (no-merge) (no-wait) (--cl-rest--) (params :command "PowerShell.ApplyCodeActionEdits" :arguments [#<hash-table equal 8/65 0x41a98edd>]) (method . "workspace/executeCommand") cl-struct-lsp--log-entry-tags cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags lsp-mode-menu cl-struct-lsp--folding-range-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp-watch-tags cl-struct-lsp--client-tags lsp--log-lines t) (err) (setq resp-error err)) nil :sync-request)
(progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) (quote (:mode :error-handler :no-merge :cancel-token :allow-other-keys))) (setq --cl-keys-- (cdr (cdr --cl-keys--)))) ((car (cdr (memq ... --cl-rest--))) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:mode :error-handler :no-merge :cancel-token)" (car --cl-keys--)))))) (lsp--send-request-async (list (quote :jsonrpc) "2.0" (quote :method) method (quote :params) params) callback mode error-handler no-merge cancel-token))
(let* ((mode (car (cdr (plist-member --cl-rest-- (quote :mode))))) (error-handler (car (cdr (plist-member --cl-rest-- (quote :error-handler))))) (no-merge (car (cdr (plist-member --cl-rest-- (quote :no-merge))))) (cancel-token (car (cdr (plist-member --cl-rest-- (quote :cancel-token)))))) (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) (quote ...)) (setq --cl-keys-- (cdr ...))) ((car (cdr ...)) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:mode :error-handler :no-merge :cancel-token)" (car --cl-keys--)))))) (lsp--send-request-async (list (quote :jsonrpc) "2.0" (quote :method) method (quote :params) params) callback mode error-handler no-merge cancel-token)))
lsp-request-async("workspace/executeCommand" (:command "PowerShell.ApplyCodeActionEdits" :arguments [#<hash-table equal 8/65 0x41a98edd>]) (closure ((resp-error) (resp-result) (expected-time . 1574944437.157068) (send-time . 1574944427.157068) (no-merge) (no-wait) (--cl-rest--) (params :command "PowerShell.ApplyCodeActionEdits" :arguments [#<hash-table equal 8/65 0x41a98edd>]) (method . "workspace/executeCommand") cl-struct-lsp--log-entry-tags cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags lsp-mode-menu cl-struct-lsp--folding-range-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp-watch-tags cl-struct-lsp--client-tags lsp--log-lines t) (res) (setq resp-result (or res :finished))) :error-handler (closure ((resp-error) (resp-result) (expected-time . 1574944437.157068) (send-time . 1574944427.157068) (no-merge) (no-wait) (--cl-rest--) (params :command "PowerShell.ApplyCodeActionEdits" :arguments [#<hash-table equal 8/65 0x41a98edd>]) (method . "workspace/executeCommand") cl-struct-lsp--log-entry-tags cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags lsp-mode-menu cl-struct-lsp--folding-range-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp-watch-tags cl-struct-lsp--client-tags lsp--log-lines t) (err) (setq resp-error err)) :no-merge nil :mode detached :cancel-token :sync-request)
(progn (lsp-request-async method params (function (lambda (res) (setq resp-result (or res :finished)))) :error-handler (function (lambda (err) (setq resp-error err))) :no-merge no-merge :mode (quote detached) :cancel-token :sync-request) (while (not (or resp-error resp-result)) (accept-process-output nil 0.001) (if (< expected-time (time-to-seconds (current-time))) (progn (error "Timeout while waiting for response. Method: %s." method)))) (cond ((eq resp-result :finished) nil) (resp-result resp-result) ((ht\? resp-error) (error (gethash "message" resp-error))) (t (error (gethash "message" (cl-first resp-error))))))
(unwind-protect (progn (lsp-request-async method params (function (lambda (res) (setq resp-result (or res :finished)))) :error-handler (function (lambda (err) (setq resp-error err))) :no-merge no-merge :mode (quote detached) :cancel-token :sync-request) (while (not (or resp-error resp-result)) (accept-process-output nil 0.001) (if (< expected-time (time-to-seconds (current-time))) (progn (error "Timeout while waiting for response. Method: %s." method)))) (cond ((eq resp-result :finished) nil) (resp-result resp-result) ((ht\? resp-error) (error (gethash "message" resp-error))) (t (error (gethash "message" (cl-first resp-error)))))) (lsp-cancel-request-by-token :sync-request))
(let* ((send-time (time-to-seconds (current-time))) (expected-time (+ send-time lsp-response-timeout)) resp-result resp-error) (unwind-protect (progn (lsp-request-async method params (function (lambda (res) (setq resp-result (or res :finished)))) :error-handler (function (lambda (err) (setq resp-error err))) :no-merge no-merge :mode (quote detached) :cancel-token :sync-request) (while (not (or resp-error resp-result)) (accept-process-output nil 0.001) (if (< expected-time (time-to-seconds (current-time))) (progn (error "Timeout while waiting for response. Method: %s." method)))) (cond ((eq resp-result :finished) nil) (resp-result resp-result) ((ht\? resp-error) (error (gethash "message" resp-error))) (t (error (gethash "message" (cl-first resp-error)))))) (lsp-cancel-request-by-token :sync-request)))
(if no-wait (lsp-notify method params) (let* ((send-time (time-to-seconds (current-time))) (expected-time (+ send-time lsp-response-timeout)) resp-result resp-error) (unwind-protect (progn (lsp-request-async method params (function (lambda (res) (setq resp-result ...))) :error-handler (function (lambda (err) (setq resp-error err))) :no-merge no-merge :mode (quote detached) :cancel-token :sync-request) (while (not (or resp-error resp-result)) (accept-process-output nil 0.001) (if (< expected-time (time-to-seconds ...)) (progn (error "Timeout while waiting for response. Method: %s." method)))) (cond ((eq resp-result :finished) nil) (resp-result resp-result) ((ht\? resp-error) (error (gethash "message" resp-error))) (t (error (gethash "message" ...))))) (lsp-cancel-request-by-token :sync-request))))
(progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) (quote (:no-wait :no-merge :allow-other-keys))) (setq --cl-keys-- (cdr (cdr --cl-keys--)))) ((car (cdr (memq ... --cl-rest--))) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:no-wait :no-merge)" (car --cl-keys--)))))) (if no-wait (lsp-notify method params) (let* ((send-time (time-to-seconds (current-time))) (expected-time (+ send-time lsp-response-timeout)) resp-result resp-error) (unwind-protect (progn (lsp-request-async method params (function (lambda ... ...)) :error-handler (function (lambda ... ...)) :no-merge no-merge :mode (quote detached) :cancel-token :sync-request) (while (not (or resp-error resp-result)) (accept-process-output nil 0.001) (if (< expected-time ...) (progn ...))) (cond ((eq resp-result :finished) nil) (resp-result resp-result) ((ht\? resp-error) (error ...)) (t (error ...)))) (lsp-cancel-request-by-token :sync-request)))))
(let* ((no-wait (car (cdr (plist-member --cl-rest-- (quote :no-wait))))) (no-merge (car (cdr (plist-member --cl-rest-- (quote :no-merge)))))) (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) (quote ...)) (setq --cl-keys-- (cdr ...))) ((car (cdr ...)) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:no-wait :no-merge)" (car --cl-keys--)))))) (if no-wait (lsp-notify method params) (let* ((send-time (time-to-seconds (current-time))) (expected-time (+ send-time lsp-response-timeout)) resp-result resp-error) (unwind-protect (progn (lsp-request-async method params (function ...) :error-handler (function ...) :no-merge no-merge :mode (quote detached) :cancel-token :sync-request) (while (not ...) (accept-process-output nil 0.001) (if ... ...)) (cond (... nil) (resp-result resp-result) (... ...) (t ...))) (lsp-cancel-request-by-token :sync-request))))))
lsp-request("workspace/executeCommand" (:command "PowerShell.ApplyCodeActionEdits" :arguments [#<hash-table equal 8/65 0x41a98edd>]))
(let ((params (if args (list :command command :arguments args) (list :command command)))) (lsp-request "workspace/executeCommand" params))
lsp--send-execute-command("PowerShell.ApplyCodeActionEdits" [#<hash-table equal 8/65 0x41a98edd>])
(if action-handler (funcall action-handler action) (lsp--send-execute-command command (gethash "arguments" action)))
(let ((action-handler (lsp--find-action-handler command))) (if action-handler (funcall action-handler action) (lsp--send-execute-command command (gethash "arguments" action))))
(if command (let ((action-handler (lsp--find-action-handler command))) (if action-handler (funcall action-handler action) (lsp--send-execute-command command (gethash "arguments" action)))) (lsp--send-execute-command command (gethash "arguments" action)))
(let ((command (gethash "command" action))) (if command (let ((action-handler (lsp--find-action-handler command))) (if action-handler (funcall action-handler action) (lsp--send-execute-command command (gethash "arguments" action)))) (lsp--send-execute-command command (gethash "arguments" action))))
lsp--execute-command(#<hash-table equal 3/65 0x41a98ebd>)
(cond ((stringp command) (lsp--execute-command action)) ((hash-table-p command) (lsp--execute-command command)))
(let ((command (gethash "command" action))) (cond ((stringp command) (lsp--execute-command action)) ((hash-table-p command) (lsp--execute-command command))))
lsp-execute-code-action(#<hash-table equal 3/65 0x41a98ebd>)
lsp-ui-sideline-apply-code-actions()
funcall-interactively(lsp-ui-sideline-apply-code-actions)
call-interactively(lsp-ui-sideline-apply-code-actions record nil)
command-execute(lsp-ui-sideline-apply-code-actions record)
execute-extended-command(nil "lsp-ui-sideline-apply-code-actions" "lsp-ui-co")
funcall-interactively(execute-extended-command nil "lsp-ui-sideline-apply-code-actions" "lsp-ui-co")
call-interactively(execute-extended-command nil nil)
command-execute(execute-extended-command)
Usually, code actions require some client-side adjustments, @kiennq willing to take a look?
I will take a look at this. Never realize that powershell lang server support code action :|
@r-darwish, do you have other custiomization for lsp-pwsh?
I'm on Windows and it seems that the code action is not support there without other customization.
I cannot even reach the error callstack
This is weird. The code action seemed to work on macOS without any customization, but I cannot see it in Windows as well. Also, I had to fix the installation in Windows in emacs-lsp/lsp-mode#1206

Here is a screenshot of the suggested code action in macOS. I had to do lsp-workspace-restart for it to show. In addition, I get the following warning whenever I turn on LSP for powershell:
Warning (lsp-mode): Unknown notification: output
I don't know if it's related, though.
Okay, I confirmed that in Windows, code action is not working, even for VsCode,

Let see if I have any luck trying it in WSL
My mistake, code action should work in Windows too. The problem is because the file path in Windows is case insensitive and it affect the diagnostic look up in (lsp-diagnostics).
Will try to resolve it in same issue too
In case someone is interested I added PowerShell to lsp-docker - https://github.com/emacs-lsp/lsp-docker/commit/e0949889955fbd96001d28b9507e04e5c6e065d7 . @kiennq I noticed that lsp-mode crashes with an obscure error when PowerShell is not installed on the machine, we may want to fix that as well.