parent
4786fe173c
commit
48c71e5bc1
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace LanguageServer\NodeVisitors;
|
||||||
|
|
||||||
|
use PhpParser\{NodeVisitorAbstract, Node};
|
||||||
|
use LanguageServer\Protocol\Position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the Node at a specified position
|
||||||
|
* Depends on ColumnCalculator
|
||||||
|
*/
|
||||||
|
class NodeAtPositionFinder extends NodeVisitorAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The node at the position, if found
|
||||||
|
*
|
||||||
|
* @var Node
|
||||||
|
*/
|
||||||
|
public $node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Position
|
||||||
|
*/
|
||||||
|
private $position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Position $position The position where the node is located
|
||||||
|
*/
|
||||||
|
public function __construct(Position $position)
|
||||||
|
{
|
||||||
|
$this->position = $position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function leaveNode(Node $node)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
!isset($this->node)
|
||||||
|
&& $node->getAttribute('startLine') <= $this->position->line + 1
|
||||||
|
&& $node->getAttribute('endLine') >= $this->position->line + 1
|
||||||
|
&& $node->getAttribute('startColumn') <= $this->position->character + 1
|
||||||
|
&& $node->getAttribute('endColumn') >= $this->position->character + 1
|
||||||
|
) {
|
||||||
|
$this->node = $node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ declare(strict_types = 1);
|
||||||
namespace LanguageServer;
|
namespace LanguageServer;
|
||||||
|
|
||||||
use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position, SymbolKind, TextEdit};
|
use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position, SymbolKind, TextEdit};
|
||||||
use LanguageServer\NodeVisitors\{ReferencesAdder, SymbolFinder, ColumnCalculator};
|
use LanguageServer\NodeVisitors\{NodeAtPositionFinder, ReferencesAdder, SymbolFinder, ColumnCalculator};
|
||||||
use PhpParser\{Error, Comment, Node, ParserFactory, NodeTraverser, Lexer, Parser};
|
use PhpParser\{Error, Comment, Node, ParserFactory, NodeTraverser, Lexer, Parser};
|
||||||
use PhpParser\PrettyPrinter\Standard as PrettyPrinter;
|
use PhpParser\PrettyPrinter\Standard as PrettyPrinter;
|
||||||
use PhpParser\NodeVisitor\NameResolver;
|
use PhpParser\NodeVisitor\NameResolver;
|
||||||
|
@ -104,7 +104,7 @@ class PhpDocument
|
||||||
* Re-parses a source file, updates symbols, reports parsing errors
|
* Re-parses a source file, updates symbols, reports parsing errors
|
||||||
* that may have occured as diagnostics and returns parsed nodes.
|
* that may have occured as diagnostics and returns parsed nodes.
|
||||||
*
|
*
|
||||||
* @return \PhpParser\Node[]
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function parse()
|
public function parse()
|
||||||
{
|
{
|
||||||
|
@ -155,9 +155,9 @@ class PhpDocument
|
||||||
$traverser->traverse($stmts);
|
$traverser->traverse($stmts);
|
||||||
|
|
||||||
$this->symbols = $symbolFinder->symbols;
|
$this->symbols = $symbolFinder->symbols;
|
||||||
}
|
|
||||||
|
|
||||||
return $stmts;
|
$this->stmts = $stmts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,14 +167,13 @@ class PhpDocument
|
||||||
*/
|
*/
|
||||||
public function getFormattedText()
|
public function getFormattedText()
|
||||||
{
|
{
|
||||||
$stmts = $this->parse();
|
if (empty($this->stmts)) {
|
||||||
if (empty($stmts)) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
$prettyPrinter = new PrettyPrinter();
|
$prettyPrinter = new PrettyPrinter();
|
||||||
$edit = new TextEdit();
|
$edit = new TextEdit();
|
||||||
$edit->range = new Range(new Position(0, 0), new Position(PHP_INT_MAX, PHP_INT_MAX));
|
$edit->range = new Range(new Position(0, 0), new Position(PHP_INT_MAX, PHP_INT_MAX));
|
||||||
$edit->newText = $prettyPrinter->prettyPrintFile($stmts);
|
$edit->newText = $prettyPrinter->prettyPrintFile($this->stmts);
|
||||||
return [$edit];
|
return [$edit];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,4 +186,22 @@ class PhpDocument
|
||||||
{
|
{
|
||||||
return $this->content;
|
return $this->content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node at a specified position
|
||||||
|
*
|
||||||
|
* @param Position $position
|
||||||
|
* @return Node|null
|
||||||
|
*/
|
||||||
|
public function getNodeAtPosition(Position $position)
|
||||||
|
{
|
||||||
|
if ($this->stmts === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$traverser = new NodeTraverser;
|
||||||
|
$finder = new NodeAtPositionFinder($position);
|
||||||
|
$traverser->addVisitor($finder);
|
||||||
|
$traverser->traverse($this->stmts);
|
||||||
|
return $finder->node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,9 @@ namespace LanguageServer\Tests\Server;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use LanguageServer\Tests\MockProtocolStream;
|
use LanguageServer\Tests\MockProtocolStream;
|
||||||
use LanguageServer\{LanguageClient, Project};
|
use LanguageServer\{LanguageClient, Project};
|
||||||
use LanguageServer\Protocol\SymbolKind;
|
use LanguageServer\NodeVisitors\NodeAtPositionFinder;
|
||||||
|
use LanguageServer\Protocol\{SymbolKind, Position};
|
||||||
|
use PhpParser\Node;
|
||||||
|
|
||||||
class PhpDocumentTest extends TestCase
|
class PhpDocumentTest extends TestCase
|
||||||
{
|
{
|
||||||
|
@ -67,4 +69,13 @@ class PhpDocumentTest extends TestCase
|
||||||
]
|
]
|
||||||
], json_decode(json_encode($symbols), true));
|
], json_decode(json_encode($symbols), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetNodeAtPosition()
|
||||||
|
{
|
||||||
|
$document = $this->project->getDocument('whatever');
|
||||||
|
$document->updateContent("<?php\n$\$a = new SomeClass;");
|
||||||
|
$node = $document->getNodeAtPosition(new Position(1, 13));
|
||||||
|
$this->assertInstanceOf(Node\Name\FullyQualified::class, $node);
|
||||||
|
$this->assertEquals('SomeClass', (string)$node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue