Skip to content

Hover #50

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 5 commits into from
Oct 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions fixtures/global_references.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
$var = 123;
echo $var;

/**
* Aute duis elit reprehenderit tempor cillum proident anim laborum eu laboris reprehenderit ea incididunt.
*
* @param TestClass $param Adipisicing non non cillum sint incididunt cillum enim mollit.
* @return TestClass
*/
function whatever(TestClass $param): TestClass {
echo $param;
}
Expand Down
45 changes: 45 additions & 0 deletions fixtures/global_symbols.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,59 @@



/**
* Esse commodo excepteur pariatur Lorem est aute incididunt reprehenderit.
*
* @var int
*/
const TEST_CONST = 123;

/**
* Pariatur ut laborum tempor voluptate consequat ea deserunt.
*
* Deserunt enim minim sunt sint ea nisi. Deserunt excepteur tempor id nostrud
* laboris commodo ad commodo velit mollit qui non officia id. Nulla duis veniam
* veniam officia deserunt et non dolore mollit ea quis eiusmod sit non. Occaecat
* consequat sunt culpa exercitation pariatur id reprehenderit nisi incididunt Lorem
* sint. Officia culpa pariatur laborum nostrud cupidatat consequat mollit.
*/
class TestClass implements TestInterface
{
/**
* Anim labore veniam consectetur laboris minim quis aute aute esse nulla ad.
*
* @var int
*/
const TEST_CLASS_CONST = 123;

/**
* Lorem excepteur officia sit anim velit veniam enim.
*
* @var TestClass
*/
public static $staticTestProperty;

/**
* Reprehenderit magna velit mollit ipsum do.
*
* @var TestClass
*/
public $testProperty;

/**
* Do magna consequat veniam minim proident eiusmod incididunt aute proident.
*/
public static function staticTestMethod()
{

}

/**
* Non culpa nostrud mollit esse sunt laboris in irure ullamco cupidatat amet.
*
* @param TestClass $testParameter Lorem sunt velit incididunt mollit
* @return TestClass
*/
public function testMethod($testParameter)
{
$testVariable = 123;
Expand All @@ -31,6 +71,11 @@ interface TestInterface

}

/**
* Officia aliquip adipisicing et nulla et laboris dolore labore.
*
* @return void
*/
function test_function()
{

Expand Down
6 changes: 6 additions & 0 deletions fixtures/references.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
$var = 123;
echo $var;

/**
* Aute duis elit reprehenderit tempor cillum proident anim laborum eu laboris reprehenderit ea incididunt.
*
* @param TestClass $param Adipisicing non non cillum sint incididunt cillum enim mollit.
* @return TestClass
*/
function whatever(TestClass $param): TestClass {
echo $param;
}
Expand Down
45 changes: 45 additions & 0 deletions fixtures/symbols.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,59 @@

namespace TestNamespace;

/**
* Esse commodo excepteur pariatur Lorem est aute incididunt reprehenderit.
*
* @var int
*/
const TEST_CONST = 123;

/**
* Pariatur ut laborum tempor voluptate consequat ea deserunt.
*
* Deserunt enim minim sunt sint ea nisi. Deserunt excepteur tempor id nostrud
* laboris commodo ad commodo velit mollit qui non officia id. Nulla duis veniam
* veniam officia deserunt et non dolore mollit ea quis eiusmod sit non. Occaecat
* consequat sunt culpa exercitation pariatur id reprehenderit nisi incididunt Lorem
* sint. Officia culpa pariatur laborum nostrud cupidatat consequat mollit.
*/
class TestClass implements TestInterface
{
/**
* Anim labore veniam consectetur laboris minim quis aute aute esse nulla ad.
*
* @var int
*/
const TEST_CLASS_CONST = 123;

/**
* Lorem excepteur officia sit anim velit veniam enim.
*
* @var TestClass
*/
public static $staticTestProperty;

/**
* Reprehenderit magna velit mollit ipsum do.
*
* @var TestClass
*/
public $testProperty;

/**
* Do magna consequat veniam minim proident eiusmod incididunt aute proident.
*/
public static function staticTestMethod()
{

}

/**
* Non culpa nostrud mollit esse sunt laboris in irure ullamco cupidatat amet.
*
* @param TestClass $testParameter Lorem sunt velit incididunt mollit
* @return TestClass
*/
public function testMethod($testParameter)
{
$testVariable = 123;
Expand All @@ -31,6 +71,11 @@ interface TestInterface

}

/**
* Officia aliquip adipisicing et nulla et laboris dolore labore.
*
* @return void
*/
function test_function()
{

Expand Down
2 changes: 2 additions & 0 deletions src/LanguageServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public function initialize(int $processId, ClientCapabilities $capabilities, str
$serverCapabilities->definitionProvider = true;
// Support "Find all references"
$serverCapabilities->referencesProvider = true;
// Support "Hover"
$serverCapabilities->hoverProvider = true;

return new InitializeResult($serverCapabilities);
}
Expand Down
84 changes: 84 additions & 0 deletions src/NodeVisitor/DocBlockParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php
declare(strict_types = 1);

namespace LanguageServer\NodeVisitor;

use PhpParser;
use PhpParser\{NodeVisitorAbstract, Node, Comment};
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\Types\Context;
use Exception;

/**
* Decorates all nodes with a docBlock attribute that is an instance of phpDocumentor\Reflection\DocBlock
*/
class DocBlockParser extends NodeVisitorAbstract
{
/**
* @var DocBlockFactory
*/
private $docBlockFactory;

/**
* The current namespace context
*
* @var string
*/
private $namespace;

/**
* Namespace aliases in the current context
*
* @var string[]
*/
private $aliases;

/**
* @var PhpParser\Error[]
*/
public $errors = [];

public function __construct(DocBlockFactory $docBlockFactory)
{
$this->docBlockFactory = $docBlockFactory;
}

public function beforeTraverse(array $nodes)
{
$this->namespace = '';
$this->aliases = [];
}

public function enterNode(Node $node)
{
if ($node instanceof Node\Stmt\Namespace_) {
$this->namespace = (string)$node->name;
} else if ($node instanceof Node\Stmt\UseUse) {
$this->aliases[(string)$node->name] = $node->alias;
}
$docComment = $node->getDocComment();
if ($docComment === null) {
return;
}
$context = new Context($this->namespace, $this->aliases);
try {
$docBlock = $this->docBlockFactory->create($docComment->getText(), $context);
$node->setAttribute('docBlock', $docBlock);
} catch (Exception $e) {
$this->errors[] = new PhpParser\Error($e->getMessage(), [
'startFilePos' => $docComment->getFilePos(),
'endFilePos' => $docComment->getFilePos() + strlen($docComment->getText()),
'startLine' => $docComment->getLine(),
'endLine' => $docComment->getLine() + preg_match_all('/[\\n\\r]/', $docComment->getText()) + 1
]);
}
}

public function leaveNode(Node $node)
{
if ($node instanceof Node\Stmt\Namespace_) {
$this->namespace = '';
$this->aliases = [];
}
}
}
48 changes: 30 additions & 18 deletions src/PhpDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
use LanguageServer\NodeVisitor\{
NodeAtPositionFinder,
ReferencesAdder,
DocBlockParser,
DefinitionCollector,
ColumnCalculator,
ReferencesCollector,
VariableReferencesCollector
};
use PhpParser\{Error, Node, NodeTraverser, Parser};
use PhpParser\NodeVisitor\NameResolver;
use phpDocumentor\Reflection\DocBlockFactory;

class PhpDocument
{
Expand All @@ -40,6 +42,13 @@ class PhpDocument
*/
private $parser;

/**
* The DocBlockFactory instance to parse docblocks
*
* @var DocBlockFactory
*/
private $docBlockFactory;

/**
* The URI of the document
*
Expand Down Expand Up @@ -76,18 +85,20 @@ class PhpDocument
private $references;

/**
* @param string $uri The URI of the document
* @param string $content The content of the document
* @param Project $project The Project this document belongs to (to register definitions etc)
* @param LanguageClient $client The LanguageClient instance (to report errors etc)
* @param Parser $parser The PHPParser instance
* @param string $uri The URI of the document
* @param string $content The content of the document
* @param Project $project The Project this document belongs to (to register definitions etc)
* @param LanguageClient $client The LanguageClient instance (to report errors etc)
* @param Parser $parser The PHPParser instance
* @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks
*/
public function __construct(string $uri, string $content, Project $project, LanguageClient $client, Parser $parser)
public function __construct(string $uri, string $content, Project $project, LanguageClient $client, Parser $parser, DocBlockFactory $docBlockFactory)
{
$this->uri = $uri;
$this->project = $project;
$this->client = $client;
$this->parser = $parser;
$this->docBlockFactory = $docBlockFactory;
$this->updateContent($content);
}

Expand Down Expand Up @@ -127,19 +138,8 @@ public function updateContent(string $content)

$diagnostics = [];
foreach ($errors as $error) {
$diagnostic = new Diagnostic();
$startLine = max($error->getStartLine() - 1, 0);
$startColumn = $error->hasColumnInfo() ? $error->getStartColumn($this->content) - 1 : 0;
$endLine = max($error->getEndLine() - 1, $startLine);
$endColumn = $error->hasColumnInfo() ? $error->getEndColumn($this->content) : 0;
$diagnostic->range = new Range(new Position($startLine, $startColumn), new Position($endLine, $endColumn));
$diagnostic->severity = DiagnosticSeverity::ERROR;
$diagnostic->source = 'php';
// Do not include "on line ..." in the error message
$diagnostic->message = $error->getRawMessage();
$diagnostics[] = $diagnostic;
$diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::ERROR, 'php');
}
$this->client->textDocument->publishDiagnostics($this->uri, $diagnostics);

// $stmts can be null in case of a fatal parsing error
if ($stmts) {
Expand All @@ -154,7 +154,17 @@ public function updateContent(string $content)
// Add column attributes to nodes
$traverser->addVisitor(new ColumnCalculator($content));

// Parse docblocks and add docBlock attributes to nodes
$docBlockParser = new DocBlockParser($this->docBlockFactory);
$traverser->addVisitor($docBlockParser);

$traverser->traverse($stmts);

// Report errors from parsing docblocks
foreach ($docBlockParser->errors as $error) {
$diagnostics[] = Diagnostic::fromError($error, $this->content, DiagnosticSeverity::WARNING, 'php');
}

$traverser = new NodeTraverser;

// Collect all definitions
Expand All @@ -181,6 +191,8 @@ public function updateContent(string $content)

$this->stmts = $stmts;
}

$this->client->textDocument->publishDiagnostics($this->uri, $diagnostics);
}

/**
Expand Down
Loading