1
0
Fork 0

Remove ParserResourceFactory and DefinitionResolverInterface (leave original DefinitionResolver for now, for more testing)

pull/357/head
Rob Lourens 2017-05-02 11:04:44 -07:00
parent 30da705a88
commit 31441f4b7e
25 changed files with 147 additions and 359 deletions

View File

@ -6,16 +6,12 @@ require __DIR__ . '/vendor/autoload.php';
use Exception; use Exception;
use LanguageServer\Index\Index; use LanguageServer\Index\Index;
use LanguageServer\ParserKind; use LanguageServer\ParserKind;
use LanguageServer\ParserResourceFactory;
use LanguageServer\PhpDocument; use LanguageServer\PhpDocument;
use LanguageServer\TolerantDefinitionResolver;
use Microsoft\PhpParser as Tolerant;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use PHPUnit\Framework\TestCase;
use LanguageServer\ClientHandler;
use LanguageServer\Protocol\Message;
use AdvancedJsonRpc;
use RecursiveDirectoryIterator; use RecursiveDirectoryIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;
use Sabre\Event\Loop;
$totalSize = 0; $totalSize = 0;
@ -60,11 +56,9 @@ foreach($frameworks as $framework) {
$index = new Index; $index = new Index;
$maxRecursion = []; $maxRecursion = [];
$definitions = []; $definitions = [];
global $parserKind;
$parserKind = $kind;
$definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $definitionResolver = new TolerantDefinitionResolver($index);
$parser = ParserResourceFactory::getParser(); $parser = new Tolerant\Parser();
try { try {
$document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); $document = new PhpDocument($testCaseFile, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver);

View File

@ -89,7 +89,7 @@ class CompletionProvider
]; ];
/** /**
* @var DefinitionResolverInterface * @var TolerantDefinitionResolver
*/ */
private $definitionResolver; private $definitionResolver;
@ -104,10 +104,10 @@ class CompletionProvider
private $index; private $index;
/** /**
* @param DefinitionResolverInterface $definitionResolver * @param TolerantDefinitionResolver $definitionResolver
* @param ReadableIndex $index * @param ReadableIndex $index
*/ */
public function __construct(DefinitionResolverInterface $definitionResolver, ReadableIndex $index) public function __construct(TolerantDefinitionResolver $definitionResolver, ReadableIndex $index)
{ {
$this->definitionResolver = $definitionResolver; $this->definitionResolver = $definitionResolver;
$this->index = $index; $this->index = $index;
@ -124,7 +124,7 @@ class CompletionProvider
{ {
// This can be made much more performant if the tree follows specific invariants. // This can be made much more performant if the tree follows specific invariants.
$node = $doc->getNodeAtPosition($pos); $node = $doc->getNodeAtPosition($pos);
if($node !== null && ($offset = $pos->toOffset($node->getFileContents())) > $node->getEndPosition() && if($node !== null && ($offset = $pos->toOffset($node->getFileContents())) > $node->getEndPosition() &&
$node->parent->getLastChild() instanceof Tolerant\MissingToken) { $node->parent->getLastChild() instanceof Tolerant\MissingToken) {

View File

@ -30,8 +30,8 @@ class ComposerScripts
$finder = new FileSystemFilesFinder; $finder = new FileSystemFilesFinder;
$contentRetriever = new FileSystemContentRetriever; $contentRetriever = new FileSystemContentRetriever;
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$parser = ParserResourceFactory::getParser(); $parser = Tolerant\Parser();
$definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $definitionResolver = new TolerantDefinitionResolver($index);
$stubsLocation = null; $stubsLocation = null;
foreach ([__DIR__ . '/../../../jetbrains/phpstorm-stubs', __DIR__ . '/../vendor/jetbrains/phpstorm-stubs'] as $dir) { foreach ([__DIR__ . '/../../../jetbrains/phpstorm-stubs', __DIR__ . '/../vendor/jetbrains/phpstorm-stubs'] as $dir) {

View File

@ -9,7 +9,7 @@ use phpDocumentor\Reflection\{Types, Type, Fqsen, TypeResolver};
use LanguageServer\Protocol\SymbolInformation; use LanguageServer\Protocol\SymbolInformation;
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
class DefinitionResolver implements DefinitionResolverInterface class DefinitionResolver
{ {
/** /**
* @var \LanguageServer\Index\ReadableIndex * @var \LanguageServer\Index\ReadableIndex

View File

@ -1,86 +0,0 @@
<?php
namespace LanguageServer;
use phpDocumentor\Reflection\Type;
use PhpParser\Node;
use Microsoft\PhpParser as Tolerant;
interface DefinitionResolverInterface
{
/**
* Builds the declaration line for a given node
*
* @param Node | Tolerant\Node $node
* @return string
*/
public function getDeclarationLineFromNode($node) : string;
/**
* Gets the documentation string for a node, if it has one
*
* @param Node | Tolerant\Node $node
* @return string|null
*/
public function getDocumentationFromNode($node);
/**
* Create a Definition for a definition node
*
* @param Node | Tolerant\Node $node
* @param string $fqn
* @return Definition
*/
public function createDefinitionFromNode($node, string $fqn = null) : Definition;
/**
* Given any node, returns the Definition object of the symbol that is referenced
*
* @param Node | Tolerant\Node $node Any reference node
* @return Definition|null
*/
public function resolveReferenceNodeToDefinition($node);
/**
* Given any node, returns the FQN of the symbol that is referenced
* Returns null if the FQN could not be resolved or the reference node references a variable
*
* @param Node | Tolerant\Node $node
* @return string|null
*/
public function resolveReferenceNodeToFqn($node);
/**
* Given an expression node, resolves that expression recursively to a type.
* If the type could not be resolved, returns Types\Mixed.
*
* @param \PhpParser\Node\Expr | Tolerant\Node $expr
* @return \phpDocumentor\Reflection\Type
*/
public function resolveExpressionNodeToType($expr) : Type;
/**
* Returns the type a reference to this symbol will resolve to.
* For properties and constants, this is the type of the property/constant.
* For functions and methods, this is the return type.
* For parameters, this is the type of the parameter.
* For classes and interfaces, this is the class type (object).
* For variables / assignments, this is the documented type or type the assignment resolves to.
* Can also be a compound type.
* If it is unknown, will be Types\Mixed.
* Returns null if the node does not have a type.
*
* @param Node | Tolerant\Node $node
* @return \phpDocumentor\Reflection\Type|null
*/
public function getTypeFromNode($node);
/**
* Returns the fully qualified name (FQN) that is defined by a node
* Returns null if the node does not declare any symbol that can be referenced by an FQN
*
* @param Node | Tolerant\Node $node
* @return string|null
*/
public static function getDefinedFqn($node);
}

View File

@ -8,10 +8,7 @@ use LanguageServer\Protocol\{
ClientCapabilities, ClientCapabilities,
TextDocumentSyncKind, TextDocumentSyncKind,
Message, Message,
MessageType,
InitializeResult, InitializeResult,
SymbolInformation,
TextDocumentIdentifier,
CompletionOptions CompletionOptions
}; };
use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder}; use LanguageServer\FilesFinder\{FilesFinder, ClientFilesFinder, FileSystemFilesFinder};
@ -19,12 +16,10 @@ use LanguageServer\ContentRetriever\{ContentRetriever, ClientContentRetriever, F
use LanguageServer\Index\{DependenciesIndex, GlobalIndex, Index, ProjectIndex, StubsIndex}; use LanguageServer\Index\{DependenciesIndex, GlobalIndex, Index, ProjectIndex, StubsIndex};
use LanguageServer\Cache\{FileSystemCache, ClientCache}; use LanguageServer\Cache\{FileSystemCache, ClientCache};
use AdvancedJsonRpc; use AdvancedJsonRpc;
use Sabre\Event\{Loop, Promise}; use Sabre\Event\{Promise};
use function Sabre\Event\coroutine; use function Sabre\Event\coroutine;
use Exception;
use Throwable; use Throwable;
use Webmozart\PathUtil\Path; use Webmozart\PathUtil\Path;
use Sabre\Uri;
class LanguageServer extends AdvancedJsonRpc\Dispatcher class LanguageServer extends AdvancedJsonRpc\Dispatcher
{ {
@ -106,7 +101,7 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
protected $projectIndex; protected $projectIndex;
/** /**
* @var DefinitionResolverInterface * @var TolerantDefinitionResolver
*/ */
protected $definitionResolver; protected $definitionResolver;
@ -192,7 +187,7 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
$this->globalIndex = new GlobalIndex($stubsIndex, $this->projectIndex); $this->globalIndex = new GlobalIndex($stubsIndex, $this->projectIndex);
// The DefinitionResolver should look in stubs, the project source and dependencies // The DefinitionResolver should look in stubs, the project source and dependencies
$this->definitionResolver = ParserResourceFactory::getDefinitionResolver($this->globalIndex); $this->definitionResolver = new TolerantDefinitionResolver($this->globalIndex);
$this->documentLoader = new PhpDocumentLoader( $this->documentLoader = new PhpDocumentLoader(
$this->contentRetriever, $this->contentRetriever,

View File

@ -5,9 +5,8 @@ namespace LanguageServer\NodeVisitor;
use PhpParser\{NodeVisitorAbstract, Node}; use PhpParser\{NodeVisitorAbstract, Node};
use LanguageServer\{ use LanguageServer\{
Definition, DefinitionResolver, DefinitionResolverInterface, FqnUtilities Definition, FqnUtilities, TolerantDefinitionResolver
}; };
use LanguageServer\Protocol\SymbolInformation;
/** /**
* Collects definitions of classes, interfaces, traits, methods, properties and constants * Collects definitions of classes, interfaces, traits, methods, properties and constants
@ -31,7 +30,7 @@ class DefinitionCollector extends NodeVisitorAbstract
private $definitionResolver; private $definitionResolver;
public function __construct(DefinitionResolverInterface $definitionResolver) public function __construct(TolerantDefinitionResolver $definitionResolver)
{ {
$this->definitionResolver = $definitionResolver; $this->definitionResolver = $definitionResolver;
} }

View File

@ -4,8 +4,9 @@ declare(strict_types = 1);
namespace LanguageServer\NodeVisitor; namespace LanguageServer\NodeVisitor;
use LanguageServer\DefinitionResolverInterface; use LanguageServer\DefinitionResolverInterface;
use PhpParser\{NodeVisitorAbstract, Node}; use PhpParser\{
use LanguageServer\DefinitionResolver; Node, NodeVisitorAbstract
};
/** /**
* Collects references to classes, interfaces, traits, methods, properties and constants * Collects references to classes, interfaces, traits, methods, properties and constants
@ -21,14 +22,14 @@ class ReferencesCollector extends NodeVisitorAbstract
public $nodes = []; public $nodes = [];
/** /**
* @var DefinitionResolverInterface * @var TolerantDefinitionResolver
*/ */
private $definitionResolver; private $definitionResolver;
/** /**
* @param DefinitionResolverInterface $definitionResolver The DefinitionResolver to resolve reference nodes to definitions * @param TolerantDefinitionResolver $definitionResolver The definition resolver to resolve reference nodes to definitions
*/ */
public function __construct(DefinitionResolverInterface $definitionResolver) public function __construct(TolerantDefinitionResolver $definitionResolver)
{ {
$this->definitionResolver = $definitionResolver; $this->definitionResolver = $definitionResolver;
} }

View File

@ -1,45 +0,0 @@
<?php
namespace LanguageServer;
use Microsoft\PhpParser as Tolerant;
use LanguageServer\Index\ReadableIndex;
class ParserResourceFactory {
const PARSER_KIND = ParserKind::TOLERANT_PHP_PARSER;
private static function getParserKind () {
global $parserKind;
return isset($parserKind) ? $parserKind : self::PARSER_KIND;
}
public static function getParser() {
if (self::getParserKind() === ParserKind::PHP_PARSER || self::getParserKind() === ParserKind::DIAGNOSTIC_PHP_PARSER) {
return new Parser;
} else {
return new Tolerant\Parser;
}
}
public static function getDefinitionResolver(ReadableIndex $index) {
switch (self::getParserKind()) {
case ParserKind::PHP_PARSER:
return new DefinitionResolver($index);
case ParserKind::TOLERANT_PHP_PARSER:
return new TolerantDefinitionResolver($index);
case ParserKind::DIAGNOSTIC_PHP_PARSER:
return new LoggedDefinitionResolver($index);
case ParserKind::DIAGNOSTIC_TOLERANT_PHP_PARSER:
return new LoggedTolerantDefinitionResolver($index);
}
}
public static function getTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri)
{
if (self::getParserKind() === ParserKind::PHP_PARSER || self::getParserKind() === ParserKind::DIAGNOSTIC_PHP_PARSER) {
return new TreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri);
} else {
return new TolerantTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri);
}
}
}

View File

@ -3,21 +3,18 @@ declare(strict_types = 1);
namespace LanguageServer; namespace LanguageServer;
use LanguageServer\Protocol\{Diagnostic, DiagnosticSeverity, Range, Position, TextEdit};
use LanguageServer\NodeVisitor\{
NodeAtPositionFinder,
ReferencesAdder,
DocBlockParser,
DefinitionCollector,
ColumnCalculator,
ReferencesCollector
};
use LanguageServer\Index\Index; use LanguageServer\Index\Index;
use PhpParser\{Error, ErrorHandler, Node, NodeTraverser}; use LanguageServer\NodeVisitor\{
use PhpParser\NodeVisitor\NameResolver; NodeAtPositionFinder
use phpDocumentor\Reflection\DocBlockFactory; };
use Sabre\Uri; use LanguageServer\Protocol\{
Diagnostic, Position, Range
};
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser as Tolerant;
use phpDocumentor\Reflection\DocBlockFactory;
use PhpParser\{
Node, NodeTraverser
};
class PhpDocument class PhpDocument
{ {
@ -38,7 +35,7 @@ class PhpDocument
/** /**
* The DefinitionResolver instance to resolve reference nodes to definitions * The DefinitionResolver instance to resolve reference nodes to definitions
* *
* @var DefinitionResolverInterface * @var TolerantDefinitionResolver
*/ */
private $definitionResolver; private $definitionResolver;
@ -102,7 +99,7 @@ class PhpDocument
* @param Index $index The Index to register definitions and references to * @param Index $index The Index to register definitions and references to
* @param Parser $parser The PHPParser instance * @param Parser $parser The PHPParser instance
* @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks * @param DocBlockFactory $docBlockFactory The DocBlockFactory instance to parse docblocks
* @param DefinitionResolverInterface $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace * @param TolerantDefinitionResolver $definitionResolver The DefinitionResolver to resolve definitions to symbols in the workspace
*/ */
public function __construct( public function __construct(
string $uri, string $uri,
@ -110,7 +107,7 @@ class PhpDocument
Index $index, Index $index,
$parser, $parser,
DocBlockFactory $docBlockFactory, DocBlockFactory $docBlockFactory,
DefinitionResolverInterface $definitionResolver TolerantDefinitionResolver $definitionResolver
) { ) {
$this->uri = $uri; $this->uri = $uri;
$this->index = $index; $this->index = $index;
@ -161,7 +158,7 @@ class PhpDocument
$this->definitions = null; $this->definitions = null;
$this->definitionNodes = null; $this->definitionNodes = null;
$treeAnalyzer = ParserResourceFactory::getTreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri); $treeAnalyzer = new TolerantTreeAnalyzer($this->parser, $content, $this->docBlockFactory, $this->definitionResolver, $this->uri);
$this->diagnostics = $treeAnalyzer->getDiagnostics(); $this->diagnostics = $treeAnalyzer->getDiagnostics();
@ -170,7 +167,7 @@ class PhpDocument
$this->definitionNodes = $treeAnalyzer->getDefinitionNodes(); $this->definitionNodes = $treeAnalyzer->getDefinitionNodes();
$this->referenceNodes = $treeAnalyzer->getReferenceNodes(); $this->referenceNodes = $treeAnalyzer->getReferenceNodes();
foreach ($this->definitions as $fqn => $definition) { foreach ($this->definitions as $fqn => $definition) {
$this->index->setDefinition($fqn, $definition); $this->index->setDefinition($fqn, $definition);
} }
@ -179,7 +176,7 @@ class PhpDocument
foreach ($this->referenceNodes as $fqn => $nodes) { foreach ($this->referenceNodes as $fqn => $nodes) {
$this->index->addReferenceUri($fqn, $this->uri); $this->index->addReferenceUri($fqn, $this->uri);
} }
$this->stmts = $treeAnalyzer->getStmts(); $this->stmts = $treeAnalyzer->getStmts();
} }

View File

@ -48,24 +48,25 @@ class PhpDocumentLoader
private $docBlockFactory; private $docBlockFactory;
/** /**
* @var DefinitionResolverInterface * @var TolerantDefinitionResolver
*/ */
private $definitionResolver; private $definitionResolver;
/** /**
* @param ContentRetriever $contentRetriever * @param ContentRetriever $contentRetriever
* @param ProjectIndex $project * @param ProjectIndex $projectIndex
* @param DefinitionResolverInterface $definitionResolver * @param TolerantDefinitionResolver $definitionResolver
* @internal param ProjectIndex $project
*/ */
public function __construct( public function __construct(
ContentRetriever $contentRetriever, ContentRetriever $contentRetriever,
ProjectIndex $projectIndex, ProjectIndex $projectIndex,
DefinitionResolverInterface $definitionResolver TolerantDefinitionResolver $definitionResolver
) { ) {
$this->contentRetriever = $contentRetriever; $this->contentRetriever = $contentRetriever;
$this->projectIndex = $projectIndex; $this->projectIndex = $projectIndex;
$this->definitionResolver = $definitionResolver; $this->definitionResolver = $definitionResolver;
$this->parser = ParserResourceFactory::getParser(); $this->parser = new Tolerant\Parser();
$this->docBlockFactory = DocBlockFactory::createInstance(); $this->docBlockFactory = DocBlockFactory::createInstance();
} }

View File

@ -3,37 +3,20 @@ declare(strict_types = 1);
namespace LanguageServer\Server; namespace LanguageServer\Server;
use Microsoft\PhpParser as Tolerant;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use PhpParser\{Node, NodeTraverser};
use LanguageServer\{ use LanguageServer\{
DefinitionResolverInterface, FqnUtilities, LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider, TolerantDefinitionResolver, TolerantTreeAnalyzer CompletionProvider, FqnUtilities, LanguageClient, PhpDocument, PhpDocumentLoader, TolerantDefinitionResolver
};
use LanguageServer\NodeVisitor\VariableReferencesCollector;
use LanguageServer\Protocol\{
SymbolLocationInformation,
SymbolDescriptor,
TextDocumentItem,
TextDocumentIdentifier,
VersionedTextDocumentIdentifier,
Position,
Range,
FormattingOptions,
TextEdit,
Location,
SymbolInformation,
ReferenceContext,
Hover,
MarkedString,
SymbolKind,
CompletionItem,
CompletionItemKind
}; };
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
use LanguageServer\Protocol\{
FormattingOptions, Hover, Location, MarkedString, Position, Range, ReferenceContext, SymbolDescriptor, SymbolLocationInformation, TextDocumentIdentifier, TextDocumentItem, VersionedTextDocumentIdentifier
};
use Microsoft\PhpParser as Tolerant;
use Sabre\Event\Promise; use Sabre\Event\Promise;
use Sabre\Uri; use Sabre\Uri;
use function LanguageServer\{
isVendored, waitForEvent
};
use function Sabre\Event\coroutine; use function Sabre\Event\coroutine;
use function LanguageServer\{waitForEvent, isVendored};
/** /**
* Provides method handlers for all textDocument/* methods * Provides method handlers for all textDocument/* methods
@ -53,7 +36,7 @@ class TextDocument
protected $project; protected $project;
/** /**
* @var DefinitionResolverInterface * @var TolerantDefinitionResolver
*/ */
protected $definitionResolver; protected $definitionResolver;
@ -79,7 +62,7 @@ class TextDocument
/** /**
* @param PhpDocumentLoader $documentLoader * @param PhpDocumentLoader $documentLoader
* @param DefinitionResolverInterface $definitionResolver * @param TolerantDefinitionResolver $definitionResolver
* @param LanguageClient $client * @param LanguageClient $client
* @param ReadableIndex $index * @param ReadableIndex $index
* @param \stdClass $composerJson * @param \stdClass $composerJson
@ -87,7 +70,7 @@ class TextDocument
*/ */
public function __construct( public function __construct(
PhpDocumentLoader $documentLoader, PhpDocumentLoader $documentLoader,
DefinitionResolverInterface $definitionResolver, TolerantDefinitionResolver $definitionResolver,
LanguageClient $client, LanguageClient $client,
ReadableIndex $index, ReadableIndex $index,
\stdClass $composerJson = null, \stdClass $composerJson = null,

View File

@ -3,16 +3,15 @@ declare(strict_types = 1);
namespace LanguageServer; namespace LanguageServer;
use LanguageServer\Protocol\TolerantSymbolInformation;
use PhpParser\Node;
use phpDocumentor\Reflection\{
DocBlock, DocBlockFactory, Types, Type, Fqsen, TypeResolver
};
use LanguageServer\Protocol\SymbolInformation;
use LanguageServer\Index\ReadableIndex; use LanguageServer\Index\ReadableIndex;
use LanguageServer\Protocol\TolerantSymbolInformation;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser as Tolerant;
use phpDocumentor\Reflection\{
DocBlock, DocBlockFactory, Fqsen, Type, TypeResolver, Types
};
use PhpParser\Node;
class TolerantDefinitionResolver implements DefinitionResolverInterface class TolerantDefinitionResolver
{ {
/** /**
* The current project index (for retrieving existing definitions) * The current project index (for retrieving existing definitions)
@ -77,7 +76,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
$defLine = \rtrim(\strtok($defLine, "\n"), "\r"); $defLine = \rtrim(\strtok($defLine, "\n"), "\r");
// TODO - pretty print rather than getting text // TODO - pretty print rather than getting text
return $defLine; return $defLine;
} }
@ -93,7 +92,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) { if ($node instanceof Tolerant\Node\Statement\NamespaceDefinition) {
return null; return null;
} }
// For properties and constants, set the node to the declaration node, rather than the individual property. // For properties and constants, set the node to the declaration node, rather than the individual property.
// This is because they get defined as part of a list. // This is because they get defined as part of a list.
$constOrPropertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node); $constOrPropertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node);
@ -196,8 +195,8 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
// TODO - why is this represented as an array? // TODO - why is this represented as an array?
// TODO interface implementations. // TODO interface implementations.
} elseif ( } elseif (
$node instanceof Tolerant\Node\Statement\InterfaceDeclaration && $node instanceof Tolerant\Node\Statement\InterfaceDeclaration &&
// TODO - this hould be better represented in the parser API // TODO - this should be better represented in the parser API
$node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null $node->interfaceBaseClause !== null && $node->interfaceBaseClause->interfaceNameList !== null
) { ) {
$def->extends = []; $def->extends = [];
@ -229,7 +228,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
// Variables are not indexed globally, as they stay in the file scope anyway. // Variables are not indexed globally, as they stay in the file scope anyway.
// Ignore variable nodes that are part of ScopedPropertyAccessExpression, // Ignore variable nodes that are part of ScopedPropertyAccessExpression,
// as the scoped property access expression node is handled separately. // as the scoped property access expression node is handled separately.
if ($node instanceof Tolerant\Node\Expression\Variable && if ($node instanceof Tolerant\Node\Expression\Variable &&
!($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression)) !($parent instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression))
{ {
// Resolve $this to the containing class definition. // Resolve $this to the containing class definition.
@ -252,6 +251,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
} }
// If the node is a function or constant, it could be namespaced, but PHP falls back to global // If the node is a function or constant, it could be namespaced, but PHP falls back to global
// http://php.net/manual/en/language.namespaces.fallback.php // http://php.net/manual/en/language.namespaces.fallback.php
// TODO - verify that this is not a method
$globalFallback = TolerantParserHelpers::isConstantFetch($node) || $parent instanceof Tolerant\Node\Expression\CallExpression; $globalFallback = TolerantParserHelpers::isConstantFetch($node) || $parent instanceof Tolerant\Node\Expression\CallExpression;
// Return the Definition object from the index index // Return the Definition object from the index index
return $this->index->getDefinition($fqn, $globalFallback); return $this->index->getDefinition($fqn, $globalFallback);
@ -264,7 +264,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
* @param Node $node * @param Node $node
* @return string|null * @return string|null
*/ */
public function resolveReferenceNodeToFqn($node) { public function resolveReferenceNodeToFqn($node) {
// TODO all name tokens should be a part of a node // TODO all name tokens should be a part of a node
if ($node instanceof Tolerant\Node\QualifiedName) { if ($node instanceof Tolerant\Node\QualifiedName) {
return $this->resolveQualifiedNameNodeToFqn($node); return $this->resolveQualifiedNameNodeToFqn($node);
@ -278,7 +278,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
} }
else if ( else if (
// A\B::C - constant access expression // A\B::C - constant access expression
$node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression $node instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression
&& !($node->memberName instanceof Tolerant\Node\Expression\Variable) && !($node->memberName instanceof Tolerant\Node\Expression\Variable)
) { ) {
return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node); return $this->resolveScopedPropertyAccessExpressionNodeToFqn($node);
@ -299,10 +299,10 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
return null; return null;
} }
// Add use clause references // Add use clause references
if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause if (($useClause = $parent) instanceof Tolerant\Node\NamespaceUseGroupClause
|| $useClause instanceof Tolerant\Node\NamespaceUseClause || $useClause instanceof Tolerant\Node\NamespaceUseClause
) { ) {
$contents = $node->getFileContents(); $contents = $node->getFileContents();
if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) { if ($useClause instanceof Tolerant\Node\NamespaceUseGroupClause) {
$prefix = $useClause->parent->parent->namespaceName; $prefix = $useClause->parent->parent->namespaceName;
if ($prefix === null) { if ($prefix === null) {
@ -331,7 +331,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
// For extends, implements, type hints and classes of classes of static calls use the name directly // For extends, implements, type hints and classes of classes of static calls use the name directly
$name = (string) ($node->getResolvedName() ?? $node->getNamespacedName()); $name = (string) ($node->getResolvedName() ?? $node->getNamespacedName());
if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($node->parent instanceof Tolerant\Node\Expression\CallExpression) {
$name .= '()'; $name .= '()';
} }
@ -555,7 +555,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
// VARIABLE // VARIABLE
// $this -> Type\this // $this -> Type\this
// $myVariable -> type of corresponding assignment expression // $myVariable -> type of corresponding assignment expression
if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) { if ($expr instanceof Tolerant\Node\Expression\Variable || $expr instanceof Tolerant\Node\UseVariableName) {
if ($expr->getName() === 'this') { if ($expr->getName() === 'this') {
return new Types\This; return new Types\This;
@ -577,7 +577,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
$expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression || $expr->callableExpression instanceof Tolerant\Node\Expression\ScopedPropertyAccessExpression ||
$expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression) $expr->callableExpression instanceof Tolerant\Node\Expression\MemberAccessExpression)
) { ) {
// Find the function definition // Find the function definition
if ($expr->callableExpression instanceof Tolerant\Node\Expression) { if ($expr->callableExpression instanceof Tolerant\Node\Expression) {
// Cannot get type for dynamic function call // Cannot get type for dynamic function call
@ -664,7 +664,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) { if ($expr->parent instanceof Tolerant\Node\Expression\CallExpression) {
$fqn .= '()'; $fqn .= '()';
} }
$def = $this->index->getDefinition($fqn); $def = $this->index->getDefinition($fqn);
if ($def === null) { if ($def === null) {
return new Types\Mixed; return new Types\Mixed;
@ -686,14 +686,14 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
} }
// ASSIGNMENT EXPRESSION // ASSIGNMENT EXPRESSION
// $a = $myExpression => resolves to the type of the right-hand operand // $a = $myExpression => resolves to the type of the right-hand operand
if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) { if ($expr instanceof Tolerant\Node\Expression\AssignmentExpression) {
return $this->resolveExpressionNodeToType($expr->rightOperand); return $this->resolveExpressionNodeToType($expr->rightOperand);
} }
// TERNARY EXPRESSION // TERNARY EXPRESSION
// $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression // $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression
// $condition ?: $elseExpression => resolves to type of $condition or $elseExpression // $condition ?: $elseExpression => resolves to type of $condition or $elseExpression
if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) { if ($expr instanceof Tolerant\Node\Expression\TernaryExpression) {
// ?: // ?:
if ($expr->ifExpression === null) { if ($expr->ifExpression === null) {
@ -751,7 +751,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
return new Types\String_; return new Types\String_;
} }
// BINARY EXPRESSIONS: // BINARY EXPRESSIONS:
// Resolve to Types\Integer if both left and right operands are integer types, otherwise Types\Float // Resolve to Types\Integer if both left and right operands are integer types, otherwise Types\Float
// [operator] +, -, *, ** // [operator] +, -, *, **
// [assignment] *=, **=, -=, += // [assignment] *=, **=, -=, +=
@ -1005,8 +1005,8 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
// PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS // PROPERTIES, CONSTS, CLASS CONSTS, ASSIGNMENT EXPRESSIONS
// Get the documented type the assignment resolves to. // Get the documented type the assignment resolves to.
if ( if (
($declarationNode = ($declarationNode =
TolerantParserHelpers::tryGetPropertyDeclaration($node) ?? TolerantParserHelpers::tryGetPropertyDeclaration($node) ??
TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node) TolerantParserHelpers::tryGetConstOrClassConstDeclaration($node)
) !== null || ) !== null ||
($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression) ($node = $node->parent) instanceof Tolerant\Node\Expression\AssignmentExpression)
@ -1085,8 +1085,8 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
// INPUT OUTPUT // INPUT OUTPUT
// namespace A\B; // namespace A\B;
// class C { // class C {
// function a () {} A\B\C::a() // function a () {} A\B\C->a()
// static function b() {} A\B\C->b() // static function b() {} A\B\C::b()
// } // }
else if ($node instanceof Tolerant\Node\MethodDeclaration) { else if ($node instanceof Tolerant\Node\MethodDeclaration) {
// Class method: use ClassName->methodName() as name // Class method: use ClassName->methodName() as name
@ -1111,7 +1111,7 @@ class TolerantDefinitionResolver implements DefinitionResolverInterface
// namespace A\B; // namespace A\B;
// class C { // class C {
// static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b // static $a = 4, $b = 4 A\B\C::$a, A\B\C::$b
// $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // $a = 4, $b = 4 A\B\C->$a, A\B\C->$b // TODO verify variable name
// } // }
else if ( else if (
($propertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) !== null && ($propertyDeclaration = TolerantParserHelpers::tryGetPropertyDeclaration($node)) !== null &&

View File

@ -7,7 +7,7 @@ use PHPUnit\Framework\TestCase;
use PhpParser\{Node}; use PhpParser\{Node};
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory TolerantDefinitionResolver, TolerantTreeAnalyzer
}; };
use LanguageServer\Index\{Index}; use LanguageServer\Index\{Index};
use function LanguageServer\pathToUri; use function LanguageServer\pathToUri;
@ -67,14 +67,14 @@ class DefinitionCollectorTest extends TestCase
private function collectDefinitions($path):array private function collectDefinitions($path):array
{ {
$uri = pathToUri($path); $uri = pathToUri($path);
$parser = ParserResourceFactory::getParser(); $parser = new Tolerant\Parser();
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$index = new Index; $index = new Index;
$definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $definitionResolver = new TolerantDefinitionResolver($index);
$content = file_get_contents($path); $content = file_get_contents($path);
$treeAnalyzer = ParserResourceFactory::getTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri); $treeAnalyzer = new TolerantTreeAnalyzer($parser, $content, $docBlockFactory, $definitionResolver, $uri);
return $treeAnalyzer->getDefinitionNodes(); return $treeAnalyzer->getDefinitionNodes();
} }
} }

View File

@ -3,22 +3,14 @@ declare(strict_types = 1);
namespace LanguageServer\Tests\Server; namespace LanguageServer\Tests\Server;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, Client, LanguageClient, Project, PhpDocument, PhpDocumentLoader, DefinitionResolver PhpDocument, PhpDocumentLoader, Project, TolerantDefinitionResolver
}; };
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Index\{
use LanguageServer\Protocol\{ DependenciesIndex, Index, ProjectIndex
TextDocumentItem,
TextDocumentIdentifier,
SymbolKind,
DiagnosticSeverity,
FormattingOptions,
ClientCapabilities
}; };
use AdvancedJsonRpc\{Request as RequestBody, Response as ResponseBody}; use PHPUnit\Framework\TestCase;
use function LanguageServer\pathToUri; use function LanguageServer\pathToUri;
class PhpDocumentLoaderTest extends TestCase class PhpDocumentLoaderTest extends TestCase
@ -34,7 +26,7 @@ class PhpDocumentLoaderTest extends TestCase
$this->loader = new PhpDocumentLoader( $this->loader = new PhpDocumentLoader(
new FileSystemContentRetriever, new FileSystemContentRetriever,
$projectIndex, $projectIndex,
ParserResourceFactory::getDefinitionResolver($projectIndex) new TolerantDefinitionResolver($projectIndex)
); );
} }

View File

@ -3,28 +3,29 @@ declare(strict_types = 1);
namespace LanguageServer\Tests\Server; namespace LanguageServer\Tests\Server;
use PHPUnit\Framework\TestCase;
use phpDocumentor\Reflection\DocBlockFactory;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, LanguageClient, PhpDocument, DefinitionResolver, Parser PhpDocument, TolerantDefinitionResolver
};
use LanguageServer\Index\{
Index
};
use LanguageServer\Protocol\{
Position
}; };
use LanguageServer\NodeVisitor\NodeAtPositionFinder;
use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Protocol\{SymbolKind, Position, ClientCapabilities};
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use PhpParser\Node;
use function LanguageServer\isVendored;
use Microsoft\PhpParser as Tolerant; use Microsoft\PhpParser as Tolerant;
use phpDocumentor\Reflection\DocBlockFactory;
use PhpParser\Node;
use PHPUnit\Framework\TestCase;
use function LanguageServer\isVendored;
class PhpDocumentTest extends TestCase class PhpDocumentTest extends TestCase
{ {
public function createDocument(string $uri, string $content) public function createDocument(string $uri, string $content)
{ {
$parser = ParserResourceFactory::getParser(); $parser = new Tolerant\Parser();
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$index = new Index; $index = new Index;
$definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $definitionResolver = new TolerantDefinitionResolver($index);
return new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver); return new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver);
} }

View File

@ -6,13 +6,12 @@ namespace LanguageServer\Tests\Server;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver
}; };
use LanguageServer\Index\{ProjectIndex, StubsIndex, GlobalIndex, DependenciesIndex, Index}; use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index};
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Protocol\{Position, Location, Range, ClientCapabilities}; use LanguageServer\Protocol\{Position, Location, Range};
use function LanguageServer\pathToUri; use function LanguageServer\pathToUri;
use Sabre\Event\Promise;
abstract class ServerTestCase extends TestCase abstract class ServerTestCase extends TestCase
{ {
@ -52,7 +51,7 @@ abstract class ServerTestCase extends TestCase
$projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex); $projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex);
$projectIndex->setComplete(); $projectIndex->setComplete();
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex);

View File

@ -6,16 +6,15 @@ namespace LanguageServer\Tests\Server\TextDocument;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, CompletionProvider, DefinitionResolver Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver
}; };
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex, GlobalIndex, StubsIndex}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Protocol\{ use LanguageServer\Protocol\{
TextDocumentIdentifier, TextDocumentIdentifier,
TextEdit, TextEdit,
Range, Range,
Position, Position,
ClientCapabilities,
CompletionList, CompletionList,
CompletionItem, CompletionItem,
CompletionItemKind CompletionItemKind
@ -38,7 +37,7 @@ class CompletionTest extends TestCase
{ {
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$contentRetriever = new FileSystemContentRetriever; $contentRetriever = new FileSystemContentRetriever;
$this->loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $this->loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver);
$this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'))->wait(); $this->loader->load(pathToUri(__DIR__ . '/../../../fixtures/global_symbols.php'))->wait();

View File

@ -6,12 +6,11 @@ namespace LanguageServer\Tests\Server\TextDocument\Definition;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\Tests\Server\ServerTestCase; use LanguageServer\Tests\Server\ServerTestCase;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver
}; };
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Protocol\{TextDocumentIdentifier, Position, Range, Location, ClientCapabilities}; use LanguageServer\Protocol\{TextDocumentIdentifier, Position, Range, Location};
use Sabre\Event\Promise;
class GlobalFallbackTest extends ServerTestCase class GlobalFallbackTest extends ServerTestCase
{ {
@ -20,7 +19,7 @@ class GlobalFallbackTest extends ServerTestCase
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$projectIndex->setComplete(); $projectIndex->setComplete();
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$contentRetriever = new FileSystemContentRetriever; $contentRetriever = new FileSystemContentRetriever;
$loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver); $loader = new PhpDocumentLoader($contentRetriever, $projectIndex, $definitionResolver);
$this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex);

View File

@ -6,18 +6,15 @@ namespace LanguageServer\Tests\Server\TextDocument;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver
}; };
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\Protocol\{ use LanguageServer\Protocol\{
TextDocumentIdentifier,
TextDocumentItem,
VersionedTextDocumentIdentifier, VersionedTextDocumentIdentifier,
TextDocumentContentChangeEvent, TextDocumentContentChangeEvent,
Range, Range,
Position, Position
ClientCapabilities
}; };
class DidChangeTest extends TestCase class DidChangeTest extends TestCase
@ -26,7 +23,7 @@ class DidChangeTest extends TestCase
{ {
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex);
$phpDocument = $loader->open('whatever', "<?php\necho 'Hello, World'\n"); $phpDocument = $loader->open('whatever', "<?php\necho 'Hello, World'\n");

View File

@ -6,12 +6,11 @@ namespace LanguageServer\Tests\Server\TextDocument;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver
}; };
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\Protocol\{TextDocumentItem, TextDocumentIdentifier, ClientCapabilities}; use LanguageServer\Protocol\{TextDocumentItem, TextDocumentIdentifier};
use Exception;
class DidCloseTest extends TestCase class DidCloseTest extends TestCase
{ {
@ -19,7 +18,7 @@ class DidCloseTest extends TestCase
{ {
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex);
$phpDocument = $loader->open('whatever', "<?php\necho 'Hello, World'\n"); $phpDocument = $loader->open('whatever', "<?php\necho 'Hello, World'\n");

View File

@ -6,7 +6,7 @@ namespace LanguageServer\Tests\Server\TextDocument;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, Client, LanguageClient, PhpDocumentLoader, DefinitionResolver Server, LanguageClient, PhpDocumentLoader, TolerantDefinitionResolver
}; };
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
@ -14,7 +14,6 @@ use LanguageServer\Protocol\{
TextDocumentIdentifier, TextDocumentIdentifier,
TextDocumentItem, TextDocumentItem,
FormattingOptions, FormattingOptions,
ClientCapabilities,
TextEdit, TextEdit,
Range, Range,
Position Position
@ -27,7 +26,7 @@ class FormattingTest extends TestCase
{ {
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex);

View File

@ -6,11 +6,11 @@ namespace LanguageServer\Tests\Server\TextDocument;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream; use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, Client, LanguageClient, ClientHandler, PhpDocumentLoader, DefinitionResolver Server, Client, LanguageClient, ClientHandler, PhpDocumentLoader, TolerantDefinitionResolver
}; };
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex}; use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Protocol\{TextDocumentIdentifier, TextDocumentItem, DiagnosticSeverity, ClientCapabilities}; use LanguageServer\Protocol\{TextDocumentItem, DiagnosticSeverity};
use Sabre\Event\Promise; use Sabre\Event\Promise;
use JsonMapper; use JsonMapper;
@ -40,7 +40,7 @@ class ParseErrorsTest extends TestCase
} }
}; };
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex); $this->textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex);
} }

View File

@ -3,14 +3,17 @@ declare(strict_types = 1);
namespace LanguageServer\Tests\Server\TextDocument\References; namespace LanguageServer\Tests\Server\TextDocument\References;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{ use LanguageServer\{
ParserResourceFactory, Server, LanguageClient, PhpDocumentLoader, DefinitionResolver LanguageClient, PhpDocumentLoader, Server, TolerantDefinitionResolver
}; };
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\ContentRetriever\FileSystemContentRetriever; use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Protocol\{TextDocumentIdentifier, Position, ReferenceContext, Location, Range, ClientCapabilities}; use LanguageServer\Index\{
DependenciesIndex, Index, ProjectIndex
};
use LanguageServer\Protocol\{
Location, Position, Range, ReferenceContext, TextDocumentIdentifier
};
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\Tests\Server\ServerTestCase; use LanguageServer\Tests\Server\ServerTestCase;
class GlobalFallbackTest extends ServerTestCase class GlobalFallbackTest extends ServerTestCase
@ -19,7 +22,7 @@ class GlobalFallbackTest extends ServerTestCase
{ {
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex); $projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$projectIndex->setComplete(); $projectIndex->setComplete();
$definitionResolver = ParserResourceFactory::getDefinitionResolver($projectIndex); $definitionResolver = new TolerantDefinitionResolver($projectIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream); $client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver); $this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex); $this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex);

