parent
49245fd4d3
commit
106aa24b5d
|
@ -42,8 +42,8 @@ class ProjectIndex extends AbstractAggregateIndex
|
|||
*/
|
||||
public function getIndexForUri(string $uri): Index
|
||||
{
|
||||
if (preg_match('/\/vendor\/(\w+\/\w+)\//', $uri, $matches)) {
|
||||
$packageName = $matches[0];
|
||||
if (preg_match('/\/vendor\/([^\/]+\/[^\/]+)\//', $uri, $matches)) {
|
||||
$packageName = $matches[1];
|
||||
return $this->dependenciesIndex->getDependencyIndex($packageName);
|
||||
}
|
||||
return $this->sourceIndex;
|
||||
|
|
|
@ -81,6 +81,30 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
|||
*/
|
||||
protected $documentLoader;
|
||||
|
||||
/**
|
||||
* The parsed composer.json file in the project, if any
|
||||
*
|
||||
* @var \stdClass
|
||||
*/
|
||||
protected $composerJson;
|
||||
|
||||
/**
|
||||
* The parsed composer.lock file in the project, if any
|
||||
*
|
||||
* @var \stdClass
|
||||
*/
|
||||
protected $composerLock;
|
||||
|
||||
/**
|
||||
* @var GlobalIndex
|
||||
*/
|
||||
protected $globalIndex;
|
||||
|
||||
/**
|
||||
* @var DefinitionResolver
|
||||
*/
|
||||
protected $definitionResolver;
|
||||
|
||||
/**
|
||||
* @param PotocolReader $reader
|
||||
* @param ProtocolWriter $writer
|
||||
|
@ -144,8 +168,6 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
|||
{
|
||||
return coroutine(function () use ($capabilities, $rootPath, $processId) {
|
||||
|
||||
yield null;
|
||||
|
||||
if ($capabilities->xfilesProvider) {
|
||||
$this->filesFinder = new ClientFilesFinder($this->client);
|
||||
} else {
|
||||
|
@ -158,31 +180,53 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
|||
$this->contentRetriever = new FileSystemContentRetriever;
|
||||
}
|
||||
|
||||
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
|
||||
$dependenciesIndex = new DependenciesIndex;
|
||||
$sourceIndex = new Index;
|
||||
$projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex);
|
||||
$stubsIndex = StubsIndex::read();
|
||||
$globalIndex = new GlobalIndex($stubsIndex, $projectIndex);
|
||||
$this->globalIndex = new GlobalIndex($stubsIndex, $projectIndex);
|
||||
|
||||
// The DefinitionResolver should look in stubs, the project source and dependencies
|
||||
$definitionResolver = new DefinitionResolver($globalIndex);
|
||||
$this->definitionResolver = new DefinitionResolver($this->globalIndex);
|
||||
|
||||
$this->documentLoader = new PhpDocumentLoader(
|
||||
$this->contentRetriever,
|
||||
$projectIndex,
|
||||
$definitionResolver
|
||||
$this->definitionResolver
|
||||
);
|
||||
|
||||
if ($rootPath !== null) {
|
||||
$this->index($rootPath)->otherwise('\\LanguageServer\\crash');
|
||||
yield $this->index($rootPath)->otherwise('LanguageServer\\crash');
|
||||
}
|
||||
|
||||
// Find composer.json
|
||||
if ($this->composerJson === null) {
|
||||
$composerJsonFiles = yield $this->filesFinder->find(Path::makeAbsolute('**/composer.json', $rootPath));
|
||||
if (!empty($composerJsonFiles)) {
|
||||
$this->composerJson = json_decode(yield $this->contentRetriever->retrieve($composerJsonFiles[0]));
|
||||
}
|
||||
}
|
||||
// Find composer.lock
|
||||
if ($this->composerLock === null) {
|
||||
$composerLockFiles = yield $this->filesFinder->find(Path::makeAbsolute('**/composer.lock', $rootPath));
|
||||
if (!empty($composerLockFiles)) {
|
||||
$this->composerLock = json_decode(yield $this->contentRetriever->retrieve($composerLockFiles[0]));
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->textDocument === null) {
|
||||
$this->textDocument = new Server\TextDocument(
|
||||
$this->documentLoader,
|
||||
$definitionResolver,
|
||||
$this->definitionResolver,
|
||||
$this->client,
|
||||
$globalIndex
|
||||
$this->globalIndex,
|
||||
$this->composerJson,
|
||||
$this->composerLock
|
||||
);
|
||||
// workspace/symbol should only look inside the project source and dependencies
|
||||
$this->workspace = new Server\Workspace($projectIndex, $this->client);
|
||||
}
|
||||
if ($this->workspace === null) {
|
||||
$this->workspace = new Server\Workspace($projectIndex, $dependenciesIndex, $sourceIndex, $this->composerLock, $this->documentLoader);
|
||||
}
|
||||
|
||||
$serverCapabilities = new ServerCapabilities();
|
||||
// Ask the client to return always full documents (because we need to rebuild the AST from scratch)
|
||||
|
@ -203,6 +247,10 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
|||
$serverCapabilities->completionProvider = new CompletionOptions;
|
||||
$serverCapabilities->completionProvider->resolveProvider = false;
|
||||
$serverCapabilities->completionProvider->triggerCharacters = ['$', '>'];
|
||||
// Support global references
|
||||
$serverCapabilities->xworkspaceReferencesProvider = true;
|
||||
$serverCapabilities->xdefinitionProvider = true;
|
||||
$serverCapabilities->xdependenciesProvider = true;
|
||||
|
||||
return new InitializeResult($serverCapabilities);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace LanguageServer\Protocol;
|
||||
|
||||
class DependencyReference
|
||||
{
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
public $hints;
|
||||
|
||||
/**
|
||||
* @var object
|
||||
*/
|
||||
public $attributes;
|
||||
|
||||
/**
|
||||
* @param object $attributes
|
||||
* @param mixed $hints
|
||||
*/
|
||||
public function __construct($attributes = null, $hints = null)
|
||||
{
|
||||
$this->attributes = $attributes ?? new \stdClass;
|
||||
$this->hints = $hints;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace LanguageServer\Protocol;
|
||||
|
||||
/**
|
||||
* Metadata about the symbol that can be used to identify or locate its
|
||||
* definition.
|
||||
*/
|
||||
class ReferenceInformation
|
||||
{
|
||||
/**
|
||||
* The location in the workspace where the `symbol` is referenced.
|
||||
*
|
||||
* @var Location
|
||||
*/
|
||||
public $reference;
|
||||
|
||||
/**
|
||||
* Metadata about the symbol that can be used to identify or locate its
|
||||
* definition.
|
||||
*
|
||||
* @var SymbolDescriptor
|
||||
*/
|
||||
public $symbol;
|
||||
|
||||
/**
|
||||
* @param Location $reference The location in the workspace where the `symbol` is referenced.
|
||||
* @param SymbolDescriptor $symbol Metadata about the symbol that can be used to identify or locate its definition.
|
||||
*/
|
||||
public function __construct(Location $reference = null, SymbolDescriptor $symbol = null)
|
||||
{
|
||||
$this->reference = $reference;
|
||||
$this->symbol = $symbol;
|
||||
}
|
||||
}
|
|
@ -108,4 +108,25 @@ class ServerCapabilities
|
|||
* @var bool|null
|
||||
*/
|
||||
public $renameProvider;
|
||||
|
||||
/**
|
||||
* The server provides workspace references exporting support.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $xworkspaceReferencesProvider;
|
||||
|
||||
/**
|
||||
* The server provides extended text document definition support.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $xdefinitionProvider;
|
||||
|
||||
/**
|
||||
* The server provides workspace dependencies support.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $dependenciesProvider;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace LanguageServer\Protocol;
|
||||
|
||||
class SymbolDescriptor extends SymbolInformation
|
||||
{
|
||||
/**
|
||||
* The fully qualified structural element name, a globally unique identifier for the symbol.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $fqsen;
|
||||
|
||||
/**
|
||||
* A package from the composer.lock file or the contents of the composer.json
|
||||
* Example: https://github.com/composer/composer/blob/master/composer.lock#L10
|
||||
* Available fields may differ
|
||||
*
|
||||
* @var object|null
|
||||
*/
|
||||
public $package;
|
||||
|
||||
/**
|
||||
* @param string $fqsen The fully qualified structural element name, a globally unique identifier for the symbol.
|
||||
* @param object $package A package from the composer.lock file or the contents of the composer.json
|
||||
*/
|
||||
public function __construct(string $fqsen = null, $package = null)
|
||||
{
|
||||
$this->fqsen = $fqsen;
|
||||
$this->package = $package;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace LanguageServer\Protocol;
|
||||
|
||||
class SymbolLocationInformation
|
||||
{
|
||||
/**
|
||||
* The location where the symbol is defined, if any.
|
||||
*
|
||||
* @var Location|null
|
||||
*/
|
||||
public $location;
|
||||
|
||||
/**
|
||||
* Metadata about the symbol that can be used to identify or locate its
|
||||
* definition.
|
||||
*
|
||||
* @var SymbolDescriptor
|
||||
*/
|
||||
public $symbol;
|
||||
|
||||
/**
|
||||
* @param SymbolDescriptor $symbol The location where the symbol is defined, if any
|
||||
* @param Location $location Metadata about the symbol that can be used to identify or locate its definition
|
||||
*/
|
||||
public function __construct(SymbolDescriptor $symbol = null, Location $location = null)
|
||||
{
|
||||
$this->symbol = $symbol;
|
||||
$this->location = $location;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ use PhpParser\{Node, NodeTraverser};
|
|||
use LanguageServer\{LanguageClient, PhpDocumentLoader, PhpDocument, DefinitionResolver, CompletionProvider};
|
||||
use LanguageServer\NodeVisitor\VariableReferencesCollector;
|
||||
use LanguageServer\Protocol\{
|
||||
SymbolLocationInformation,
|
||||
SymbolDescriptor,
|
||||
TextDocumentItem,
|
||||
TextDocumentIdentifier,
|
||||
VersionedTextDocumentIdentifier,
|
||||
|
@ -39,44 +41,58 @@ class TextDocument
|
|||
*
|
||||
* @var \LanguageServer\LanguageClient
|
||||
*/
|
||||
private $client;
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var Project
|
||||
*/
|
||||
private $project;
|
||||
protected $project;
|
||||
|
||||
/**
|
||||
* @var PrettyPrinter
|
||||
*/
|
||||
private $prettyPrinter;
|
||||
protected $prettyPrinter;
|
||||
|
||||
/**
|
||||
* @var DefinitionResolver
|
||||
*/
|
||||
private $definitionResolver;
|
||||
protected $definitionResolver;
|
||||
|
||||
/**
|
||||
* @var CompletionProvider
|
||||
*/
|
||||
private $completionProvider;
|
||||
protected $completionProvider;
|
||||
|
||||
/**
|
||||
* @var ReadableIndex
|
||||
*/
|
||||
private $index;
|
||||
protected $index;
|
||||
|
||||
/**
|
||||
* @var \stdClass|null
|
||||
*/
|
||||
protected $composerJson;
|
||||
|
||||
/**
|
||||
* @var \stdClass|null
|
||||
*/
|
||||
protected $composerLock;
|
||||
|
||||
/**
|
||||
* @param PhpDocumentLoader $documentLoader
|
||||
* @param DefinitionResolver $definitionResolver
|
||||
* @param LanguageClient $client
|
||||
* @param ReadableIndex $index
|
||||
* @param \stdClass $composerJson
|
||||
* @param \stdClass $composerLock
|
||||
*/
|
||||
public function __construct(
|
||||
PhpDocumentLoader $documentLoader,
|
||||
DefinitionResolver $definitionResolver,
|
||||
LanguageClient $client,
|
||||
ReadableIndex $index
|
||||
ReadableIndex $index,
|
||||
\stdClass $composerJson = null,
|
||||
\stdClass $composerLock = null
|
||||
) {
|
||||
$this->documentLoader = $documentLoader;
|
||||
$this->client = $client;
|
||||
|
@ -84,6 +100,8 @@ class TextDocument
|
|||
$this->definitionResolver = $definitionResolver;
|
||||
$this->completionProvider = new CompletionProvider($this->definitionResolver, $index);
|
||||
$this->index = $index;
|
||||
$this->composerJson = $composerJson;
|
||||
$this->composerLock = $composerLock;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,7 +265,14 @@ class TextDocument
|
|||
if ($node === null) {
|
||||
return [];
|
||||
}
|
||||
// Handle definition nodes
|
||||
$fqn = DefinitionResolver::getDefinedFqn($node);
|
||||
if ($fqn !== null) {
|
||||
$def = $this->index->getDefinition($fqn);
|
||||
} else {
|
||||
// Handle reference nodes
|
||||
$def = $this->definitionResolver->resolveReferenceNodeToDefinition($node);
|
||||
}
|
||||
if (
|
||||
$def === null
|
||||
|| $def->symbolInformation === null
|
||||
|
@ -317,4 +342,61 @@ class TextDocument
|
|||
return $this->completionProvider->provideCompletion($document, $position);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is the same as textDocument/definition, except that
|
||||
*
|
||||
* The method returns metadata about the definition (the same metadata that workspace/xreferences searches for).
|
||||
* The concrete location to the definition (location field) is optional. This is useful because the language server
|
||||
* might not be able to resolve a goto definition request to a concrete location (e.g. due to lack of dependencies)
|
||||
* but still may know some information about it.
|
||||
*
|
||||
* @param TextDocumentIdentifier $textDocument The text document
|
||||
* @param Position $position The position inside the text document
|
||||
* @return Promise <SymbolLocationInformation[]>
|
||||
*/
|
||||
public function xdefinition(TextDocumentIdentifier $textDocument, Position $position): Promise
|
||||
{
|
||||
return coroutine(function () use ($textDocument, $position) {
|
||||
$document = yield $this->documentLoader->getOrLoad($textDocument->uri);
|
||||
$node = $document->getNodeAtPosition($position);
|
||||
if ($node === null) {
|
||||
return [];
|
||||
}
|
||||
// Handle definition nodes
|
||||
$fqn = DefinitionResolver::getDefinedFqn($node);
|
||||
if ($fqn !== null) {
|
||||
$def = $this->index->getDefinition($fqn);
|
||||
} else {
|
||||
// Handle reference nodes
|
||||
$def = $this->definitionResolver->resolveReferenceNodeToDefinition($node);
|
||||
}
|
||||
if (
|
||||
$def === null
|
||||
|| $def->symbolInformation === null
|
||||
|| Uri\parse($def->symbolInformation->location->uri)['scheme'] === 'phpstubs'
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
$symbol = new SymbolDescriptor;
|
||||
foreach (get_object_vars($def->symbolInformation) as $prop => $val) {
|
||||
$symbol->$prop = $val;
|
||||
}
|
||||
$symbol->fqsen = $def->fqn;
|
||||
if (preg_match('/\/vendor\/([^\/]+\/[^\/]+)\//', $def->symbolInformation->location->uri, $matches) && $this->composerLock !== null) {
|
||||
// Definition is inside a dependency
|
||||
$packageName = $matches[1];
|
||||
foreach ($this->composerLock->packages as $package) {
|
||||
if ($package->name === $packageName) {
|
||||
$symbol->package = $package;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ($this->composerJson !== null) {
|
||||
// Definition belongs to a root package
|
||||
$symbol->package = $this->composerJson;
|
||||
}
|
||||
return [new SymbolLocationInformation($symbol, $symbol->location)];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,22 +3,17 @@ declare(strict_types = 1);
|
|||
|
||||
namespace LanguageServer\Server;
|
||||
|
||||
use LanguageServer\{LanguageClient, Project};
|
||||
use LanguageServer\Index\ProjectIndex;
|
||||
use LanguageServer\Protocol\SymbolInformation;
|
||||
use LanguageServer\{LanguageClient, Project, PhpDocumentLoader};
|
||||
use LanguageServer\Index\{ProjectIndex, DependenciesIndex, Index};
|
||||
use LanguageServer\Protocol\{SymbolInformation, SymbolDescriptor, ReferenceInformation, DependencyReference, Location};
|
||||
use Sabre\Event\Promise;
|
||||
use function Sabre\Event\coroutine;
|
||||
|
||||
/**
|
||||
* Provides method handlers for all workspace/* methods
|
||||
*/
|
||||
class Workspace
|
||||
{
|
||||
/**
|
||||
* The lanugage client object to call methods on the client
|
||||
*
|
||||
* @var \LanguageServer\LanguageClient
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* The symbol index for the workspace
|
||||
*
|
||||
|
@ -27,12 +22,39 @@ class Workspace
|
|||
private $index;
|
||||
|
||||
/**
|
||||
* @param ProjectIndex $index Index that is searched on a workspace/symbol request
|
||||
* @var DependenciesIndex
|
||||
*/
|
||||
public function __construct(ProjectIndex $index, LanguageClient $client)
|
||||
private $dependenciesIndex;
|
||||
|
||||
/**
|
||||
* @var Index
|
||||
*/
|
||||
private $sourceIndex;
|
||||
|
||||
/**
|
||||
* @var \stdClass
|
||||
*/
|
||||
public $composerLock;
|
||||
|
||||
/**
|
||||
* @var PhpDocumentLoader
|
||||
*/
|
||||
public $documentLoader;
|
||||
|
||||
/**
|
||||
* @param ProjectIndex $index Index that is searched on a workspace/symbol request
|
||||
* @param DependenciesIndex $dependenciesIndex Index that is used on a workspace/xreferences request
|
||||
* @param DependenciesIndex $sourceIndex Index that is used on a workspace/xreferences request
|
||||
* @param \stdClass $composerLock The parsed composer.lock of the project, if any
|
||||
* @param PhpDocumentLoader $documentLoader PhpDocumentLoader instance to load documents
|
||||
*/
|
||||
public function __construct(ProjectIndex $index, DependenciesIndex $dependenciesIndex, Index $sourceIndex, \stdClass $composerLock = null, PhpDocumentLoader $documentLoader)
|
||||
{
|
||||
$this->sourceIndex = $sourceIndex;
|
||||
$this->index = $index;
|
||||
$this->client = $client;
|
||||
$this->dependenciesIndex = $dependenciesIndex;
|
||||
$this->composerLock = $composerLock;
|
||||
$this->documentLoader = $documentLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,4 +73,90 @@ class Workspace
|
|||
}
|
||||
return $symbols;
|
||||
}
|
||||
|
||||
/**
|
||||
* The workspace references request is sent from the client to the server to locate project-wide references to a symbol given its description / metadata.
|
||||
*
|
||||
* @param SymbolDescriptor $query Partial metadata about the symbol that is being searched for.
|
||||
* @param string[] $files An optional list of files to restrict the search to.
|
||||
* @return ReferenceInformation[]
|
||||
*/
|
||||
public function xreferences($query, array $files = null): Promise
|
||||
{
|
||||
return coroutine(function () use ($query, $files) {
|
||||
if ($this->composerLock === null) {
|
||||
return [];
|
||||
}
|
||||
/** Map from URI to array of referenced FQNs in dependencies */
|
||||
$refs = [];
|
||||
// Get all references TO dependencies
|
||||
$fqns = isset($query->fqsen) ? [$query->fqsen] : array_values($this->dependenciesIndex->getDefinitions());
|
||||
foreach ($fqns as $fqn) {
|
||||
foreach ($this->sourceIndex->getReferenceUris($fqn) as $uri) {
|
||||
if (!isset($refs[$uri])) {
|
||||
$refs[$uri] = [];
|
||||
}
|
||||
if (array_search($uri, $refs[$uri]) === false) {
|
||||
$refs[$uri][] = $fqn;
|
||||
}
|
||||
}
|
||||
}
|
||||
$refInfos = [];
|
||||
foreach ($refs as $uri => $fqns) {
|
||||
foreach ($fqns as $fqn) {
|
||||
$def = $this->dependenciesIndex->getDefinition($fqn);
|
||||
$symbol = new SymbolDescriptor;
|
||||
$symbol->fqsen = $fqn;
|
||||
foreach (get_object_vars($def->symbolInformation) as $prop => $val) {
|
||||
$symbol->$prop = $val;
|
||||
}
|
||||
// Find out package name
|
||||
preg_match('/\/vendor\/([^\/]+\/[^\/]+)\//', $def->symbolInformation->location->uri, $matches);
|
||||
$packageName = $matches[1];
|
||||
foreach ($this->composerLock->packages as $package) {
|
||||
if ($package->name === $packageName) {
|
||||
$symbol->package = $package;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If there was no FQSEN provided, check if query attributes match
|
||||
if (!isset($query->fqsen)) {
|
||||
$matches = true;
|
||||
foreach (get_object_vars($query) as $prop => $val) {
|
||||
if ($query->$prop != $symbol->$prop) {
|
||||
$matches = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$matches) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$doc = yield $this->documentLoader->getOrLoad($uri);
|
||||
foreach ($doc->getReferenceNodesByFqn($fqn) as $node) {
|
||||
$refInfo = new ReferenceInformation;
|
||||
$refInfo->reference = Location::fromNode($node);
|
||||
$refInfo->symbol = $symbol;
|
||||
$refInfos[] = $refInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $refInfos;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DependencyReference[]
|
||||
*/
|
||||
public function xdependencies(): array
|
||||
{
|
||||
if ($this->composerLock === null) {
|
||||
return [];
|
||||
}
|
||||
$dependencyReferences = [];
|
||||
foreach ($this->composerLock->packages as $package) {
|
||||
$dependencyReferences[] = new DependencyReference($package);
|
||||
}
|
||||
return $dependencyReferences;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,9 @@ class LanguageServerTest extends TestCase
|
|||
$serverCapabilities->completionProvider = new CompletionOptions;
|
||||
$serverCapabilities->completionProvider->resolveProvider = false;
|
||||
$serverCapabilities->completionProvider->triggerCharacters = ['$', '>'];
|
||||
$serverCapabilities->xworkspaceReferencesProvider = true;
|
||||
$serverCapabilities->xdefinitionProvider = true;
|
||||
$serverCapabilities->xdependenciesProvider = true;
|
||||
|
||||
$this->assertEquals(new InitializeResult($serverCapabilities), $result);
|
||||
}
|
||||
|
|
|
@ -45,13 +45,15 @@ abstract class ServerTestCase extends TestCase
|
|||
|
||||
public function setUp()
|
||||
{
|
||||
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
|
||||
$sourceIndex = new Index;
|
||||
$dependenciesIndex = new DependenciesIndex;
|
||||
$projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex);
|
||||
|
||||
$definitionResolver = new DefinitionResolver($projectIndex);
|
||||
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
|
||||
$this->documentLoader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
|
||||
$this->textDocument = new Server\TextDocument($this->documentLoader, $definitionResolver, $client, $projectIndex);
|
||||
$this->workspace = new Server\Workspace($projectIndex, $client);
|
||||
$this->workspace = new Server\Workspace($projectIndex, $dependenciesIndex, $sourceIndex, null, $this->documentLoader);
|
||||
|
||||
$globalSymbolsUri = pathToUri(realpath(__DIR__ . '/../../fixtures/global_symbols.php'));
|
||||
$globalReferencesUri = pathToUri(realpath(__DIR__ . '/../../fixtures/global_references.php'));
|
||||
|
|
Loading…
Reference in New Issue