1
0
Fork 0

Created SymbolInformation,Range and Location factories

pull/661/head
dantleech 2018-07-29 15:26:38 +01:00 committed by Daniel Leech
parent 49eada5da8
commit 641b1c2907
8 changed files with 171 additions and 7 deletions

View File

@ -4,6 +4,7 @@ declare(strict_types = 1);
namespace LanguageServer;
use LanguageServer\Index\ReadableIndex;
use LanguageServer\ProtocolBridge\SymbolInformationFactory;
use LanguageServer\Protocol\SymbolInformation;
use Microsoft\PhpParser;
use Microsoft\PhpParser\Node;
@ -36,12 +37,19 @@ class DefinitionResolver
private $docBlockFactory;
/**
* Creates SignatureInformation
* Creates SignatureInformation instances
*
* @var SignatureInformationFactory
*/
private $signatureInformationFactory;
/**
* Creates SymbolInformation instances
*
* @var SymbolInformationFactory
*/
private $symbolInformationFactory;
/**
* @param ReadableIndex $index
*/
@ -51,6 +59,7 @@ class DefinitionResolver
$this->typeResolver = new TypeResolver;
$this->docBlockFactory = DocBlockFactory::createInstance();
$this->signatureInformationFactory = new SignatureInformationFactory($this);
$this->symbolInformationFactory = new SymbolInformationFactory();
}
/**
@ -233,7 +242,7 @@ class DefinitionResolver
}
}
$def->symbolInformation = SymbolInformation::fromNode($node, $fqn);
$def->symbolInformation = $this->symbolInformationFactory->fromNode($node, $fqn);
if ($def->symbolInformation !== null) {
$def->type = $this->getTypeFromNode($node);

View File

@ -7,11 +7,11 @@ use LanguageServer\Protocol\{
ServerCapabilities,
ClientCapabilities,
TextDocumentSyncKind,
Message,
InitializeResult,
CompletionOptions,
SignatureHelpOptions
};
use LanguageServer\ProtocolBridge\Message;
use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder};
use LanguageServer\ContentRetriever\{ContentRetriever, ClientContentRetriever, FileSystemContentRetriever};
use LanguageServer\Index\{DependenciesIndex, GlobalIndex, Index, ProjectIndex, StubsIndex};

View File

@ -0,0 +1,32 @@
<?php
namespace LanguageServer\ProtocolBridge;
use LanguageServer\Protocol\Location;
use LanguageServer\Protocol\Position;
use LanguageServer\Protocol\Range;
use Microsoft\PhpParser\Node;
use Microsoft\PhpParser\PositionUtilities;
class LocationFactory
{
/**
* Returns the location of the node
*
* @param Node $node
* @return self
*/
public static function fromNode(Node $node): Location
{
$range = PositionUtilities::getRangeFromPosition(
$node->getStart(),
$node->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)
));
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace LanguageServer\ProtocolBridge;
use LanguageServer\Protocol\Position;
use LanguageServer\Protocol\Range;
use Microsoft\PhpParser\Node;
use Microsoft\PhpParser\PositionUtilities;
class RangeFactory
{
/**
* Returns the range the node spans
*
* @param Node $node
* @return self
*/
public static function fromNode(Node $node)
{
$range = PositionUtilities::getRangeFromPosition(
$node->getStart(),
$node->getWidth(),
$node->getFileContents()
);
return new Range(
new Position($range->start->line, $range->start->character),
new Position($range->end->line, $range->end->character)
);
}
}

View File

