Repository: sublimelsp/LSP

Issue:
Code actions of CodeActionLiteral type are not supported (used by eslint-server)
While experimenting with [eslint-server](https://github.com/Microsoft/vscode-eslint/tree/master/server), I've noticed that its code actions for fixing lint issues are not handled properly.

I found two issues:
 - handling CodeActions action list as an array of `Command` while protocol also allows array of `CodeAction`.
 - Passing `args` param to `workspace/executeCommand` instead of expected `arguments` param.


Discussion:

Resolving patch:
diff --git a/plugin/code_actions.py b/plugin/code_actions.py
--- a/plugin/code_actions.py
+++ b/plugin/code_actions.py
@@ -10,6 +10,7 @@
 from .core.registry import client_for_view, LspTextCommand
 from .core.protocol import Request
 from .diagnostics import get_point_diagnostics
+from .core.edit import parse_workspace_edit
 from .core.url import filename_to_uri
 from .core.views import region_to_range
 from .core.registry import session_for_view
@@ -80,6 +81,11 @@ def hide_bulb(self) -> None:
         self.view.erase_regions('lsp_bulb')
 
 
+def is_command(command_or_code_action: dict) -> bool:
+    command_field = command_or_code_action.get('command')
+    return isinstance(command_field, str)
+
+
 class LspCodeActionsCommand(LspTextCommand):
     def is_enabled(self):
         return self.has_client_with_capability('codeActionProvider')
@@ -108,11 +114,26 @@ def show_popup_menu(self) -> None:
 
     def handle_select(self, index: int) -> None:
         if index > -1:
-            client = client_for_view(self.view)
-            if client:
-                client.send_request(
-                    Request.executeCommand(self.commands[index]),
-                    self.handle_command_response)
+
+            selected = self.commands[index]
+            if is_command(selected):
+                self.run_command(selected)
+            else:
+                # CodeAction can have an edit and/or command.
+                maybe_edit = selected.get('edit')
+                if maybe_edit:
+                    changes = parse_workspace_edit(maybe_edit)
+                    self.view.window().run_command("lsp_apply_workspace_edit", {'changes': changes})
+                maybe_command = selected.get('command')
+                if maybe_command:
+                    self.run_command(maybe_command)
+
+    def run_command(self, command) -> None:
+        client = client_for_view(self.view)
+        if client:
+            client.send_request(
+                Request.executeCommand(command),
+                self.handle_command_response)
 
     def handle_command_response(self, response):
         pass
diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py
--- a/plugin/core/sessions.py
+++ b/plugin/core/sessions.py
@@ -135,12 +135,15 @@ def get_initialize_params(project_path: str, config: ClientConfig):
                 "formatting": {},
                 "rangeFormatting": {},
                 "definition": {},
-                "codeAction": {},
+                "codeAction": {
+                    "codeActionLiteralSupport": {}
+                },
                 "rename": {}
             },
             "workspace": {
                 "applyEdit": True,
-                "didChangeConfiguration": {}
+                "didChangeConfiguration": {},
+                "executeCommand": {},
             }
         }
     }
diff --git a/plugin/execute_command.py b/plugin/execute_command.py
--- a/plugin/execute_command.py
+++ b/plugin/execute_command.py
@@ -24,13 +24,14 @@ def _handle_response(self, command: str, response: 'Optional[Any]') -> None:
         msg = "command {} completed".format(command)
         if response:
             msg += "with response: {}".format(response)
+
         sublime.message_dialog(msg)
 
     def _handle_error(self, command: str, error: 'Dict[str, Any]') -> None:
         msg = "command {} failed. Reason: {}".format(command, error.get("message", "none provided by server :("))
         sublime.message_dialog(msg)
 
-    def _send_command(self, client: Client, command_name: str, command_args: 'Dict[str, Any]') -> None:
+    def _send_command(self, client: Client, command_name: str, command_args: 'Optional[List[Any]]') -> None:
         request = {
             "command": command_name,
             "arguments": command_args


Test patch: