internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: sublimelsp/LSP

Issue:
Show server command errors in an error dialog when running a code action
**Is your feature request related to a problem? Please describe.**
When running a code action of the "command" kind, it's hard to see what happened when the server returns an error response.

**Describe the solution you'd like**
When an error response is returned, show it with `sublime.error_message`.

**Describe alternatives you've considered**
Maybe print it to the status bar. But, users are engaged in this action already, so it's OK to show a popup dialog I think.

**Additional context**

This shows in the log panel, and it is currently the *only* way to figure out what happened.
```
:: --> clangd workspace/executeCommand(11): {'arguments': [{'file': 'file:///home/raoul/xxx.h', 'selection': {'end': {'line': 62, 'character': 19}, 'start': {'line': 62, 'character': 19}}, 'tweakID': 'DefineOutline'}], 'title': 'Move function body to out-of-line.', 'command': 'clangd.applyTweak'}
:: <~~ clangd 11: {'message': "Couldn't find a suitable implementation file.", 'code': -32001}
```



Discussion:
I guess a dialog might be good enough for now but it's not ideal since it blocks the whole editor (including the main thread) and also might be a bit unexpected when the command is triggered from code action.

There are many use cases where we would want to show an error message (or just an info message) of some kind and we don't have a good solution for those. I think a panel could work but probably a separate one from the diagnostics panel.
I agree with @rchl, there are other cases where where a status bar isn't enough and error message is too much. Since ST doesn't have a notification. LSP could setup a new panel just for notifications.

Resolving patch:
diff --git a/plugin/code_actions.py b/plugin/code_actions.py
--- a/plugin/code_actions.py
+++ b/plugin/code_actions.py
@@ -2,6 +2,7 @@
 from .core.protocol import CodeAction
 from .core.protocol import Command
 from .core.protocol import Diagnostic
+from .core.protocol import Error
 from .core.protocol import Request
 from .core.registry import LspTextCommand
 from .core.registry import sessions_for_view
@@ -312,6 +313,12 @@ def run_async() -> None:
                 selected = self.commands[index]
                 session = self.session_by_name(selected[0])
                 if session:
-                    session.run_code_action_async(selected[2], progress=True)
+                    name = session.config.name
+                    session.run_code_action_async(selected[2], progress=True).then(
+                        lambda resp: self.handle_response_async(name, resp))
 
             sublime.set_timeout_async(run_async)
+
+    def handle_response_async(self, session_name: str, response: Any) -> None:
+        if isinstance(response, Error):
+            sublime.error_message("{}: {}".format(session_name, str(response)))


Test patch:
Repository: sublimelsp/LSP

Issue:
UI blocked by dialogs when failing to start LS
The UI gets "DDOS'ed" in case server fails to start in non-project window.

1. Configure an LS server in LSP.sublime-settings that points to non-existing command
2. Open a new window and a file in it that window that triggers that server

This first triggers a dialog that says that server failed to start and then another dialog popups saying that the server can't be disabled due to not having a project. After second dialog is closed the first one opens again, blocking the UI.


Discussion:

Resolving patch:
diff --git a/plugin/core/configurations.py b/plugin/core/configurations.py
--- a/plugin/core/configurations.py
+++ b/plugin/core/configurations.py
@@ -79,7 +79,7 @@ def disable_config(self, config_name: str, only_for_session: bool = False) -> No
         if only_for_session:
             self._disable_for_session(config_name)
         else:
-            disable_in_project(self._window, config_name, only_for_session)
+            disable_in_project(self._window, config_name)
         self.update()
 
     def _disable_for_session(self, config_name: str) -> None:
diff --git a/plugin/core/windows.py b/plugin/core/windows.py
--- a/plugin/core/windows.py
+++ b/plugin/core/windows.py
@@ -333,14 +333,14 @@ def start_async(self, config: ClientConfig, initiating_view: sublime.View) -> No
             self._new_session = session
         except Exception as e:
             message = "".join((
-                "Failed to start {0} - disabling for this window. ",
+                "Failed to start {0} - disabling for this window for the duration of the current session.\n",
                 "Re-enable by running \"LSP: Enable Language Server In Project\" from the Command Palette.",
                 "\n\n--- Error: ---\n{1}"
             )).format(config.name, str(e))
             exception_log("Unable to start subprocess for {}".format(config.name), e)
             if isinstance(e, CalledProcessError):
                 print("Server output:\n{}".format(e.output.decode('utf-8', 'replace')))
