Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make workspace/willRenameFiles working #2531

Open
wants to merge 70 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
4e8923a
Make it working first
przepompownia Feb 4, 2024
d0e923e
Try to use generator
przepompownia Feb 5, 2024
8ca9325
Merge branch 'master' into fix-will-rename
przepompownia Feb 6, 2024
bc83378
Merge branch 'master' into fix-will-rename
przepompownia Feb 13, 2024
f5649a1
Fix edits in source file
przepompownia Feb 13, 2024
896a7a2
Merge branch 'master' into fix-will-rename
przepompownia Feb 14, 2024
aba4e3b
Merge branch 'master' into fix-will-rename
przepompownia Feb 22, 2024
dcca493
Merge branch 'master' into fix-will-rename
przepompownia Feb 24, 2024
0197e9a
Merge branch 'master' into fix-will-rename
przepompownia Feb 24, 2024
772ce0c
Merge branch 'fix-will-rename' into fix-will-rename-with-gen
przepompownia Feb 25, 2024
2f72e79
Fix TestFileRenamer
przepompownia Feb 25, 2024
b32e8a0
Remove unused import
przepompownia Feb 25, 2024
ca646c7
Fix FileRenamerTest
przepompownia Feb 25, 2024
4d0b4bb
FileRenamerTest: revert intermediate changes
przepompownia Feb 25, 2024
c00e8c0
Add default value
przepompownia Feb 25, 2024
f7fb8a4
Add missing import
przepompownia Feb 25, 2024
b3eab4c
Nullsafe op.
przepompownia Feb 25, 2024
f47b15a
Nullsafe op.
przepompownia Feb 25, 2024
455b61e
Null to string
przepompownia Feb 25, 2024
83aa54d
Null to array
przepompownia Feb 25, 2024
85043dc
Update baseline
przepompownia Feb 25, 2024
b09fa7f
Remove unused import
przepompownia Feb 25, 2024
897bbca
Merge branch 'master' into fix-will-rename
przepompownia Feb 25, 2024
efaf955
Use master fixes of error handling in both rename handlers
przepompownia Feb 25, 2024
9fefcd5
Merge branch 'master' into fix-will-rename
przepompownia Feb 26, 2024
594545b
Rename local variable
przepompownia Feb 27, 2024
41b9a2d
Remove assertion
przepompownia Feb 27, 2024
aefac36
Revert "Rename local variable"
przepompownia Feb 27, 2024
fd42641
Fix renaming
przepompownia Feb 27, 2024
e74770d
Merge branch 'master' into fix-will-rename
przepompownia Feb 27, 2024
970a7e8
Remove unused import
przepompownia Feb 27, 2024
55e2c82
Merge branch 'master' into fix-will-rename
przepompownia Mar 2, 2024
1898cd7
Merge branch 'master' into fix-will-rename
przepompownia Mar 10, 2024
502939e
Merge branch 'master' into fix-will-rename
przepompownia Mar 15, 2024
870c09c
FileRenamer: return Promise<RenameEdit>
przepompownia Mar 16, 2024
e484224
Merge branch 'master' into fix-will-rename-new-model
przepompownia Mar 16, 2024
9db0160
Fix FileRenameHandlerTest
przepompownia Mar 16, 2024
0fb5b64
Fix FileRenamerTest
przepompownia Mar 16, 2024
8555bc2
cs-fixer
przepompownia Mar 16, 2024
c2b7548
phpstan
przepompownia Mar 17, 2024
6177ce0
RenameEdit: only list
przepompownia Mar 17, 2024
8331057
Merge branch 'master-no-phar' into fix-will-rename-remote
przepompownia Mar 18, 2024
b9b2b33
Merge branch 'fix-will-rename-new-model-no-phar' into fix-will-rename…
przepompownia Mar 18, 2024
f630090
Update baseline
przepompownia Mar 17, 2024
288b0f9
Yield the result from Adapter
przepompownia Mar 18, 2024
e3843eb
Remove unused import
przepompownia Mar 18, 2024
f87dd64
Merge branch 'master' into fix-will-rename-remote
przepompownia Mar 19, 2024
8f9ad3d
Merge branch 'master' into fix-will-rename-remote
przepompownia Mar 23, 2024
a015161
Merge branch 'master' into fix-will-rename-remote
przepompownia Mar 29, 2024
86d7adf
Rename `RenameEdit` to `WorkspaceRenameEdit`
przepompownia Mar 29, 2024
d99b20a
fixup! Rename `RenameEdit` to `WorkspaceRenameEdit`
przepompownia Mar 29, 2024
2871419
Rename `RenameEditConverter` to `WorkspaceRenameEditsConverter`
przepompownia Mar 29, 2024
1bf47bd
Convert variadic arguments to docblock typed array
przepompownia Mar 30, 2024
4fbb24b
Fix type in docblock
przepompownia Mar 30, 2024
4640afd
Update baseline
przepompownia Mar 30, 2024
1dc9c48
Merge branch 'master' into fix-will-rename-remote
przepompownia Mar 30, 2024
502da51
Remove redundant array_filter
przepompownia Mar 31, 2024
35e02db
Merge branch 'master' into fix-will-rename-remote
przepompownia Apr 6, 2024
c6880ec
Refactoring:
dantleech Apr 13, 2024
8e7b819
Refactor to make the operation unit the textdocument edits
dantleech Apr 13, 2024
d9fa5c8
Update lib/Rename/Adapter/ClassMover/FileRenamer.php
dantleech Apr 14, 2024
90e0cc0
Update lib/Rename/Model/FileRenamer/TestFileRenamer.php
dantleech Apr 14, 2024
0077bb6
Merge pull request #1 from phpactor/fix-will-rename-dan
przepompownia Apr 14, 2024
0af0c08
Rename variable
przepompownia Apr 14, 2024
aafe0bc
Clean unused import
przepompownia Apr 14, 2024
f3f311b
Fix type
przepompownia Apr 14, 2024
279ad86
Change type assertions after refactor
przepompownia Apr 14, 2024
8267288
Update baseline
przepompownia Apr 14, 2024
2f56e95
Remove unused import
przepompownia Apr 14, 2024
222f576
Add sprintf format
przepompownia Apr 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 34 additions & 10 deletions lib/Extension/LanguageServerRename/Handler/FileRenameHandler.php
Expand Up @@ -4,13 +4,14 @@