View File

@ -8,8 +8,8 @@ use Exception;
use LanguageServer\Definition; use LanguageServer\Definition;
use LanguageServer\Index\Index; use LanguageServer\Index\Index;
use LanguageServer\ParserKind; use LanguageServer\ParserKind;
use LanguageServer\ParserResourceFactory;
use LanguageServer\PhpDocument; use LanguageServer\PhpDocument;
use LanguageServer\TolerantDefinitionResolver;
use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -60,8 +60,14 @@ class ValidationTest extends TestCase
echo "Test file: " . realpath($testCaseFile) . PHP_EOL; echo "Test file: " . realpath($testCaseFile) . PHP_EOL;
$fileContents = file_get_contents($testCaseFile); $fileContents = file_get_contents($testCaseFile);
$expectedValues = $this->getExpectedTestValues($testCaseFile, $frameworkName, $fileContents); $actualValues = $this->getActualTestValues($testCaseFile, $fileContents);
$actualValues = $this->getActualTestValues($testCaseFile, $frameworkName, $fileContents);
$outputFile = getExpectedValuesFile($testCaseFile);
if (!file_exists($outputFile)) {
file_put_contents(json_encode($actualValues, JSON_PRETTY_PRINT));
}
$expectedValues = (array)json_decode(file_get_contents($outputFile));
try { try {
$this->assertEquals($expectedValues['definitions'], $actualValues['definitions']); $this->assertEquals($expectedValues['definitions'], $actualValues['definitions']);
@ -81,56 +87,11 @@ class ValidationTest extends TestCase
} }
} }
/** private function getActualTestValues($filename, $fileContents): array {
* @param $filename
* @param $frameworkName
* @param $fileContents
* @return array
*/
private function getExpectedTestValues($filename, $frameworkName, $fileContents) {
global $parserKind;
$parserKind = ParserKind::PHP_PARSER;
$outputFile = getExpectedValuesFile($filename);
if (file_exists($outputFile)) {
return (array)json_decode(file_get_contents($outputFile));
}
$index = new Index(); $index = new Index();
$parser = ParserResourceFactory::getParser(); $parser = new Tolerant\Parser();
$docBlockFactory = DocBlockFactory::createInstance(); $docBlockFactory = DocBlockFactory::createInstance();
$definitionResolver = ParserResourceFactory::getDefinitionResolver($index); $definitionResolver = new TolerantDefinitionResolver($index);
try {
$document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver);
} catch (\Throwable $e) {
$this->markTestSkipped('Baseline parser failed: '. $e->getTraceAsString());
}
if ($document->getStmts() === null) {
$this->markTestSkipped('Baseline parser failed: null AST');
}
$expectedRefs = $index->references;
$this->filterSkippedReferences($expectedRefs);
$expectedDefs = $this->getTestValuesFromDefs($document->getDefinitions());
$refsAndDefs = array(
'references' => json_decode(json_encode($expectedRefs)),
'definitions' => json_decode(json_encode($expectedDefs))
);
return $refsAndDefs;
}
private function getActualTestValues($filename, $frameworkName, $fileContents): array {
global $parserKind;
$parserKind = ParserKind::TOLERANT_PHP_PARSER;
$index = new Index();
$parser = ParserResourceFactory::getParser();
$docBlockFactory = DocBlockFactory::createInstance();
$definitionResolver = ParserResourceFactory::getDefinitionResolver($index);
$document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver); $document = new PhpDocument($filename, $fileContents, $index, $parser, $docBlockFactory, $definitionResolver);