We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Could you add following command: "Show all occurrences and rename symbol"
Hi!

I would like to see all occurrences of symbol before renaming.
It would be nice to have this command.

Thanks!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `plugin/core/panels.py`
Content:
```
1 from .typing import Dict, Optional, List, Generator, Tuple
2 from .types import debounced
3 from contextlib import contextmanager
4 import sublime
5 import sublime_plugin
6 
7 
8 # about 80 chars per line implies maintaining a buffer of about 40kb per window
9 SERVER_PANEL_MAX_LINES = 500
10 
11 # If nothing else shows up after 80ms, actually print the messages to the panel
12 SERVER_PANEL_DEBOUNCE_TIME_MS = 80
13 
14 OUTPUT_PANEL_SETTINGS = {
15     "auto_indent": False,
16     "draw_indent_guides": False,
17     "draw_unicode_white_space": "none",
18     "draw_white_space": "none",
19     "fold_buttons": True,
20     "gutter": True,
21     "is_widget": True,
22     "line_numbers": False,
23     "lsp_active": True,
24     "margin": 3,
25     "match_brackets": False,
26     "rulers": [],
27     "scroll_past_end": False,
28     "show_definitions": False,
29     "tab_size": 4,
30     "translate_tabs_to_spaces": False,
31     "word_wrap": False
32 }
33 
34 
35 class PanelName:
36     Diagnostics = "diagnostics"
37     References = "references"
38     LanguageServers = "language servers"
39 
40 
41 @contextmanager
42 def mutable(view: sublime.View) -> Generator:
43     view.set_read_only(False)
44     yield
45     view.set_read_only(True)
46 
47 
48 def create_output_panel(window: sublime.Window, name: str) -> Optional[sublime.View]:
49     panel = window.create_output_panel(name)
50     settings = panel.settings()
51     for key, value in OUTPUT_PANEL_SETTINGS.items():
52         settings.set(key, value)
53     return panel
54 
55 
56 def destroy_output_panels(window: sublime.Window) -> None:
57     for field in filter(lambda a: not a.startswith('__'), PanelName.__dict__.keys()):
58         panel_name = getattr(PanelName, field)
59         panel = window.find_output_panel(panel_name)
60         if panel and panel.is_valid():
61             panel.settings().set("syntax", "Packages/Text/Plain text.tmLanguage")
62             window.destroy_output_panel(panel_name)
63 
64 
65 def create_panel(window: sublime.Window, name: str, result_file_regex: str, result_line_regex: str,
66                  syntax: str) -> Optional[sublime.View]:
67     panel = create_output_panel(window, name)
68     if not panel:
69         return None
70     if result_file_regex:
71         panel.settings().set("result_file_regex", result_file_regex)
72     if result_line_regex:
73         panel.settings().set("result_line_regex", result_line_regex)
74     panel.assign_syntax(syntax)
75     # Call create_output_panel a second time after assigning the above
76     # settings, so that it'll be picked up as a result buffer
77     # see: Packages/Default/exec.py#L228-L230
78     panel = window.create_output_panel(name)
79     # All our panels are read-only
80     panel.set_read_only(True)
81     return panel
82 
83 
84 def ensure_panel(window: sublime.Window, name: str, result_file_regex: str, result_line_regex: str,
85                  syntax: str) -> Optional[sublime.View]:
86     return window.find_output_panel(name) or create_panel(window, name, result_file_regex, result_line_regex, syntax)
87 
88 
89 class LspClearPanelCommand(sublime_plugin.TextCommand):
90     """
91     A clear_panel command to clear the error panel.
92     """
93 
94     def run(self, edit: sublime.Edit) -> None:
95         with mutable(self.view):
96             self.view.erase(edit, sublime.Region(0, self.view.size()))
97 
98 
99 class LspUpdatePanelCommand(sublime_plugin.TextCommand):
100     """
101     A update_panel command to update the error panel with new text.
102     """
103 
104     def run(self, edit: sublime.Edit, characters: Optional[str] = "") -> None:
105         # Clear folds
106         self.view.unfold(sublime.Region(0, self.view.size()))
107 
108         with mutable(self.view):
109             self.view.replace(edit, sublime.Region(0, self.view.size()), characters or "")
110 
111         # Clear the selection
112         selection = self.view.sel()
113         selection.clear()
114 
115 
116 def ensure_server_panel(window: sublime.Window) -> Optional[sublime.View]:
117     return ensure_panel(window, PanelName.LanguageServers, "", "", "Packages/LSP/Syntaxes/ServerLog.sublime-syntax")
118 
119 
120 def update_server_panel(window: sublime.Window, prefix: str, message: str) -> None:
121     if not window.is_valid():
122         return
123     window_id = window.id()
124     panel = ensure_server_panel(window)
125     if not panel:
126         return
127     LspUpdateServerPanelCommand.to_be_processed.setdefault(window_id, []).append((prefix, message))
128     previous_length = len(LspUpdateServerPanelCommand.to_be_processed[window_id])
129 
130     def condition() -> bool:
131         if not panel:
132             return False
133         if not panel.is_valid():
134             return False
135         to_process = LspUpdateServerPanelCommand.to_be_processed.get(window_id)
136         if to_process is None:
137             return False
138         current_length = len(to_process)
139         if current_length >= 10:
140             # Do not let the queue grow large.
141             return True
142         # If the queue remains stable, flush the messages.
143         return current_length == previous_length
144 
145     debounced(
146         lambda: panel.run_command("lsp_update_server_panel", {"window_id": window_id}) if panel else None,
147         SERVER_PANEL_DEBOUNCE_TIME_MS,
148         condition
149     )
150 
151 
152 class LspUpdateServerPanelCommand(sublime_plugin.TextCommand):
153 
154     to_be_processed = {}  # type: Dict[int, List[Tuple[str, str]]]
155 
156     def run(self, edit: sublime.Edit, window_id: int) -> None:
157         to_process = self.to_be_processed.pop(window_id)
158         with mutable(self.view):
159             for prefix, message in to_process:
160                 message = message.replace("\r\n", "\n")  # normalize Windows eol
161                 self.view.insert(edit, self.view.size(), "{}: {}\n".format(prefix, message))
162                 total_lines, _ = self.view.rowcol(self.view.size())
163                 point = 0  # Starting from point 0 in the panel ...
164                 regions = []  # type: List[sublime.Region]
165             for _ in range(0, max(0, total_lines - SERVER_PANEL_MAX_LINES)):
166                 # ... collect all regions that span an entire line ...
167                 region = self.view.full_line(point)
168                 regions.append(region)
169                 point = region.b
170             for region in reversed(regions):
171                 # ... and erase them in reverse order
172                 self.view.erase(edit, region)
173
```

Path: `plugin/rename.py`
Content:
```
1 import sublime
2 import sublime_plugin
3 from .core.edit import apply_workspace_edit
4 from .core.edit import parse_workspace_edit
5 from .core.protocol import Range
6 from .core.protocol import Request
7 from .core.registry import get_position
8 from .core.registry import LspTextCommand
9 from .core.typing import Any, Optional
10 from .core.views import range_to_region
11 from .core.views import text_document_position_params
12 
13 
14 class RenameSymbolInputHandler(sublime_plugin.TextInputHandler):
15     def __init__(self, view: sublime.View, placeholder: str) -> None:
16         self.view = view
17         self._placeholder = placeholder
18 
19     def name(self) -> str:
20         return "new_name"
21 
22     def placeholder(self) -> str:
23         return self._placeholder
24 
25     def initial_text(self) -> str:
26         return self.placeholder()
27 
28     def validate(self, name: str) -> bool:
29         return len(name) > 0
30 
31 
32 class LspSymbolRenameCommand(LspTextCommand):
33 
34     capability = 'renameProvider'
35 
36     # mypy: Signature of "is_enabled" incompatible with supertype "LspTextCommand"
37     def is_enabled(  # type: ignore
38         self,
39         new_name: str = "",
40         placeholder: str = "",
41         position: Optional[int] = None,
42         event: Optional[dict] = None,
43         point: Optional[int] = None
44     ) -> bool:
45         if self.best_session("renameProvider.prepareProvider"):
46             # The language server will tell us if the selection is on a valid token.
47             return True
48         return super().is_enabled(event, point)
49 
50     def input(self, args: dict) -> Optional[sublime_plugin.TextInputHandler]:
51         if "new_name" not in args:
52             placeholder = args.get("placeholder", "")
53             if not placeholder:
54                 point = args.get("point")
55                 # guess the symbol name
56                 if not isinstance(point, int):
57                     point = self.view.sel()[0].b
58                 placeholder = self.view.substr(self.view.word(point))
59             return RenameSymbolInputHandler(self.view, placeholder)
60         else:
61             return None
62 
63     def run(
64         self,
65         edit: sublime.Edit,
66         new_name: str = "",
67         placeholder: str = "",
68         position: Optional[int] = None,
69         event: Optional[dict] = None,
70         point: Optional[int] = None
71     ) -> None:
72         if position is None:
73             pos = get_position(self.view, event, point)
74             if new_name:
75                 return self._do_rename(pos, new_name)
76             else:
77                 session = self.best_session("{}.prepareProvider".format(self.capability))
78                 if session:
79                     params = text_document_position_params(self.view, pos)
80                     request = Request.prepareRename(params, self.view)
81                     self.event = event
82                     session.send_request(request, lambda r: self.on_prepare_result(r, pos), self.on_prepare_error)
83                 else:
84                     # trigger InputHandler manually
85                     raise TypeError("required positional argument")
86         else:
87             if new_name:
88                 return self._do_rename(position, new_name)
89             else:
90                 # trigger InputHandler manually
91                 raise TypeError("required positional argument")
92 
93     def _do_rename(self, position: int, new_name: str) -> None:
94         session = self.best_session(self.capability)
95         if session:
96             params = text_document_position_params(self.view, position)
97             params["newName"] = new_name
98             session.send_request(
99                 Request.rename(params, self.view),
100                 # This has to run on the main thread due to calling apply_workspace_edit
101                 lambda r: sublime.set_timeout(lambda: self.on_rename_result(r))
102             )
103 
104     def on_rename_result(self, response: Any) -> None:
105         window = self.view.window()
106         if window:
107             if response:
108                 apply_workspace_edit(window, parse_workspace_edit(response))
109             else:
110                 window.status_message('Nothing to rename')
111 
112     def on_prepare_result(self, response: Any, pos: int) -> None:
113         if response is None:
114             sublime.error_message("The current selection cannot be renamed")
115             return
116         # It must be a dict at this point.
117         if "placeholder" in response:
118             placeholder = response["placeholder"]
119             r = response["range"]
120         else:
121             placeholder = self.view.substr(self.view.word(pos))
122             r = response
123         region = range_to_region(Range.from_lsp(r), self.view)
124         args = {"placeholder": placeholder, "position": region.a, "event": self.event}
125         self.view.run_command("lsp_symbol_rename", args)
126 
127     def on_prepare_error(self, error: Any) -> None:
128         sublime.error_message("Rename error: {}".format(error["message"]))
129
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/plugin/core/panels.py b/plugin/core/panels.py
--- a/plugin/core/panels.py
+++ b/plugin/core/panels.py
@@ -35,6 +35,7 @@
 class PanelName:
     Diagnostics = "diagnostics"
     References = "references"
+    Rename = "rename"
     LanguageServers = "language servers"
 
 
diff --git a/plugin/rename.py b/plugin/rename.py
--- a/plugin/rename.py
+++ b/plugin/rename.py
@@ -1,14 +1,19 @@
-import sublime
-import sublime_plugin
 from .core.edit import apply_workspace_edit
 from .core.edit import parse_workspace_edit
+from .core.edit import TextEdit
+from .core.panels import ensure_panel
+from .core.panels import PanelName
 from .core.protocol import Range
 from .core.protocol import Request
 from .core.registry import get_position
 from .core.registry import LspTextCommand
-from .core.typing import Any, Optional
+from .core.registry import windows
+from .core.typing import Any, Optional, Dict, List
 from .core.views import range_to_region
 from .core.views import text_document_position_params
+import os
+import sublime
+import sublime_plugin
 
 
 class RenameSymbolInputHandler(sublime_plugin.TextInputHandler):
@@ -105,7 +110,18 @@
         window = self.view.window()
         if window:
             if response:
-                apply_workspace_edit(window, parse_workspace_edit(response))
+                changes = parse_workspace_edit(response)
+                file_count = len(changes.keys())
+                if file_count > 1:
+                    total_changes = sum(map(len, changes.values()))
+                    message = "Replace {} occurrences across {} files?".format(total_changes, file_count)
+                    choice = sublime.yes_no_cancel_dialog(message, "Replace", "Dry Run")
+                    if choice == sublime.DIALOG_YES:
+                        apply_workspace_edit(window, changes)
+                    elif choice == sublime.DIALOG_NO:
+                        self._render_rename_panel(changes, total_changes, file_count)
+                else:
+                    apply_workspace_edit(window, changes)
             else:
                 window.status_message('Nothing to rename')
 
@@ -126,3 +142,49 @@
 
     def on_prepare_error(self, error: Any) -> None:
         sublime.error_message("Rename error: {}".format(error["message"]))
+
+    def _get_relative_path(self, file_path: str) -> str:
+        window = self.view.window()
+        if not window:
+            return file_path
+        base_dir = windows.lookup(window).get_project_path(file_path)
+        if base_dir:
+            return os.path.relpath(file_path, base_dir)
+        else:
+            return file_path
+
+    def _render_rename_panel(self, changes: Dict[str, List[TextEdit]], total_changes: int, file_count: int) -> None:
+        window = self.view.window()
+        if not window:
+            return
+        panel = ensure_rename_panel(window)
+        if not panel:
+            return
+        text = ''
+        for file, file_changes in changes.items():
+            text += '◌ {}:\n'.format(self._get_relative_path(file))
+            for edit in file_changes:
+                start = edit[0]
+                text += '\t{:>8}:{}\n'.format(start[0] + 1, start[1] + 1)
+            # append a new line after each file name
+            text += '\n'
+        base_dir = windows.lookup(window).get_project_path(self.view.file_name() or "")
+        panel.settings().set("result_base_dir", base_dir)
+        panel.run_command("lsp_clear_panel")
+        window.run_command("show_panel", {"panel": "output.rename"})
+        fmt = "{} changes across {} files. Double-click on a row:col number to jump to that location.\n\n{}"
+        panel.run_command('append', {
+            'characters': fmt.format(total_changes, file_count, text),
+            'force': True,
+            'scroll_to_end': False
+        })
+
+
+def ensure_rename_panel(window: sublime.Window) -> Optional[sublime.View]:
+    return ensure_panel(
+        window=window,
+        name=PanelName.Rename,
+        result_file_regex=r"^\s*\S\s+(\S.*):$",
+        result_line_regex=r"^\s*([0-9]+):([0-9]+)\s*$",
+        syntax="Packages/LSP/Syntaxes/Rename.sublime-syntax"
+    )

{"golden_diff": "diff --git a/plugin/core/panels.py b/plugin/core/panels.py\n--- a/plugin/core/panels.py\n+++ b/plugin/core/panels.py\n@@ -35,6 +35,7 @@\n class PanelName:\n     Diagnostics = \"diagnostics\"\n     References = \"references\"\n+    Rename = \"rename\"\n     LanguageServers = \"language servers\"\n \n \ndiff --git a/plugin/rename.py b/plugin/rename.py\n--- a/plugin/rename.py\n+++ b/plugin/rename.py\n@@ -1,14 +1,19 @@\n-import sublime\n-import sublime_plugin\n from .core.edit import apply_workspace_edit\n from .core.edit import parse_workspace_edit\n+from .core.edit import TextEdit\n+from .core.panels import ensure_panel\n+from .core.panels import PanelName\n from .core.protocol import Range\n from .core.protocol import Request\n from .core.registry import get_position\n from .core.registry import LspTextCommand\n-from .core.typing import Any, Optional\n+from .core.registry import windows\n+from .core.typing import Any, Optional, Dict, List\n from .core.views import range_to_region\n from .core.views import text_document_position_params\n+import os\n+import sublime\n+import sublime_plugin\n \n \n class RenameSymbolInputHandler(sublime_plugin.TextInputHandler):\n@@ -105,7 +110,18 @@\n         window = self.view.window()\n         if window:\n             if response:\n-                apply_workspace_edit(window, parse_workspace_edit(response))\n+                changes = parse_workspace_edit(response)\n+                file_count = len(changes.keys())\n+                if file_count > 1:\n+                    total_changes = sum(map(len, changes.values()))\n+                    message = \"Replace {} occurrences across {} files?\".format(total_changes, file_count)\n+                    choice = sublime.yes_no_cancel_dialog(message, \"Replace\", \"Dry Run\")\n+                    if choice == sublime.DIALOG_YES:\n+                        apply_workspace_edit(window, changes)\n+                    elif choice == sublime.DIALOG_NO:\n+                        self._render_rename_panel(changes, total_changes, file_count)\n+                else:\n+                    apply_workspace_edit(window, changes)\n             else:\n                 window.status_message('Nothing to rename')\n \n@@ -126,3 +142,49 @@\n \n     def on_prepare_error(self, error: Any) -> None:\n         sublime.error_message(\"Rename error: {}\".format(error[\"message\"]))\n+\n+    def _get_relative_path(self, file_path: str) -> str:\n+        window = self.view.window()\n+        if not window:\n+            return file_path\n+        base_dir = windows.lookup(window).get_project_path(file_path)\n+        if base_dir:\n+            return os.path.relpath(file_path, base_dir)\n+        else:\n+            return file_path\n+\n+    def _render_rename_panel(self, changes: Dict[str, List[TextEdit]], total_changes: int, file_count: int) -> None:\n+        window = self.view.window()\n+        if not window:\n+            return\n+        panel = ensure_rename_panel(window)\n+        if not panel:\n+            return\n+        text = ''\n+        for file, file_changes in changes.items():\n+            text += '\u25cc {}:\\n'.format(self._get_relative_path(file))\n+            for edit in file_changes:\n+                start = edit[0]\n+                text += '\\t{:>8}:{}\\n'.format(start[0] + 1, start[1] + 1)\n+            # append a new line after each file name\n+            text += '\\n'\n+        base_dir = windows.lookup(window).get_project_path(self.view.file_name() or \"\")\n+        panel.settings().set(\"result_base_dir\", base_dir)\n+        panel.run_command(\"lsp_clear_panel\")\n+        window.run_command(\"show_panel\", {\"panel\": \"output.rename\"})\n+        fmt = \"{} changes across {} files. Double-click on a row:col number to jump to that location.\\n\\n{}\"\n+        panel.run_command('append', {\n+            'characters': fmt.format(total_changes, file_count, text),\n+            'force': True,\n+            'scroll_to_end': False\n+        })\n+\n+\n+def ensure_rename_panel(window: sublime.Window) -> Optional[sublime.View]:\n+    return ensure_panel(\n+        window=window,\n+        name=PanelName.Rename,\n+        result_file_regex=r\"^\\s*\\S\\s+(\\S.*):$\",\n+        result_line_regex=r\"^\\s*([0-9]+):([0-9]+)\\s*$\",\n+        syntax=\"Packages/LSP/Syntaxes/Rename.sublime-syntax\"\n+    )\n", "issue": "Could you add following command: \"Show all occurrences and rename symbol\"\nHi!\r\n\r\nI would like to see all occurrences of symbol before renaming.\r\nIt would be nice to have this command.\r\n\r\nThanks!\n", "before_files": [{"content": "from .typing import Dict, Optional, List, Generator, Tuple\nfrom .types import debounced\nfrom contextlib import contextmanager\nimport sublime\nimport sublime_plugin\n\n\n# about 80 chars per line implies maintaining a buffer of about 40kb per window\nSERVER_PANEL_MAX_LINES = 500\n\n# If nothing else shows up after 80ms, actually print the messages to the panel\nSERVER_PANEL_DEBOUNCE_TIME_MS = 80\n\nOUTPUT_PANEL_SETTINGS = {\n    \"auto_indent\": False,\n    \"draw_indent_guides\": False,\n    \"draw_unicode_white_space\": \"none\",\n    \"draw_white_space\": \"none\",\n    \"fold_buttons\": True,\n    \"gutter\": True,\n    \"is_widget\": True,\n    \"line_numbers\": False,\n    \"lsp_active\": True,\n    \"margin\": 3,\n    \"match_brackets\": False,\n    \"rulers\": [],\n    \"scroll_past_end\": False,\n    \"show_definitions\": False,\n    \"tab_size\": 4,\n    \"translate_tabs_to_spaces\": False,\n    \"word_wrap\": False\n}\n\n\nclass PanelName:\n    Diagnostics = \"diagnostics\"\n    References = \"references\"\n    LanguageServers = \"language servers\"\n\n\n@contextmanager\ndef mutable(view: sublime.View) -> Generator:\n    view.set_read_only(False)\n    yield\n    view.set_read_only(True)\n\n\ndef create_output_panel(window: sublime.Window, name: str) -> Optional[sublime.View]:\n    panel = window.create_output_panel(name)\n    settings = panel.settings()\n    for key, value in OUTPUT_PANEL_SETTINGS.items():\n        settings.set(key, value)\n    return panel\n\n\ndef destroy_output_panels(window: sublime.Window) -> None:\n    for field in filter(lambda a: not a.startswith('__'), PanelName.__dict__.keys()):\n        panel_name = getattr(PanelName, field)\n        panel = window.find_output_panel(panel_name)\n        if panel and panel.is_valid():\n            panel.settings().set(\"syntax\", \"Packages/Text/Plain text.tmLanguage\")\n            window.destroy_output_panel(panel_name)\n\n\ndef create_panel(window: sublime.Window, name: str, result_file_regex: str, result_line_regex: str,\n                 syntax: str) -> Optional[sublime.View]:\n    panel = create_output_panel(window, name)\n    if not panel:\n        return None\n    if result_file_regex:\n        panel.settings().set(\"result_file_regex\", result_file_regex)\n    if result_line_regex:\n        panel.settings().set(\"result_line_regex\", result_line_regex)\n    panel.assign_syntax(syntax)\n    # Call create_output_panel a second time after assigning the above\n    # settings, so that it'll be picked up as a result buffer\n    # see: Packages/Default/exec.py#L228-L230\n    panel = window.create_output_panel(name)\n    # All our panels are read-only\n    panel.set_read_only(True)\n    return panel\n\n\ndef ensure_panel(window: sublime.Window, name: str, result_file_regex: str, result_line_regex: str,\n                 syntax: str) -> Optional[sublime.View]:\n    return window.find_output_panel(name) or create_panel(window, name, result_file_regex, result_line_regex, syntax)\n\n\nclass LspClearPanelCommand(sublime_plugin.TextCommand):\n    \"\"\"\n    A clear_panel command to clear the error panel.\n    \"\"\"\n\n    def run(self, edit: sublime.Edit) -> None:\n        with mutable(self.view):\n            self.view.erase(edit, sublime.Region(0, self.view.size()))\n\n\nclass LspUpdatePanelCommand(sublime_plugin.TextCommand):\n    \"\"\"\n    A update_panel command to update the error panel with new text.\n    \"\"\"\n\n    def run(self, edit: sublime.Edit, characters: Optional[str] = \"\") -> None:\n        # Clear folds\n        self.view.unfold(sublime.Region(0, self.view.size()))\n\n        with mutable(self.view):\n            self.view.replace(edit, sublime.Region(0, self.view.size()), characters or \"\")\n\n        # Clear the selection\n        selection = self.view.sel()\n        selection.clear()\n\n\ndef ensure_server_panel(window: sublime.Window) -> Optional[sublime.View]:\n    return ensure_panel(window, PanelName.LanguageServers, \"\", \"\", \"Packages/LSP/Syntaxes/ServerLog.sublime-syntax\")\n\n\ndef update_server_panel(window: sublime.Window, prefix: str, message: str) -> None:\n    if not window.is_valid():\n        return\n    window_id = window.id()\n    panel = ensure_server_panel(window)\n    if not panel:\n        return\n    LspUpdateServerPanelCommand.to_be_processed.setdefault(window_id, []).append((prefix, message))\n    previous_length = len(LspUpdateServerPanelCommand.to_be_processed[window_id])\n\n    def condition() -> bool:\n        if not panel:\n            return False\n        if not panel.is_valid():\n            return False\n        to_process = LspUpdateServerPanelCommand.to_be_processed.get(window_id)\n        if to_process is None:\n            return False\n        current_length = len(to_process)\n        if current_length >= 10:\n            # Do not let the queue grow large.\n            return True\n        # If the queue remains stable, flush the messages.\n        return current_length == previous_length\n\n    debounced(\n        lambda: panel.run_command(\"lsp_update_server_panel\", {\"window_id\": window_id}) if panel else None,\n        SERVER_PANEL_DEBOUNCE_TIME_MS,\n        condition\n    )\n\n\nclass LspUpdateServerPanelCommand(sublime_plugin.TextCommand):\n\n    to_be_processed = {}  # type: Dict[int, List[Tuple[str, str]]]\n\n    def run(self, edit: sublime.Edit, window_id: int) -> None:\n        to_process = self.to_be_processed.pop(window_id)\n        with mutable(self.view):\n            for prefix, message in to_process:\n                message = message.replace(\"\\r\\n\", \"\\n\")  # normalize Windows eol\n                self.view.insert(edit, self.view.size(), \"{}: {}\\n\".format(prefix, message))\n                total_lines, _ = self.view.rowcol(self.view.size())\n                point = 0  # Starting from point 0 in the panel ...\n                regions = []  # type: List[sublime.Region]\n            for _ in range(0, max(0, total_lines - SERVER_PANEL_MAX_LINES)):\n                # ... collect all regions that span an entire line ...\n                region = self.view.full_line(point)\n                regions.append(region)\n                point = region.b\n            for region in reversed(regions):\n                # ... and erase them in reverse order\n                self.view.erase(edit, region)\n", "path": "plugin/core/panels.py"}, {"content": "import sublime\nimport sublime_plugin\nfrom .core.edit import apply_workspace_edit\nfrom .core.edit import parse_workspace_edit\nfrom .core.protocol import Range\nfrom .core.protocol import Request\nfrom .core.registry import get_position\nfrom .core.registry import LspTextCommand\nfrom .core.typing import Any, Optional\nfrom .core.views import range_to_region\nfrom .core.views import text_document_position_params\n\n\nclass RenameSymbolInputHandler(sublime_plugin.TextInputHandler):\n    def __init__(self, view: sublime.View, placeholder: str) -> None:\n        self.view = view\n        self._placeholder = placeholder\n\n    def name(self) -> str:\n        return \"new_name\"\n\n    def placeholder(self) -> str:\n        return self._placeholder\n\n    def initial_text(self) -> str:\n        return self.placeholder()\n\n    def validate(self, name: str) -> bool:\n        return len(name) > 0\n\n\nclass LspSymbolRenameCommand(LspTextCommand):\n\n    capability = 'renameProvider'\n\n    # mypy: Signature of \"is_enabled\" incompatible with supertype \"LspTextCommand\"\n    def is_enabled(  # type: ignore\n        self,\n        new_name: str = \"\",\n        placeholder: str = \"\",\n        position: Optional[int] = None,\n        event: Optional[dict] = None,\n        point: Optional[int] = None\n    ) -> bool:\n        if self.best_session(\"renameProvider.prepareProvider\"):\n            # The language server will tell us if the selection is on a valid token.\n            return True\n        return super().is_enabled(event, point)\n\n    def input(self, args: dict) -> Optional[sublime_plugin.TextInputHandler]:\n        if \"new_name\" not in args:\n            placeholder = args.get(\"placeholder\", \"\")\n            if not placeholder:\n                point = args.get(\"point\")\n                # guess the symbol name\n                if not isinstance(point, int):\n                    point = self.view.sel()[0].b\n                placeholder = self.view.substr(self.view.word(point))\n            return RenameSymbolInputHandler(self.view, placeholder)\n        else:\n            return None\n\n    def run(\n        self,\n        edit: sublime.Edit,\n        new_name: str = \"\",\n        placeholder: str = \"\",\n        position: Optional[int] = None,\n        event: Optional[dict] = None,\n        point: Optional[int] = None\n    ) -> None:\n        if position is None:\n            pos = get_position(self.view, event, point)\n            if new_name:\n                return self._do_rename(pos, new_name)\n            else:\n                session = self.best_session(\"{}.prepareProvider\".format(self.capability))\n                if session:\n                    params = text_document_position_params(self.view, pos)\n                    request = Request.prepareRename(params, self.view)\n                    self.event = event\n                    session.send_request(request, lambda r: self.on_prepare_result(r, pos), self.on_prepare_error)\n                else:\n                    # trigger InputHandler manually\n                    raise TypeError(\"required positional argument\")\n        else:\n            if new_name:\n                return self._do_rename(position, new_name)\n            else:\n                # trigger InputHandler manually\n                raise TypeError(\"required positional argument\")\n\n    def _do_rename(self, position: int, new_name: str) -> None:\n        session = self.best_session(self.capability)\n        if session:\n            params = text_document_position_params(self.view, position)\n            params[\"newName\"] = new_name\n            session.send_request(\n                Request.rename(params, self.view),\n                # This has to run on the main thread due to calling apply_workspace_edit\n                lambda r: sublime.set_timeout(lambda: self.on_rename_result(r))\n            )\n\n    def on_rename_result(self, response: Any) -> None:\n        window = self.view.window()\n        if window:\n            if response:\n                apply_workspace_edit(window, parse_workspace_edit(response))\n            else:\n                window.status_message('Nothing to rename')\n\n    def on_prepare_result(self, response: Any, pos: int) -> None:\n        if response is None:\n            sublime.error_message(\"The current selection cannot be renamed\")\n            return\n        # It must be a dict at this point.\n        if \"placeholder\" in response:\n            placeholder = response[\"placeholder\"]\n            r = response[\"range\"]\n        else:\n            placeholder = self.view.substr(self.view.word(pos))\n            r = response\n        region = range_to_region(Range.from_lsp(r), self.view)\n        args = {\"placeholder\": placeholder, \"position\": region.a, \"event\": self.event}\n        self.view.run_command(\"lsp_symbol_rename\", args)\n\n    def on_prepare_error(self, error: Any) -> None:\n        sublime.error_message(\"Rename error: {}\".format(error[\"message\"]))\n", "path": "plugin/rename.py"}], "after_files": [{"content": "from .typing import Dict, Optional, List, Generator, Tuple\nfrom .types import debounced\nfrom contextlib import contextmanager\nimport sublime\nimport sublime_plugin\n\n\n# about 80 chars per line implies maintaining a buffer of about 40kb per window\nSERVER_PANEL_MAX_LINES = 500\n\n# If nothing else shows up after 80ms, actually print the messages to the panel\nSERVER_PANEL_DEBOUNCE_TIME_MS = 80\n\nOUTPUT_PANEL_SETTINGS = {\n    \"auto_indent\": False,\n    \"draw_indent_guides\": False,\n    \"draw_unicode_white_space\": \"none\",\n    \"draw_white_space\": \"none\",\n    \"fold_buttons\": True,\n    \"gutter\": True,\n    \"is_widget\": True,\n    \"line_numbers\": False,\n    \"lsp_active\": True,\n    \"margin\": 3,\n    \"match_brackets\": False,\n    \"rulers\": [],\n    \"scroll_past_end\": False,\n    \"show_definitions\": False,\n    \"tab_size\": 4,\n    \"translate_tabs_to_spaces\": False,\n    \"word_wrap\": False\n}\n\n\nclass PanelName:\n    Diagnostics = \"diagnostics\"\n    References = \"references\"\n    Rename = \"rename\"\n    LanguageServers = \"language servers\"\n\n\n@contextmanager\ndef mutable(view: sublime.View) -> Generator:\n    view.set_read_only(False)\n    yield\n    view.set_read_only(True)\n\n\ndef create_output_panel(window: sublime.Window, name: str) -> Optional[sublime.View]:\n    panel = window.create_output_panel(name)\n    settings = panel.settings()\n    for key, value in OUTPUT_PANEL_SETTINGS.items():\n        settings.set(key, value)\n    return panel\n\n\ndef destroy_output_panels(window: sublime.Window) -> None:\n    for field in filter(lambda a: not a.startswith('__'), PanelName.__dict__.keys()):\n        panel_name = getattr(PanelName, field)\n        panel = window.find_output_panel(panel_name)\n        if panel and panel.is_valid():\n            panel.settings().set(\"syntax\", \"Packages/Text/Plain text.tmLanguage\")\n            window.destroy_output_panel(panel_name)\n\n\ndef create_panel(window: sublime.Window, name: str, result_file_regex: str, result_line_regex: str,\n                 syntax: str) -> Optional[sublime.View]:\n    panel = create_output_panel(window, name)\n    if not panel:\n        return None\n    if result_file_regex:\n        panel.settings().set(\"result_file_regex\", result_file_regex)\n    if result_line_regex:\n        panel.settings().set(\"result_line_regex\", result_line_regex)\n    panel.assign_syntax(syntax)\n    # Call create_output_panel a second time after assigning the above\n    # settings, so that it'll be picked up as a result buffer\n    # see: Packages/Default/exec.py#L228-L230\n    panel = window.create_output_panel(name)\n    # All our panels are read-only\n    panel.set_read_only(True)\n    return panel\n\n\ndef ensure_panel(window: sublime.Window, name: str, result_file_regex: str, result_line_regex: str,\n                 syntax: str) -> Optional[sublime.View]:\n    return window.find_output_panel(name) or create_panel(window, name, result_file_regex, result_line_regex, syntax)\n\n\nclass LspClearPanelCommand(sublime_plugin.TextCommand):\n    \"\"\"\n    A clear_panel command to clear the error panel.\n    \"\"\"\n\n    def run(self, edit: sublime.Edit) -> None:\n        with mutable(self.view):\n            self.view.erase(edit, sublime.Region(0, self.view.size()))\n\n\nclass LspUpdatePanelCommand(sublime_plugin.TextCommand):\n    \"\"\"\n    A update_panel command to update the error panel with new text.\n    \"\"\"\n\n    def run(self, edit: sublime.Edit, characters: Optional[str] = \"\") -> None:\n        # Clear folds\n        self.view.unfold(sublime.Region(0, self.view.size()))\n\n        with mutable(self.view):\n            self.view.replace(edit, sublime.Region(0, self.view.size()), characters or \"\")\n\n        # Clear the selection\n        selection = self.view.sel()\n        selection.clear()\n\n\ndef ensure_server_panel(window: sublime.Window) -> Optional[sublime.View]:\n    return ensure_panel(window, PanelName.LanguageServers, \"\", \"\", \"Packages/LSP/Syntaxes/ServerLog.sublime-syntax\")\n\n\ndef update_server_panel(window: sublime.Window, prefix: str, message: str) -> None:\n    if not window.is_valid():\n        return\n    window_id = window.id()\n    panel = ensure_server_panel(window)\n    if not panel:\n        return\n    LspUpdateServerPanelCommand.to_be_processed.setdefault(window_id, []).append((prefix, message))\n    previous_length = len(LspUpdateServerPanelCommand.to_be_processed[window_id])\n\n    def condition() -> bool:\n        if not panel:\n            return False\n        if not panel.is_valid():\n            return False\n        to_process = LspUpdateServerPanelCommand.to_be_processed.get(window_id)\n        if to_process is None:\n            return False\n        current_length = len(to_process)\n        if current_length >= 10:\n            # Do not let the queue grow large.\n            return True\n        # If the queue remains stable, flush the messages.\n        return current_length == previous_length\n\n    debounced(\n        lambda: panel.run_command(\"lsp_update_server_panel\", {\"window_id\": window_id}) if panel else None,\n        SERVER_PANEL_DEBOUNCE_TIME_MS,\n        condition\n    )\n\n\nclass LspUpdateServerPanelCommand(sublime_plugin.TextCommand):\n\n    to_be_processed = {}  # type: Dict[int, List[Tuple[str, str]]]\n\n    def run(self, edit: sublime.Edit, window_id: int) -> None:\n        to_process = self.to_be_processed.pop(window_id)\n        with mutable(self.view):\n            for prefix, message in to_process:\n                message = message.replace(\"\\r\\n\", \"\\n\")  # normalize Windows eol\n                self.view.insert(edit, self.view.size(), \"{}: {}\\n\".format(prefix, message))\n                total_lines, _ = self.view.rowcol(self.view.size())\n                point = 0  # Starting from point 0 in the panel ...\n                regions = []  # type: List[sublime.Region]\n            for _ in range(0, max(0, total_lines - SERVER_PANEL_MAX_LINES)):\n                # ... collect all regions that span an entire line ...\n                region = self.view.full_line(point)\n                regions.append(region)\n                point = region.b\n            for region in reversed(regions):\n                # ... and erase them in reverse order\n                self.view.erase(edit, region)\n", "path": "plugin/core/panels.py"}, {"content": "from .core.edit import apply_workspace_edit\nfrom .core.edit import parse_workspace_edit\nfrom .core.edit import TextEdit\nfrom .core.panels import ensure_panel\nfrom .core.panels import PanelName\nfrom .core.protocol import Range\nfrom .core.protocol import Request\nfrom .core.registry import get_position\nfrom .core.registry import LspTextCommand\nfrom .core.registry import windows\nfrom .core.typing import Any, Optional, Dict, List\nfrom .core.views import range_to_region\nfrom .core.views import text_document_position_params\nimport os\nimport sublime\nimport sublime_plugin\n\n\nclass RenameSymbolInputHandler(sublime_plugin.TextInputHandler):\n    def __init__(self, view: sublime.View, placeholder: str) -> None:\n        self.view = view\n        self._placeholder = placeholder\n\n    def name(self) -> str:\n        return \"new_name\"\n\n    def placeholder(self) -> str:\n        return self._placeholder\n\n    def initial_text(self) -> str:\n        return self.placeholder()\n\n    def validate(self, name: str) -> bool:\n        return len(name) > 0\n\n\nclass LspSymbolRenameCommand(LspTextCommand):\n\n    capability = 'renameProvider'\n\n    # mypy: Signature of \"is_enabled\" incompatible with supertype \"LspTextCommand\"\n    def is_enabled(  # type: ignore\n        self,\n        new_name: str = \"\",\n        placeholder: str = \"\",\n        position: Optional[int] = None,\n        event: Optional[dict] = None,\n        point: Optional[int] = None\n    ) -> bool:\n        if self.best_session(\"renameProvider.prepareProvider\"):\n            # The language server will tell us if the selection is on a valid token.\n            return True\n        return super().is_enabled(event, point)\n\n    def input(self, args: dict) -> Optional[sublime_plugin.TextInputHandler]:\n        if \"new_name\" not in args:\n            placeholder = args.get(\"placeholder\", \"\")\n            if not placeholder:\n                point = args.get(\"point\")\n                # guess the symbol name\n                if not isinstance(point, int):\n                    point = self.view.sel()[0].b\n                placeholder = self.view.substr(self.view.word(point))\n            return RenameSymbolInputHandler(self.view, placeholder)\n        else:\n            return None\n\n    def run(\n        self,\n        edit: sublime.Edit,\n        new_name: str = \"\",\n        placeholder: str = \"\",\n        position: Optional[int] = None,\n        event: Optional[dict] = None,\n        point: Optional[int] = None\n    ) -> None:\n        if position is None:\n            pos = get_position(self.view, event, point)\n            if new_name:\n                return self._do_rename(pos, new_name)\n            else:\n                session = self.best_session(\"{}.prepareProvider\".format(self.capability))\n                if session:\n                    params = text_document_position_params(self.view, pos)\n                    request = Request.prepareRename(params, self.view)\n                    self.event = event\n                    session.send_request(request, lambda r: self.on_prepare_result(r, pos), self.on_prepare_error)\n                else:\n                    # trigger InputHandler manually\n                    raise TypeError(\"required positional argument\")\n        else:\n            if new_name:\n                return self._do_rename(position, new_name)\n            else:\n                # trigger InputHandler manually\n                raise TypeError(\"required positional argument\")\n\n    def _do_rename(self, position: int, new_name: str) -> None:\n        session = self.best_session(self.capability)\n        if session:\n            params = text_document_position_params(self.view, position)\n            params[\"newName\"] = new_name\n            session.send_request(\n                Request.rename(params, self.view),\n                # This has to run on the main thread due to calling apply_workspace_edit\n                lambda r: sublime.set_timeout(lambda: self.on_rename_result(r))\n            )\n\n    def on_rename_result(self, response: Any) -> None:\n        window = self.view.window()\n        if window:\n            if response:\n                changes = parse_workspace_edit(response)\n                file_count = len(changes.keys())\n                if file_count > 1:\n                    total_changes = sum(map(len, changes.values()))\n                    message = \"Replace {} occurrences across {} files?\".format(total_changes, file_count)\n                    choice = sublime.yes_no_cancel_dialog(message, \"Replace\", \"Dry Run\")\n                    if choice == sublime.DIALOG_YES:\n                        apply_workspace_edit(window, changes)\n                    elif choice == sublime.DIALOG_NO:\n                        self._render_rename_panel(changes, total_changes, file_count)\n                else:\n                    apply_workspace_edit(window, changes)\n            else:\n                window.status_message('Nothing to rename')\n\n    def on_prepare_result(self, response: Any, pos: int) -> None:\n        if response is None:\n            sublime.error_message(\"The current selection cannot be renamed\")\n            return\n        # It must be a dict at this point.\n        if \"placeholder\" in response:\n            placeholder = response[\"placeholder\"]\n            r = response[\"range\"]\n        else:\n            placeholder = self.view.substr(self.view.word(pos))\n            r = response\n        region = range_to_region(Range.from_lsp(r), self.view)\n        args = {\"placeholder\": placeholder, \"position\": region.a, \"event\": self.event}\n        self.view.run_command(\"lsp_symbol_rename\", args)\n\n    def on_prepare_error(self, error: Any) -> None:\n        sublime.error_message(\"Rename error: {}\".format(error[\"message\"]))\n\n    def _get_relative_path(self, file_path: str) -> str:\n        window = self.view.window()\n        if not window:\n            return file_path\n        base_dir = windows.lookup(window).get_project_path(file_path)\n        if base_dir:\n            return os.path.relpath(file_path, base_dir)\n        else:\n            return file_path\n\n    def _render_rename_panel(self, changes: Dict[str, List[TextEdit]], total_changes: int, file_count: int) -> None:\n        window = self.view.window()\n        if not window:\n            return\n        panel = ensure_rename_panel(window)\n        if not panel:\n            return\n        text = ''\n        for file, file_changes in changes.items():\n            text += '\u25cc {}:\\n'.format(self._get_relative_path(file))\n            for edit in file_changes:\n                start = edit[0]\n                text += '\\t{:>8}:{}\\n'.format(start[0] + 1, start[1] + 1)\n            # append a new line after each file name\n            text += '\\n'\n        base_dir = windows.lookup(window).get_project_path(self.view.file_name() or \"\")\n        panel.settings().set(\"result_base_dir\", base_dir)\n        panel.run_command(\"lsp_clear_panel\")\n        window.run_command(\"show_panel\", {\"panel\": \"output.rename\"})\n        fmt = \"{} changes across {} files. Double-click on a row:col number to jump to that location.\\n\\n{}\"\n        panel.run_command('append', {\n            'characters': fmt.format(total_changes, file_count, text),\n            'force': True,\n            'scroll_to_end': False\n        })\n\n\ndef ensure_rename_panel(window: sublime.Window) -> Optional[sublime.View]:\n    return ensure_panel(\n        window=window,\n        name=PanelName.Rename,\n        result_file_regex=r\"^\\s*\\S\\s+(\\S.*):$\",\n        result_line_regex=r\"^\\s*([0-9]+):([0-9]+)\\s*$\",\n        syntax=\"Packages/LSP/Syntaxes/Rename.sublime-syntax\"\n    )\n", "path": "plugin/rename.py"}]}