@ -0,0 +1,88 @@
<?php
namespace LanguageServer\ProtocolBridge;
use LanguageServer\Protocol\Location;
use LanguageServer\Protocol\SymbolInformation;
use LanguageServer\Protocol\SymbolKind;
class SymbolInformationFactory
{
/**
* Converts a Node to a SymbolInformation
*
* @param Node $node
* @param string $fqn If given, $containerName will be extracted from it
* @return SymbolInformation|null
*/
public function fromNode($node, string $fqn = null)
{
$symbol = new SymbolInformation();
if ($node instanceof Node\Statement\ClassDeclaration) {
$symbol->kind = SymbolKind::CLASS_;
} else if ($node instanceof Node\Statement\TraitDeclaration) {
$symbol->kind = SymbolKind::CLASS_;
} else if (\LanguageServer\ParserHelpers\isConstDefineExpression($node)) {
// constants with define() like
// define('TEST_DEFINE_CONSTANT', false);
$symbol->kind = SymbolKind::CONSTANT;
$symbol->name = $node->argumentExpressionList->children[0]->expression->getStringContentsText();
} else if ($node instanceof Node\Statement\InterfaceDeclaration) {
$symbol->kind = SymbolKind::INTERFACE;
} else if ($node instanceof Node\Statement\NamespaceDefinition) {
$symbol->kind = SymbolKind::NAMESPACE;
} else if ($node instanceof Node\Statement\FunctionDeclaration) {
$symbol->kind = SymbolKind::FUNCTION;
} else if ($node instanceof Node\MethodDeclaration) {
$nameText = $node->getName();
if ($nameText === '__construct' || $nameText === '__destruct') {
$symbol->kind = SymbolKind::CONSTRUCTOR;
} else {
$symbol->kind = SymbolKind::METHOD;
}
} else if ($node instanceof Node\Expression\Variable && $node->getFirstAncestor(Node\PropertyDeclaration::class) !== null) {
$symbol->kind = SymbolKind::PROPERTY;
} else if ($node instanceof Node\ConstElement) {
$symbol->kind = SymbolKind::CONSTANT;
} else if (
(
($node instanceof Node\Expression\AssignmentExpression)
&& $node->leftOperand instanceof Node\Expression\Variable
)
|| $node instanceof Node\UseVariableName
|| $node instanceof Node\Parameter
) {
$symbol->kind = SymbolKind::VARIABLE;
} else {
return null;
}
if ($node instanceof Node\Expression\AssignmentExpression) {
if ($node->leftOperand instanceof Node\Expression\Variable) {
$symbol->name = $node->leftOperand->getName();
} elseif ($node->leftOperand instanceof PhpParser\Token) {
$symbol->name = trim($node->leftOperand->getText($node->getFileContents()), "$");
}
} else if ($node instanceof Node\UseVariableName) {
$symbol->name = $node->getName();
} else if (isset($node->name)) {
if ($node->name instanceof Node\QualifiedName) {
$symbol->name = (string)PhpParser\ResolvedName::buildName($node->name->nameParts, $node->getFileContents());
} else {
$symbol->name = ltrim((string)$node->name->getText($node->getFileContents()), "$");
}
} else if (isset($node->variableName)) {
$symbol->name = $node->variableName->getText($node);
} else if (!isset($symbol->name)) {
return null;
}
$symbol->location = LocationFactory::fromNode($node);
if ($fqn !== null) {
$parts = preg_split('/(::|->|\\\\)/', $fqn);
array_pop($parts);
$symbol->containerName = implode('\\', $parts);
}
return $symbol;
}
}

View File

@ -7,6 +7,8 @@ use LanguageServer\{
CompletionProvider, SignatureHelpProvider, LanguageClient, PhpDocument, PhpDocumentLoader, DefinitionResolver
};
use LanguageServer\Index\ReadableIndex;
use LanguageServer\ProtocolBridge\LocationFactory;
use LanguageServer\ProtocolBridge\RangeFactory;
use LanguageServer\Protocol\{
FormattingOptions,
Hover,
@ -233,7 +235,7 @@ class TextDocument
$refs = $document->getReferenceNodesByFqn($fqn);
if ($refs !== null) {
foreach ($refs as $ref) {
$locations[] = Location::fromNode($ref);
$locations[] = LocationFactory::fromNode($ref);
}
}
}
@ -332,7 +334,7 @@ class TextDocument
}
yield waitForEvent($this->index, 'definition-added');
}
$range = Range::fromNode($node);
$range = RangeFactory::fromNode($node);
if ($def === null) {
return new Hover([], $range);
}

View File

@ -5,6 +5,7 @@ namespace LanguageServer\Server;
use LanguageServer\{LanguageClient, PhpDocumentLoader};
use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index};
use LanguageServer\ProtocolBridge\LocationFactory;
use LanguageServer\Protocol\{
FileChangeType,
FileEvent,
@ -150,7 +151,7 @@ class Workspace
$doc = yield $this->documentLoader->getOrLoad($uri);
foreach ($doc->getReferenceNodesByFqn($fqn) as $node) {
$refInfo = new ReferenceInformation;
$refInfo->reference = Location::fromNode($node);
$refInfo->reference = LocationFactory::fromNode($node);
$refInfo->symbol = $query;
$refInfos[] = $refInfo;
}

View File

@ -3,6 +3,7 @@ declare(strict_types = 1);
namespace LanguageServer;
use LanguageServer\ProtocolBridge\RangeFactory;
use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position};
use phpDocumentor\Reflection\DocBlockFactory;
use Microsoft\PhpParser;
@ -100,7 +101,7 @@ class TreeAnalyzer
if ($method && $method->isStatic()) {
$this->diagnostics[] = new Diagnostic(
"\$this can not be used in static methods.",
Range::fromNode($node),
RangeFactory::fromNode($node),
null,
DiagnosticSeverity::ERROR,
'php'