use Amp\Promise;
use Phpactor\LanguageServerProtocol\FileOperationOptions;
use Phpactor\LanguageServer\Core\Server\ClientApi;
use Phpactor\Rename\Model\Exception\CouldNotRename;
use Phpactor\Rename\Model\FileRenamer;
use Phpactor\Rename\Model\LocatedTextEditsMap;
use Phpactor\Extension\LanguageServerRename\Util\LocatedTextEditConverter;
use Phpactor\Extension\LanguageServerRename\Util\WorkspaceRenameEditsConverter;
use Phpactor\LanguageServerProtocol\FileOperationFilter;
use Phpactor\LanguageServerProtocol\FileOperationPattern;
use Phpactor\LanguageServerProtocol\FileOperationRegistrationOptions;
use Phpactor\LanguageServerProtocol\FileRename;
use Phpactor\LanguageServerProtocol\RenameFilesParams;
use Phpactor\LanguageServerProtocol\ServerCapabilities;
use Phpactor\LanguageServerProtocol\WorkspaceEdit;
Expand All @@ -21,8 +22,11 @@

class FileRenameHandler implements Handler, CanRegisterCapabilities
{
public function __construct(private FileRenamer $renamer, private LocatedTextEditConverter $converter)
{
public function __construct(
private FileRenamer $renamer,
private WorkspaceRenameEditsConverter $converter,
private ClientApi $clientApi,
) {
}


Expand All @@ -39,14 +43,34 @@ public function methods(): array
public function willRenameFiles(RenameFilesParams $params): Promise
{
return call(function () use ($params) {
$workspaceEdits = LocatedTextEditsMap::create();
foreach ($params->files as $rename) {
assert($rename instanceof FileRename);
$count = 0;
$documentChanges = [];
try {
foreach ($params->files as $rename) {
$locatedEditMap = LocatedTextEditsMap::create();

$workspaceEdits = $workspaceEdits->merge(yield $this->renamer->renameFile(TextDocumentUri::fromString($rename->oldUri), TextDocumentUri::fromString($rename->newUri)));
}
$renameEdit = yield $this->renamer->renameFile(
TextDocumentUri::fromString($rename->oldUri),
TextDocumentUri::fromString($rename->newUri)
);

$workspaceEdit = $this->converter->toWorkspaceEdit($renameEdit);

foreach ($workspaceEdit->documentChanges ?? [] as $change) {
$documentChanges[] = $change;
}
}

return $this->converter->toWorkspaceEdit($workspaceEdits);
return new WorkspaceEdit(documentChanges: $documentChanges);
} catch (CouldNotRename $error) {
$previous = $error->getPrevious();

$this->clientApi->window()->showMessage()->error(sprintf(
$error->getMessage() . ($previous?->getTraceAsString() ?? '')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is sprintf missing a format string? %s %s why do we get the trace from $previous?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied catching CouldNotRename from RenameHandler to have the same way of error handling and don't know what the trace was needed for in the original place:

https://github.com/phpactor/phpactor/blame/a23130918b61c3f45f4a403abe56b5a06be80de9/lib/Extension/LanguageServerRename/Handler/RenameHandler.php#L93

));

return new WorkspaceEdit(null, []);
}
});
}

Expand Down
11 changes: 6 additions & 5 deletions lib/Extension/LanguageServerRename/Handler/RenameHandler.php
Expand Up @@ -8,9 +8,10 @@
use Phpactor\Rename\Model\Exception\CouldNotRename;
use Phpactor\Rename\Model\LocatedTextEdit;
use Phpactor\Rename\Model\LocatedTextEditsMap;
use Phpactor\Rename\Model\WorkspaceRenameEdits;
use Phpactor\Rename\Model\RenameResult;
use Phpactor\Rename\Model\Renamer;
use Phpactor\Extension\LanguageServerRename\Util\LocatedTextEditConverter;
use Phpactor\Extension\LanguageServerRename\Util\WorkspaceRenameEditsConverter;
use Phpactor\LanguageServerProtocol\PrepareRenameParams;
use Phpactor\LanguageServerProtocol\PrepareRenameRequest;
use Phpactor\LanguageServerProtocol\Range;
Expand All @@ -30,7 +31,7 @@
class RenameHandler implements Handler, CanRegisterCapabilities
{
public function __construct(
private LocatedTextEditConverter $converter,
private WorkspaceRenameEditsConverter $converter,
private TextDocumentLocator $documentLocator,
private Renamer $renamer,
private ClientApi $clientApi
Expand Down Expand Up @@ -119,9 +120,9 @@ public function registerCapabiltiies(ServerCapabilities $capabilities): void
*/
private function resultToWorkspaceEdit(array $locatedEdits, ?RenameResult $renameResult): WorkspaceEdit
{
return $this->converter->toWorkspaceEdit(
return $this->converter->toWorkspaceEdit(new WorkspaceRenameEdits(array_filter([
LocatedTextEditsMap::fromLocatedEdits($locatedEdits),
$renameResult
);
$renameResult,
])));
}
}
Expand Up @@ -10,7 +10,7 @@
use Phpactor\Rename\Model\Renamer\ChainRenamer;
use Phpactor\Extension\LanguageServerRename\Handler\RenameHandler;
use Phpactor\Rename\Model\Renamer;
use Phpactor\Extension\LanguageServerRename\Util\LocatedTextEditConverter;
use Phpactor\Extension\LanguageServerRename\Util\WorkspaceRenameEditsConverter;
use Phpactor\Extension\LanguageServer\LanguageServerExtension;
use Phpactor\LanguageServer\Core\Server\ClientApi;
use Phpactor\MapResolver\Resolver;
Expand All @@ -31,7 +31,7 @@ public function load(ContainerBuilder $container): void

$container->register(RenameHandler::class, function (Container $container) {
return new RenameHandler(
$container->get(LocatedTextEditConverter::class),
$container->get(WorkspaceRenameEditsConverter::class),
$container->get(TextDocumentLocator::class),
$container->get(Renamer::class),
$container->get(ClientApi::class)
Expand All @@ -43,14 +43,15 @@ public function load(ContainerBuilder $container): void
$container->register(FileRenameHandler::class, function (Container $container) {
return new FileRenameHandler(
$container->get(FileRenamer::class),
$container->get(LocatedTextEditConverter::class),
$container->get(WorkspaceRenameEditsConverter::class),
$container->get(ClientApi::class)
);
}, [
LanguageServerExtension::TAG_METHOD_HANDLER => []
]);

$container->register(LocatedTextEditConverter::class, function (Container $container) {
return new LocatedTextEditConverter(
$container->register(WorkspaceRenameEditsConverter::class, function (Container $container) {
return new WorkspaceRenameEditsConverter(
$container->get(LanguageServerExtension::SERVICE_SESSION_WORKSPACE),
$container->get(TextDocumentLocator::class),
);
Expand Down
Expand Up @@ -75,7 +75,7 @@ public function load(ContainerBuilder $container): void
]);

$container->register(DefinitionAndReferenceFinder::class, function (Container $container) {
// wrap the definiton and reference finder to update the index with the current workspace
// wrap the definition and reference finder to update the index with the current workspace
return new WorkspaceUpdateReferenceFinder(
$container->get(LanguageServerExtension::SERVICE_SESSION_WORKSPACE),
$container->get(Indexer::class),
Expand All @@ -91,7 +91,7 @@ public function load(ContainerBuilder $container): void
new ClassToFileUriToNameConverter($container->get(ClassToFileExtension::SERVICE_CONVERTER)),
$container->get(TextDocumentLocator::class),
$container->get(QueryClient::class),
$container->get(ClassMover::class)
$container->get(ClassMover::class),
);
return new LoggingFileRenamer(
$renamer,
Expand Down
Expand Up @@ -4,17 +4,22 @@

use Phpactor\Extension\LanguageServerBridge\TextDocument\WorkspaceTextDocumentLocator;
use Phpactor\Extension\LanguageServerRename\Handler\FileRenameHandler;
use Phpactor\Extension\LanguageServerRename\Util\WorkspaceRenameEditsConverter;
use Phpactor\LanguageServer\Core\Server\ClientApi;
use Phpactor\LanguageServer\Core\Server\RpcClient;
use Phpactor\Rename\Model\FileRenamer\TestFileRenamer;
use Phpactor\Rename\Model\LocatedTextEditsMap;
use Phpactor\Extension\LanguageServerRename\Tests\IntegrationTestCase;
use Phpactor\Extension\LanguageServerRename\Util\LocatedTextEditConverter;
use Phpactor\LanguageServerProtocol\FileOperationRegistrationOptions;
use Phpactor\LanguageServerProtocol\FileRename;
use Phpactor\LanguageServerProtocol\RenameFilesParams;
use Phpactor\LanguageServerProtocol\WorkspaceEdit;
use Phpactor\LanguageServer\Core\Rpc\ResponseMessage;
use Phpactor\LanguageServer\LanguageServerTesterBuilder;
use Phpactor\LanguageServer\Test\LanguageServerTester;
use Phpactor\Rename\Model\WorkspaceRenameEdits;
use Phpactor\Rename\Model\RenameResult;
use Phpactor\TextDocument\TextDocumentUri;
use Phpactor\TextDocument\TextEdit;
use Phpactor\TextDocument\TextEdits;
use function Amp\Promise\wait;
Expand Down Expand Up @@ -43,10 +48,18 @@ public function testMoveFileNoEdits(): void

public function testMoveFileEdits(): void
{
$server = $this->createServer(false, [
'file:///file1' => TextEdits::one(TextEdit::create(0, 0, 'Hello')),
'file:///file2' => TextEdits::one(TextEdit::create(0, 0, 'Hello')),
]);
$server = $this->createServer(
false,
[
'file:///file1' => TextEdits::one(TextEdit::create(0, 0, 'Hello')),
'file:///file2' => TextEdits::one(TextEdit::create(0, 0, 'Hello')),
],
new RenameResult(
TextDocumentUri::fromString('file:///file1'),
TextDocumentUri::fromString('file:///file2'),
),
);

$server->initialize();

$response = wait($server->request('workspace/willRenameFiles', new RenameFilesParams([
Expand All @@ -58,28 +71,44 @@ public function testMoveFileEdits(): void
$edits = $response->result;
self::assertInstanceOf(WorkspaceEdit::class, $edits);
assert($edits instanceof WorkspaceEdit);
self::assertCount(2, $edits->documentChanges);
self::assertIsArray($edits->documentChanges);
self::assertCount(3, $edits->documentChanges);
}

private function createServer(bool $willFail = false, array $workspaceEdits = []): LanguageServerTester
{
private function createServer(
bool $willFail = false,
array $workspaceEdits = [],
?RenameResult $renameResult = null,
): LanguageServerTester {
$builder = LanguageServerTesterBuilder::createBare()
->enableTextDocuments()
->enableFileEvents();
$builder->addHandler($this->createHandler($builder, $willFail, $workspaceEdits));
$builder->addHandler($this->createHandler($builder, $willFail, $renameResult, $workspaceEdits));
$server = $builder->build();

foreach ($workspaceEdits as $path => $_) {
$server->textDocument()->open($path, '');
}

return $server;
}

private function createHandler(LanguageServerTesterBuilder $builder, bool $willError = false, array $workspaceEdits = []): FileRenameHandler
{
private function createHandler(
LanguageServerTesterBuilder $builder,
bool $willError = false,
?RenameResult $renameResult = null,
array $workspaceEdits = [],
): FileRenameHandler {
return new FileRenameHandler(
new TestFileRenamer($willError, new LocatedTextEditsMap($workspaceEdits)),
new LocatedTextEditConverter($builder->workspace(), new WorkspaceTextDocumentLocator($builder->workspace()))
new TestFileRenamer(
$willError,
new WorkspaceRenameEdits(array_filter([
new LocatedTextEditsMap($workspaceEdits),
$renameResult,
])),
),
new WorkspaceRenameEditsConverter($builder->workspace(), new WorkspaceTextDocumentLocator($builder->workspace())),
new ClientApi($this->createMock(RpcClient::class)),
);
}
}
Expand Up @@ -5,20 +5,46 @@
use Phpactor\Extension\LanguageServerBridge\Converter\TextEditConverter;
use Phpactor\LanguageServerProtocol\OptionalVersionedTextDocumentIdentifier;
use Phpactor\Rename\Model\LocatedTextEditsMap;
use Phpactor\Rename\Model\WorkspaceRenameEdits;
use Phpactor\Rename\Model\RenameResult;
use Phpactor\LanguageServerProtocol\RenameFile;
use Phpactor\LanguageServerProtocol\TextDocumentEdit;
use Phpactor\LanguageServerProtocol\WorkspaceEdit;
use Phpactor\LanguageServer\Core\Workspace\Workspace;
use Phpactor\TextDocument\TextDocumentLocator;

final class LocatedTextEditConverter
final class WorkspaceRenameEditsConverter
{
public function __construct(private Workspace $workspace, private TextDocumentLocator $locator)
{
}

public function toWorkspaceEdit(LocatedTextEditsMap $map, ?RenameResult $renameResult = null): WorkspaceEdit
public function toWorkspaceEdit(WorkspaceRenameEdits $edits): WorkspaceEdit
{
$documentEdits = [];

foreach ($edits as $edit) {
if ($edit instanceof RenameResult) {
$documentEdits[] = new RenameFile(
'rename',
$edit->oldUri(),
$edit->newUri(),
);
}
if ($edit instanceof LocatedTextEditsMap) {
foreach ($this->prepareDocumentEdits($edit) as $textEdit) {
$documentEdits[] = $textEdit;
}
}
}

return new WorkspaceEdit(null, $documentEdits);
}

/**
* @return TextDocumentEdit[]
*/
private function prepareDocumentEdits(LocatedTextEditsMap $map): array
{
$documentEdits = [];
foreach ($map->toLocatedTextEdits() as $result) {
Expand All @@ -37,29 +63,22 @@ public function toWorkspaceEdit(LocatedTextEditsMap $map, ?RenameResult $renameR

// deduplicate the edits: with renaming we currently have multiple
// references to the declaration.
$documentEdits = array_map(function (TextDocumentEdit $documentEdit) {
$new = [];
foreach ($documentEdit->edits as $edit) {
$new[sprintf(
'%s-%s-%s',
$edit->range->start->line,
$edit->range->start->character,
$edit->newText
)] = $edit;
}
$documentEdit->edits = array_values($new);
return $documentEdit;
}, $documentEdits);

if (null !== $renameResult) {
$documentEdits[] = new RenameFile(
'rename',
$renameResult->oldUri(),
$renameResult->newUri(),
);
}

return new WorkspaceEdit(null, $documentEdits);
return array_map(
function (TextDocumentEdit $documentEdit) {
$new = [];
foreach ($documentEdit->edits as $edit) {
$new[sprintf(
'%s-%s-%s',
$edit->range->start->line,
$edit->range->start->character,
$edit->newText
)] = $edit;
}
$documentEdit->edits = array_values($new);
return $documentEdit;
},
$documentEdits
);
}

private function getDocumentVersion(string $uri): int
Expand Down