-            self._configs.disable_config(config.name)
+            self._configs.disable_config(config.name, only_for_session=True)
             config.erase_view_status(initiating_view)
             sublime.message_dialog(message)
             # Continue with handling pending listeners
diff --git a/plugin/core/workspace.py b/plugin/core/workspace.py
--- a/plugin/core/workspace.py
+++ b/plugin/core/workspace.py
@@ -72,7 +72,7 @@ def enable_in_project(window: sublime.Window, config_name: str) -> None:
             "Can't enable {} in the current workspace. Ensure that the project is saved first.".format(config_name))
 
 
-def disable_in_project(window: sublime.Window, config_name: str, only_for_session: bool = False) -> None:
+def disable_in_project(window: sublime.Window, config_name: str) -> None:
     project_data = window.project_data()
     if isinstance(project_data, dict):
         project_settings = project_data.setdefault('settings', dict())


Test patch:
Repository: sublimelsp/LSP

Issue:
There should be a way to have Code Actions enabled but not visually offering them
**Is your feature request related to a problem? Please describe.**

Some language servers have certain Code Actions that are offered very frequently. For example, on virtually every line, [ocaml-lsp](https://github.com/ocaml/ocaml-lsp) will offer a Code Action to add a type annotation. This gets annoying, because although it's technically a valid thing being offered, it's distracting for there _always_ to be a bulb or annotation visible in ST.

**Describe the solution you'd like**

For it to be made possible to either:

**(A)** Disable the visual offering of all Code Actions. I guess by adding `false` as a possible value for this setting:

```jsonc
// Show code actions:
// "annotation" - show an annotation on the right when code actions are available.
// "bulb" - show a bulb in the gutter when code actions are available.
// Note: Due to API limitations, the "bulb" icon can not be clicked so the code actions can only be triggered
// using a keyboard shortcut or the context menu.
"show_code_actions": "annotation",
```

...then Code Actions would not be offered visually, but could still be summoned at the caret using a keybinding for the command `lsp_code_actions`.

or **(B)** Allowing the `disabled_capabilities` per-client setting to be used to mute certain Code Actions that the user doesn't want to be visually offered. Something like:

```jsonc
"disabled_capabilities": {
    "codeActionProvider": {
        "mute": ["type-annotate"],
    }
},
```


Discussion:

Resolving patch:
diff --git a/plugin/documents.py b/plugin/documents.py
--- a/plugin/documents.py
+++ b/plugin/documents.py
@@ -273,7 +273,8 @@ def diagnostics_touching_point_async(
 
     def on_diagnostics_updated_async(self) -> None:
         self._clear_code_actions_annotation()
-        self._do_code_actions()
+        if userprefs().show_code_actions:
+            self._do_code_actions()
         self._update_diagnostic_in_status_bar_async()
 
     def _update_diagnostic_in_status_bar_async(self) -> None:
@@ -339,8 +340,9 @@ def on_selection_modified_async(self) -> None:
             self._when_selection_remains_stable_async(self._do_highlights_async, current_region,
                                                       after_ms=self.highlights_debounce_time)
             self._clear_code_actions_annotation()
-            self._when_selection_remains_stable_async(self._do_code_actions, current_region,
-                                                      after_ms=self.code_actions_debounce_time)
+            if userprefs().show_code_actions:
+                self._when_selection_remains_stable_async(self._do_code_actions, current_region,
+                                                          after_ms=self.code_actions_debounce_time)
             self._update_diagnostic_in_status_bar_async()
             self._resolve_visible_code_lenses_async()
 


Test patch:
Repository: sublimelsp/LSP

Issue:
Getting error "list index out of range" when no command is defined
**Describe the bug**
LSP shows a cryptic error message when you want to use elixir-ls but the package settings don't define a default command similar to other clients. When you install ElixirLS on Manjaro the executable is named `elixir-ls`.

**To Reproduce**
Steps to reproduce the behavior:
1. In the User LSP.sublime-settings file choose a client you have installed.
2. Set command to an empty array e.g.:
```json
{
  "clients": {
    "elixir-ls": {
      "command": [],
      "enabled": true
    }
  }
}
```

**Expected behavior**
I would expect a hint that the command is empty/missing and needs to be configured before LSP tries to call it.

**Screenshots**
A dialog window pops up with the following error message:
```
Could not start elixir-ls
list index out of range
Server will be disabled for this window
```

**Environment (please complete the following information):**
- OS: Linux Manjaro
- Sublime Text version: 4096
- LSP version: 1.2.9
- Language servers used: only elixir-ls

**Additional context**
The error originally stems from `subprocess.Popen()` which expects args to be a non-empty array. The `Popen` function is called from `def _start_subprocess` in `"transports.py:260"`.

The error message comes from `"/plugin/core/windows.py:344"`.


Discussion:
I get the same error by just editing and saving `LSP-metals` settings

Resolving patch:
diff --git a/plugin/core/types.py b/plugin/core/types.py
--- a/plugin/core/types.py
+++ b/plugin/core/types.py
@@ -520,6 +520,8 @@ def __init__(
         env: Dict[str, str],
         listener_socket: Optional[socket.socket]
     ) -> None:
+        if not command and not tcp_port:
+            raise ValueError('neither "command" nor "tcp_port" is provided; cannot start a language server')
         self.name = name
         self.command = command
         self.tcp_port = tcp_port


Test patch:
Repository: sublimelsp/LSP

Issue:
`os.path.relpath` may throw an exception on Windows.
`os.path.relpath` may throw an exception on Windows.

```
Traceback (most recent call last):
File "C:\tools\sublime\Data\Installed Packages\LSP.sublime-package\plugin/references.py", line 55, in 
File "C:\tools\sublime\Data\Installed Packages\LSP.sublime-package\plugin/references.py", line 62, in _handle_response
File "C:\tools\sublime\Data\Installed Packages\LSP.sublime-package\plugin/references.py", line 85, in _show_references_in_output_panel
File "C:\tools\sublime\Data\Installed Packages\LSP.sublime-package\plugin/references.py", line 107, in _get_relative_path
File "./python3.3/ntpath.py", line 564, in relpath
ValueError: path is on mount 'C:', start on mount '\myserver\myshare'
```


Discussion:
> On Windows, ValueError is raised when path and start are on different drives.
https://docs.python.org/3/library/os.path.html#os.path.relpath

Resolving patch:
diff --git a/plugin/references.py b/plugin/references.py
--- a/plugin/references.py
+++ b/plugin/references.py
@@ -104,9 +104,12 @@ def _show_references_in_output_panel(self, word: str, session: Session, location
 
 def _get_relative_path(base_dir: Optional[str], file_path: str) -> str:
     if base_dir:
-        return os.path.relpath(file_path, base_dir)
-    else:
-        return file_path
+        try:
+            return os.path.relpath(file_path, base_dir)
+        except ValueError:
+            # On Windows, ValueError is raised when path and start are on different drives.
+            pass
+    return file_path
 
 
 def _group_locations_by_uri(


Test patch:
Repository: sublimelsp/LSP

Issue:
Window status messages from plugins should be cleared if plugin gets unloaded
If plugins set status messages via `Session.set_window_status_async`, they should automatically be erased when the plugin gets unloaded (by *Package Control: Disable Package*), just like it happens for the plugin name in the status bar.

I tried to add something like
```python
for status_key in session._status_messages.keys():
    view.erase_status(status_key)
```
(with the right references/substitutions for `session` and `view`) in `SessionView.__del__` or in `Session.unregister_session_view_async`, but neither of these places worked for me.

I would create a PR, but it would be great if someone could help me where exactly to put that code.


Discussion:
It should probably go in `Session.__del__`, no?
I tried it like this, but it still doesn't work for me:
```diff
--- C:\Users\jwortmann\AppData\Roaming\Sublime Text\Packages\LSP\plugin\core\sessions.py	Tue Jun  8 21:04:20 2021
+++ C:\Users\jwortmann\AppData\Roaming\Sublime Text\Packages\LSP\plugin\core\sessions.py	Tue Jun  8 21:04:30 2021
@@ -842,6 +842,11 @@
         self._plugin = None  # type: Optional[AbstractPlugin]
         self._status_messages = {}  # type: Dict[str, str]
 
+    def __del__(self) -> None:
+        for sv in self._session_views:
+            for status_key in self._status_messages.keys():
+                sv.view.erase_status(status_key)
+
     def __getattr__(self, name: str) -> Any:
         """
         If we don't have a request/notification handler, look up the request/notification handler in the plugin.
```

According to various answers on https://stackoverflow.com/questions/1481488/what-is-the-del-method-and-how-do-i-call-it, it is adviced against using `__del__` and there are caveats to it like
> The __del__ method, it will be called when the object is garbage collected. Note that it isn't necessarily guaranteed to be called though.

Do we have access to all sessions in `unregister_plugin` in sessions.py somehow (or how are the sessions closed when the plugin gets unloaded - I see that a shutdown request is sent as expected in that case)? I guess that might be an appropriate place, but of course you probably have more insight to this package.
I think the SessionViews might already be deleted at the point of `Session.__del__` if the session was force-shutdown.
Have you tried doing it from `Session.end_async()`?

Resolving patch:
diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py
--- a/plugin/core/sessions.py
+++ b/plugin/core/sessions.py
@@ -1331,6 +1331,8 @@ def end_async(self) -> None:
             self._plugin.on_session_end_async()
             self._plugin = None
         for sv in self.session_views_async():
+            for status_key in self._status_messages.keys():
+                sv.view.erase_status(status_key)
             sv.shutdown_async()
         self.capabilities.clear()
         self._registrations.clear()


Test patch:
Repository: sublimelsp/LSP

Issue:
Diagnostics underline in the view are not show if "diagnostics_gutter_marker" is set to ""
**Describe the bug**
If "diagnostics_gutter_marker" is set to ""

Diagnostics underlines are not visible in the view:

<img width="786" alt="Screenshot 2021-07-06 at 13 38 37" src="https://user-images.githubusercontent.com/22029477/124593989-9059dd80-de5f-11eb-82af-4f9ba744122a.png">

If I set If "diagnostics_gutter_marker" is set to "sign":
I will see the diagnostic underlines:

<img width="794" alt="Screenshot 2021-07-06 at 13 38 18" src="https://user-images.githubusercontent.com/22029477/124594041-9ea7f980-de5f-11eb-94ea-f840d43b717f.png">

**Expected behavior**
I should see view diagnostic underlines even when I set "diagnostics_gutter_marker" is set to "".

**Environment (please complete the following information):**
- OS: macOS 10.15
- Sublime Text version: 4106
- LSP version: latest commit


Discussion:

Resolving patch:
diff --git a/plugin/session_view.py b/plugin/session_view.py
--- a/plugin/session_view.py
+++ b/plugin/session_view.py
@@ -217,8 +217,7 @@ def _draw_diagnostics(self, severity: int, max_severity_level: int, flags: int,
         for key_tag in key_tags.values():
             self.view.erase_regions(key_tag)
         data = self.session_buffer.data_per_severity.get((severity, multiline))
-        # TODO: Why do we have this data.icon check?
-        if data and data.icon and severity <= max_severity_level:
+        if data and severity <= max_severity_level:
             non_tag_regions = data.regions
             for tag, regions in data.regions_with_tag.items():
                 tag_scope = self.diagnostics_tag_scope(tag)


Test patch:
Repository: sublimelsp/LSP

Issue:
Side by side option for symbol action links in hover popup doesn't work if location is in same file
**Describe the bug**
The side by side icon link for "Definition" / "Type Definition" / "Declaration" from the hover popup doesn't work if the location of the definition/declaration is in the same file.

**To Reproduce**
Steps to reproduce the behavior:
1. Have `"show_symbol_action_links": true` in the settings (this is the default value)
2. Hover over symbol (e.g. function call) which has a definition in the same file
3. Click on ◨ next to "Definition", or use <kbd>Ctrl</kbd> + click on the text link
4. See that the view scrolls to the location, instead of opening the location in a new tab to the right

**Expected behavior**
LSP should open the definition in a new new to the right, similar to how the built-in definitions popup from ST does

**Environment (please complete the following information):**
- OS: Win 10
- LSP version: main

**Additional context**

Seems like the `flags` argument which includes the "side_by_side" information is lost/ignored here:
https://github.com/sublimelsp/LSP/blob/1bcd518102c1516c9d808c974b7d2a5eba7d0b80/plugin/core/open.py#L30-L31


Discussion:

Resolving patch:
diff --git a/plugin/core/open.py b/plugin/core/open.py
--- a/plugin/core/open.py
+++ b/plugin/core/open.py
@@ -24,11 +24,15 @@ def open_file(
     The provided uri MUST be a file URI
     """
     file = parse_uri(uri)[1]
-    # window.open_file brings the file to focus if it's already opened, which we don't want.
-    # So we first check if there's already a view for that file.
+    # window.open_file brings the file to focus if it's already opened, which we don't want (unless it's supposed
+    # to open as a separate view).
     view = window.find_open_file(file)
     if view:
-        return Promise.resolve(view)
+        opens_in_current_group = group == -1 or window.active_group() == group
+        opens_as_new_selection = (flags & (sublime.ADD_TO_SELECTION | sublime.REPLACE_MRU)) != 0
+        return_existing_view = opens_in_current_group and not opens_as_new_selection
+        if return_existing_view:
+            return Promise.resolve(view)
 
     view = window.open_file(file, flags, group)
     if not view.is_loading():


Test patch:
Repository: sublimelsp/LSP

Issue:
Hover popup shows horizontal line
**Describe the bug**
Don't have time to look at it now but LSP-json shows some unexpected content (line) at the bottom of the hover popup:
![Screenshot 2022-07-05 at 11 07 11](https://user-images.githubusercontent.com/153197/177292966-24a3a30a-8429-452a-ba14-a70fb024e439.png)

Latest everything at the time of reporting.


Discussion:
Setting "show_symbol_action_links" to false will fix the issue.
This was introduced in https://github.com/sublimelsp/LSP/pull/1974

Didn't looked closely at that [PR](https://github.com/sublimelsp/LSP/pull/1974) to see what exactly causes this :)

I looked closely and the bug is somewhere here around this line
https://github.com/sublimelsp/LSP/pull/1974/files#diff-e572bef24745eb3ac503d83266340c8f98d60cf6e2d1ae91b0628370af45ac58R280

```
        if userprefs().show_symbol_action_links and contents and not only_diagnostics and hover_content:
            symbol_actions_content = self.symbol_actions_content(listener, point)
            if link_content and link_has_standard_tooltip:
                symbol_actions_content += ' | ' + link_content
            elif link_content:
                contents += '<div class="link with-padding">' + link_content + '</div>'
            contents += '<div class="actions">' + symbol_actions_content + '</div>' # hot spot, line 280 :)
```

`symbol_actions_content` value is an empty string on line 280

Looks like putting the last line under a `if symbol_actions_content:` will fix it.

And I think there is another bug: in case there is non-empty `link_content`, but no other `symbol_action_content`, then there will be an unneeded vertical spacer ` | ` at the beginning. I can make a PR to fix it.

Resolving patch:
diff --git a/plugin/hover.py b/plugin/hover.py
--- a/plugin/hover.py
+++ b/plugin/hover.py
@@ -274,10 +274,13 @@ def _show_hover(self, listener: AbstractViewListener, point: int, only_diagnosti
         if userprefs().show_symbol_action_links and contents and not only_diagnostics and hover_content:
             symbol_actions_content = self.symbol_actions_content(listener, point)
             if link_content and link_has_standard_tooltip:
-                symbol_actions_content += ' | ' + link_content
+                if symbol_actions_content:
+                    symbol_actions_content += ' | '
+                symbol_actions_content += link_content
             elif link_content:
                 contents += '<div class="link with-padding">' + link_content + '</div>'
-            contents += '<div class="actions">' + symbol_actions_content + '</div>'
+            if symbol_actions_content:
+                contents += '<div class="actions">' + symbol_actions_content + '</div>'
         elif link_content:
             contents += '<div class="{}">{}</div>'.format('link with-padding' if contents else 'link', link_content)
 


Test patch: