From 207c6a2a682bf87ce8af971233f2574a4dd7a900 Mon Sep 17 00:00:00 2001 From: Florian Schunk Date: Fri, 11 Oct 2019 21:30:14 +0200 Subject: [PATCH] add rename functionality --- src/Factory/LocationFactory.php | 21 ++++++++++++++++ src/Server/TextDocument.php | 43 ++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/Factory/LocationFactory.php b/src/Factory/LocationFactory.php index 3ccc80b..01329d6 100644 --- a/src/Factory/LocationFactory.php +++ b/src/Factory/LocationFactory.php @@ -6,6 +6,7 @@ use LanguageServerProtocol\Location; use LanguageServerProtocol\Position; use LanguageServerProtocol\Range; use Microsoft\PhpParser\Node; +use Microsoft\PhpParser\Token; use Microsoft\PhpParser\PositionUtilities; class LocationFactory @@ -29,4 +30,24 @@ class LocationFactory new Position($range->end->line, $range->end->character) )); } + + /** + * Returns the location of the token + * + * @param Token $node + * @return self + */ + public static function fromToken(Node $node, Token $token): Location + { + $range = PositionUtilities::getRangeFromPosition( + $token->getStartPosition(), + $token->getWidth(), + $node->getFileContents() + ); + + return new Location($node->getUri(), new Range( + new Position($range->start->line, $range->start->character), + new Position($range->end->line, $range->end->character) + )); + } } diff --git a/src/Server/TextDocument.php b/src/Server/TextDocument.php index 039ff57..2273c29 100644 --- a/src/Server/TextDocument.php +++ b/src/Server/TextDocument.php @@ -23,6 +23,8 @@ use LanguageServerProtocol\{ TextDocumentIdentifier, TextDocumentItem, VersionedTextDocumentIdentifier, + WorkspaceEdit, + TextEdit, CompletionContext }; use Microsoft\PhpParser\Node; @@ -179,7 +181,7 @@ class TextDocument TextDocumentIdentifier $textDocument, Position $position ): Promise { - return coroutine(function () use ($textDocument, $position) { + return coroutine(function () use ($context, $textDocument, $position) { $document = yield $this->documentLoader->getOrLoad($textDocument->uri); $node = $document->getNodeAtPosition($position); if ($node === null) { @@ -211,6 +213,9 @@ class TextDocument $descendantNode->getName() === $node->getName() ) { $locations[] = LocationFactory::fromNode($descendantNode); + } else if (($descendantNode instanceof Node\Parameter) + && $context->includeDeclaration && $descendantNode->getName() === $node->getName() ) { + $locations[] = LocationFactory::fromToken($descendantNode, $descendantNode->variableName); } } } else { @@ -245,6 +250,42 @@ class TextDocument }); } + /** + * The rename request is sent from the client to the server to perform a workspace-wide rename of a symbol. + * + * @param TextDocumentIdentifier $textDocument The document to rename in. + * @param Position $position The position at which this request was sent. + * @param string $newName The new name of the symbol. + * @return Promise + */ + public function rename( + TextDocumentIdentifier $textDocument, + Position $position, + string $newName + ) : Promise { + return coroutine( function () use ($textDocument, $position, $newName) { + $document = yield $this->documentLoader->getOrLoad($textDocument->uri); + $node = $document->getNodeAtPosition($position); + if ( + $node instanceof Node\Expression\Variable || + $node instanceof Node\Parameter + ) { + $newName = '$' . $newName; + } + $locations = yield $this->references(new ReferenceContext(true), $textDocument, $position); + $edits = [$textDocument->uri => [] ]; + foreach ($locations as $location) { + $textEdit = new TextEdit($location->range, $newName); + if (!isset($edits[$location->uri])) { + $edits[$location->uri] = []; + } + $edits[$location->uri][] = $textEdit; + } + return new WorkspaceEdit($edits); + }); + } + + /** * The signature help request is sent from the client to the server to request signature information at a given * cursor position.