Created SymbolInformation,Range and Location factories
parent
49eada5da8
commit
641b1c2907
|
@ -4,6 +4,7 @@ declare(strict_types = 1);
|
||||||
namespace LanguageServer;
|
namespace LanguageServer;
|
||||||
|
|
||||||
use LanguageServer\Index\ReadableIndex;
|
use LanguageServer\Index\ReadableIndex;
|
||||||
|
use LanguageServer\ProtocolBridge\SymbolInformationFactory;
|
||||||
use LanguageServer\Protocol\SymbolInformation;
|
use LanguageServer\Protocol\SymbolInformation;
|
||||||
use Microsoft\PhpParser;
|
use Microsoft\PhpParser;
|
||||||
use Microsoft\PhpParser\Node;
|
use Microsoft\PhpParser\Node;
|
||||||
|
@ -36,12 +37,19 @@ class DefinitionResolver
|
||||||
private $docBlockFactory;
|
private $docBlockFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates SignatureInformation
|
* Creates SignatureInformation instances
|
||||||
*
|
*
|
||||||
* @var SignatureInformationFactory
|
* @var SignatureInformationFactory
|
||||||
*/
|
*/
|
||||||
private $signatureInformationFactory;
|
private $signatureInformationFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates SymbolInformation instances
|
||||||
|
*
|
||||||
|
* @var SymbolInformationFactory
|
||||||
|
*/
|
||||||
|
private $symbolInformationFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ReadableIndex $index
|
* @param ReadableIndex $index
|
||||||
*/
|
*/
|
||||||
|
@ -51,6 +59,7 @@ class DefinitionResolver
|
||||||
$this->typeResolver = new TypeResolver;
|
$this->typeResolver = new TypeResolver;
|
||||||
$this->docBlockFactory = DocBlockFactory::createInstance();
|
$this->docBlockFactory = DocBlockFactory::createInstance();
|
||||||
$this->signatureInformationFactory = new SignatureInformationFactory($this);
|
$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) {
|
if ($def->symbolInformation !== null) {
|
||||||
$def->type = $this->getTypeFromNode($node);
|
$def->type = $this->getTypeFromNode($node);
|
||||||
|
|
|
@ -7,11 +7,11 @@ use LanguageServer\Protocol\{
|
||||||
ServerCapabilities,
|
ServerCapabilities,
|
||||||
ClientCapabilities,
|
ClientCapabilities,
|
||||||
TextDocumentSyncKind,
|
TextDocumentSyncKind,
|
||||||
Message,
|
|
||||||
InitializeResult,
|
InitializeResult,
|
||||||
CompletionOptions,
|
CompletionOptions,
|
||||||
SignatureHelpOptions
|
SignatureHelpOptions
|
||||||
};
|
};
|
||||||
|
use LanguageServer\ProtocolBridge\Message;
|
||||||
use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder};
|
use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder};
|
||||||
use LanguageServer\ContentRetriever\{ContentRetriever, ClientContentRetriever, FileSystemContentRetriever};
|
use LanguageServer\ContentRetriever\{ContentRetriever, ClientContentRetriever, FileSystemContentRetriever};
|
||||||
use LanguageServer\Index\{DependenciesIndex, GlobalIndex, Index, ProjectIndex, StubsIndex};
|
use LanguageServer\Index\{DependenciesIndex, GlobalIndex, Index, ProjectIndex, StubsIndex};
|
||||||
|
|
|
@ -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)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ use LanguageServer\{
|
||||||
CompletionProvider, SignatureHelpProvider, LanguageClient, PhpDocument, PhpDocumentLoader, DefinitionResolver
|
CompletionProvider, SignatureHelpProvider, LanguageClient, PhpDocument, PhpDocumentLoader, DefinitionResolver
|
||||||
};
|
};
|
||||||
use LanguageServer\Index\ReadableIndex;
|
use LanguageServer\Index\ReadableIndex;
|
||||||
|
use LanguageServer\ProtocolBridge\LocationFactory;
|
||||||
|
use LanguageServer\ProtocolBridge\RangeFactory;
|
||||||
use LanguageServer\Protocol\{
|
use LanguageServer\Protocol\{
|
||||||
FormattingOptions,
|
FormattingOptions,
|
||||||
Hover,
|
Hover,
|
||||||
|
@ -233,7 +235,7 @@ class TextDocument
|
||||||
$refs = $document->getReferenceNodesByFqn($fqn);
|
$refs = $document->getReferenceNodesByFqn($fqn);
|
||||||
if ($refs !== null) {
|
if ($refs !== null) {
|
||||||
foreach ($refs as $ref) {
|
foreach ($refs as $ref) {
|
||||||
$locations[] = Location::fromNode($ref);
|
$locations[] = LocationFactory::fromNode($ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,7 +334,7 @@ class TextDocument
|
||||||
}
|
}
|
||||||
yield waitForEvent($this->index, 'definition-added');
|
yield waitForEvent($this->index, 'definition-added');
|
||||||
}
|
}
|
||||||
$range = Range::fromNode($node);
|
$range = RangeFactory::fromNode($node);
|
||||||
if ($def === null) {
|
if ($def === null) {
|
||||||
return new Hover([], $range);
|
return new Hover([], $range);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace LanguageServer\Server;
|
||||||
|
|
||||||
use LanguageServer\{LanguageClient, PhpDocumentLoader};
|
use LanguageServer\{LanguageClient, PhpDocumentLoader};
|
||||||
use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index};
|
use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index};
|
||||||
|
use LanguageServer\ProtocolBridge\LocationFactory;
|
||||||
use LanguageServer\Protocol\{
|
use LanguageServer\Protocol\{
|
||||||
FileChangeType,
|
FileChangeType,
|
||||||
FileEvent,
|
FileEvent,
|
||||||
|
@ -150,7 +151,7 @@ class Workspace
|
||||||
$doc = yield $this->documentLoader->getOrLoad($uri);
|
$doc = yield $this->documentLoader->getOrLoad($uri);
|
||||||
foreach ($doc->getReferenceNodesByFqn($fqn) as $node) {
|
foreach ($doc->getReferenceNodesByFqn($fqn) as $node) {
|
||||||
$refInfo = new ReferenceInformation;
|
$refInfo = new ReferenceInformation;
|
||||||
$refInfo->reference = Location::fromNode($node);
|
$refInfo->reference = LocationFactory::fromNode($node);
|
||||||
$refInfo->symbol = $query;
|
$refInfo->symbol = $query;
|
||||||
$refInfos[] = $refInfo;
|
$refInfos[] = $refInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ declare(strict_types = 1);
|
||||||
|
|
||||||
namespace LanguageServer;
|
namespace LanguageServer;
|
||||||
|
|
||||||
|
use LanguageServer\ProtocolBridge\RangeFactory;
|
||||||
use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position};
|
use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position};
|
||||||
use phpDocumentor\Reflection\DocBlockFactory;
|
use phpDocumentor\Reflection\DocBlockFactory;
|
||||||
use Microsoft\PhpParser;
|
use Microsoft\PhpParser;
|
||||||
|
@ -100,7 +101,7 @@ class TreeAnalyzer
|
||||||
if ($method && $method->isStatic()) {
|
if ($method && $method->isStatic()) {
|
||||||
$this->diagnostics[] = new Diagnostic(
|
$this->diagnostics[] = new Diagnostic(
|
||||||
"\$this can not be used in static methods.",
|
"\$this can not be used in static methods.",
|
||||||
Range::fromNode($node),
|
RangeFactory::fromNode($node),
|
||||||
null,
|
null,
|
||||||
DiagnosticSeverity::ERROR,
|
DiagnosticSeverity::ERROR,
|
||||||
'php'
|
'php'
|
||||||
|
|
Loading…
Reference in New Issue