Skip to content

Go to definition support #49

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

Merged
merged 13 commits into from
Oct 9, 2016
Merged
24 changes: 24 additions & 0 deletions fixtures/references.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace TestNamespace;

$obj = new TestClass();
$obj->testMethod();
echo $obj->testProperty;
TestClass::staticTestMethod();
echo TestClass::$staticTestProperty;
echo TestClass::TEST_CLASS_CONST;
test_function();

$var = 123;
echo $var;

function whatever(TestClass $param): TestClass {
echo $param;
}

$fn = function() use ($var) {
echo $var;
};

echo TEST_CONST;
32 changes: 31 additions & 1 deletion fixtures/symbols.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@

namespace TestNamespace;

class TestClass
const TEST_CONST = 123;

class TestClass implements TestInterface
{
const TEST_CLASS_CONST = 123;
public static $staticTestProperty;
public $testProperty;

public static function staticTestMethod()
{

}

public function testMethod($testParameter)
{
$testVariable = 123;
Expand All @@ -21,3 +30,24 @@ interface TestInterface
{

}

function test_function()
{

}

new class {
const TEST_CLASS_CONST = 123;
public static $staticTestProperty;
public $testProperty;

public static function staticTestMethod()
{

}

public function testMethod($testParameter)
{
$testVariable = 123;
}
};
6 changes: 6 additions & 0 deletions fixtures/use.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

namespace SecondTestNamespace;

use TestNamespace\TestClass;
use TestNamespace\{TestTrait, TestInterface};
3 changes: 3 additions & 0 deletions src/LanguageServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ public function initialize(int $processId, ClientCapabilities $capabilities, str
$serverCapabilities->workspaceSymbolProvider = true;
// Support "Format Code"
$serverCapabilities->documentFormattingProvider = true;
// Support "Go to definition"
$serverCapabilities->definitionProvider = true;

return new InitializeResult($serverCapabilities);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
declare(strict_types = 1);

namespace LanguageServer;
namespace LanguageServer\NodeVisitor;

use PhpParser\{NodeVisitorAbstract, Node};

Expand Down
28 changes: 28 additions & 0 deletions src/NodeVisitor/DefinitionCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types = 1);

namespace LanguageServer\NodeVisitor;

use PhpParser\{NodeVisitorAbstract, Node};

/**
* Collects definitions of classes, interfaces, traits, methods, properties and constants
* Depends on ReferencesAdder and NameResolver
*/
class DefinitionCollector extends NodeVisitorAbstract
{
/**
* Map from fully qualified name (FQN) to Node
*
* @var Node[]
*/
public $definitions = [];

public function enterNode(Node $node)
{
$fqn = $node->getAttribute('ownerDocument')->getDefinedFqn($node);
if ($fqn !== null) {
$this->definitions[$fqn] = $node;
}
}
}
47 changes: 47 additions & 0 deletions src/NodeVisitor/NodeAtPositionFinder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
declare(strict_types = 1);

namespace LanguageServer\NodeVisitor;

use PhpParser\{NodeVisitorAbstract, Node};
use LanguageServer\Protocol\{Position, Range};

/**
* 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)
{
$range = Range::fromNode($node);
// Workaround for https://github.com/nikic/PHP-Parser/issues/311
$parent = $node->getAttribute('parentNode');
if (isset($parent) && $parent instanceof Node\Stmt\GroupUse && $parent->prefix === $node) {
return;
}
if (!isset($this->node) && $range->includes($this->position)) {
$this->node = $node;
}
}
}
55 changes: 55 additions & 0 deletions src/NodeVisitor/ReferencesAdder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
declare(strict_types = 1);

namespace LanguageServer\NodeVisitor;

use PhpParser\{NodeVisitorAbstract, Node};
use LanguageServer\Protocol\{SymbolInformation, SymbolKind, Range, Position, Location};

/**
* Decorates all nodes with parent and sibling references (similar to DOM nodes)
*/
class ReferencesAdder extends NodeVisitorAbstract
{
/**
* @var Node[]
*/
private $stack = [];

/**
* @var Node
*/
private $previous;

/**
* @var mixed
*/
private $document;

/**
* @param mixed $document The value for the ownerDocument attribute
*/
public function __construct($document = null)
{
$this->document = $document;
}

public function enterNode(Node $node)
{
$node->setAttribute('ownerDocument', $this->document);
if (!empty($this->stack)) {
$node->setAttribute('parentNode', end($this->stack));
}
if (isset($this->previous) && $this->previous->getAttribute('parentNode') === $node->getAttribute('parentNode')) {
$node->setAttribute('previousSibling', $this->previous);
$this->previous->setAttribute('nextSibling', $node);
}
$this->stack[] = $node;
}

public function leaveNode(Node $node)
{
$this->previous = $node;
array_pop($this->stack);
}
}
Loading