Repository: sublimelsp/LSP

Issue:
Wrong placeholder in the rename quick panel
**Describe the bug**

For LSP-intelephense, it seems that the placeholder in the quick panel is the one under the caret rather than the actual symbol which triggers that. The actual renaming operation is done right though.

Unfortunately `Rename` is a premium feature in intelephense... and I can't reproduce this with LSP-pyright... weird.


**To Reproduce**

```php
<?php

class Foo
{
    public static function getInstance()
    {
        return new static();
    }

    public function abcd()
    {
        echo 'haha';
    }
}

Foo::getInstance()->abcd();
```

Steps to reproduce the behavior:
1. Place caret on `haha`
2. Hover on `bar`
3. Click `Rename` on the popup
4. `haha` will be in the shown quick panel

**Expected behavior**

It should be `bar` in the shown panel.

**Screenshots**

Video recording: https://streamable.com/bw762h

**Environment (please complete the following information):**
- OS: Win7 x64
- Sublime Text version: 4090
- LSP version: the latest commit on `st4000-exploration` 653fd3c4e25c2ed5294f76b0b8b5db79f56f18c2 
- Language servers used: intelephense

**Additional context**

I see the server communication log but I didn't see any "line 11" in it but they are all correct "line 15".

LSP log:

```
:: --> LSP-intelephense textDocument/hover(87): {'position': {'character': 23, 'line': 15}, 'textDocument': {'uri': 'file:///E:/_Test/php/src/test.php'}}
:: <<< LSP-intelephense 87: {'range': {'start': {'character': 20, 'line': 15}, 'end': {'character': 24, 'line': 15}}, 'contents': {'kind': 'markdown', 'value': '__Foo::abcd__\n\n```php\n<?php\npublic function abcd() { }\n```\n\n_@return_ `void`'}}
:: --> LSP-intelephense textDocument/prepareRename(88): {'position': {'character': 23, 'line': 15}, 'textDocument': {'uri': 'file:///E:/_Test/php/src/test.php'}}
:: <<< LSP-intelephense 88: {'start': {'character': 20, 'line': 15}, 'end': {'character': 24, 'line': 15}}
```


Discussion:
The difference is that intelephense is a prepareRenameProvider, while pyright is not.

Resolving patch:
diff --git a/plugin/rename.py b/plugin/rename.py
--- a/plugin/rename.py
+++ b/plugin/rename.py
@@ -20,9 +20,7 @@ def name(self) -> str:
         return "new_name"
 
     def placeholder(self) -> str:
-        if self._placeholder:
-            return self._placeholder
-        return self.get_current_symbol_name()
+        return self._placeholder
 
     def initial_text(self) -> str:
         return self.placeholder()
@@ -30,14 +28,6 @@ def initial_text(self) -> str:
     def validate(self, name: str) -> bool:
         return len(name) > 0
 
-    def get_current_symbol_name(self) -> str:
-        pos = get_position(self.view)
-        current_name = self.view.substr(self.view.word(pos))
-        # Is this check necessary?
-        if not current_name:
-            current_name = ""
-        return current_name
-
 
 class LspSymbolRenameCommand(LspTextCommand):
 
@@ -87,7 +77,7 @@ def run(
                     params = text_document_position_params(self.view, pos)
                     request = Request.prepareRename(params, self.view)
                     self.event = event
-                    session.send_request(request, self.on_prepare_result, self.on_prepare_error)
+                    session.send_request(request, lambda r: self.on_prepare_result(r, pos), self.on_prepare_error)
                 else:
                     # trigger InputHandler manually
                     raise TypeError("required positional argument")
@@ -117,7 +107,7 @@ def on_rename_result(self, response: Any) -> None:
             else:
                 window.status_message('Nothing to rename')
 
-    def on_prepare_result(self, response: Any) -> None:
+    def on_prepare_result(self, response: Any, pos: int) -> None:
         if response is None:
             sublime.error_message("The current selection cannot be renamed")
             return
@@ -126,7 +116,7 @@ def on_prepare_result(self, response: Any) -> None:
             placeholder = response["placeholder"]
             r = response["range"]
         else:
-            placeholder = ""
+            placeholder = self.view.substr(self.view.word(pos))
             r = response
         region = range_to_region(Range.from_lsp(r), self.view)
         args = {"placeholder": placeholder, "position": region.a, "event": self.event}


Test patch: