Lsp-mode: Command execution is broken in Powershell

Created on 28 Nov 2019  路  8Comments  路  Source: emacs-lsp/lsp-mode

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

  1. Open emacs with lsp-start-plain.el
  2. Install the powershell package
  3. Open a Powershell file, start up LSP and write cd somewhere
  4. LSP should suggest an action to replace cd with Set-Locaiton. Try to execute it
  5. execution should fail

Expected 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)

All 8 comments

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

image

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,
image
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.

Was this page helpful?
0 / 5 - 0 ratings