1
0
Fork 0

Cleaned up code. Fixed tests

pull/31/head
Stephan Unverwerth 2016-09-18 21:51:23 +02:00
parent d597eeebf6
commit a34426fb4e
6 changed files with 85 additions and 64 deletions

View File

@ -75,12 +75,12 @@ class LanguageServer extends \AdvancedJsonRpc\Dispatcher
/**
* The initialize request is sent as the first request from the client to the server.
*
* @param string $rootPath The rootPath of the workspace. Is null if no folder is open.
* @param int $processId The process Id of the parent process that started the server.
* @param ClientCapabilities $capabilities The capabilities provided by the client (editor)
* @param string $rootPath The rootPath of the workspace. Is null if no folder is open.
* @return InitializeResult
*/
public function initialize(string $rootPath, int $processId, ClientCapabilities $capabilities): InitializeResult
public function initialize(int $processId, ClientCapabilities $capabilities, string $rootPath = null): InitializeResult
{
// start building project index
if ($rootPath) {
@ -124,7 +124,7 @@ class LanguageServer extends \AdvancedJsonRpc\Dispatcher
/**
* Parses workspace files, one at a time.
*
* @param string $rootPath The rootPath of the workspace. Is null if no folder is open.
* @param string $rootPath The rootPath of the workspace.
* @return void
*/
private function indexProject(string $rootPath)
@ -136,26 +136,29 @@ class LanguageServer extends \AdvancedJsonRpc\Dispatcher
foreach($files as $file) {
$fileList = array_merge($fileList, $file);
}
$numTotalFiles = count($fileList);
$processFile = function() use (&$fileList, &$processFile, &$rootPath){
$startTime = microtime(true);
$processFile = function() use (&$fileList, &$processFile, $rootPath, $numTotalFiles, $startTime) {
if ($file = array_pop($fileList)) {
$uri = 'file://'.($file[0] == '/' || $file[0] == '\\' ? '' : '/').str_replace('\\', '/', $file);
$numFiles = count($fileList);
if (($numFiles % 100) == 0) {
$this->client->window->logMessage(3, $numFiles.' PHP files remaining.');
}
$fileNum = $numTotalFiles - count($fileList);
$shortName = substr($file, strlen($rootPath)+1);
$this->client->window->logMessage(3, "Parsing file $fileNum/$numTotalFiles: $shortName.");
$this->project->getDocument($uri)->updateAst(file_get_contents($file));
Loop\nextTick($processFile);
Loop\setTimeout($processFile, 0);
}
else {
$this->client->window->logMessage(3, 'All PHP files parsed.');
$duration = (int)(microtime(true) - $startTime);
$this->client->window->logMessage(3, "All PHP files parsed in $duration seconds.");
}
};
Loop\nextTick($processFile);
Loop\setTimeout($processFile, 0);
}
}

View File

@ -8,8 +8,26 @@ use PhpParser\NodeVisitor\NameResolver;
class Project
{
/**
* An associative array [string => PhpDocument]
* that maps URIs to loaded PhpDocuments
*
* @var array
*/
private $documents;
/**
* Instance of the PHP parser
*
* @var ParserAbstract
*/
private $parser;
/**
* Reference to the language server client interface
*
* @var LanguageClient
*/
private $client;
public function __construct(LanguageClient $client)

View File

@ -30,32 +30,36 @@ class ProtocolStreamReader implements ProtocolReader
{
$this->input = $input;
Loop\addReadStream($this->input, function() {
$c = fgetc($this->input);
$this->buffer .= $c;
switch ($this->parsingMode) {
case ParsingMode::HEADERS:
if ($this->buffer === "\r\n") {
$this->parsingMode = ParsingMode::BODY;
$this->contentLength = (int)$this->headers['Content-Length'];
$this->buffer = '';
} else if (substr($this->buffer, -2) === "\r\n") {
$parts = explode(':', $this->buffer);
$this->headers[$parts[0]] = trim($parts[1]);
$this->buffer = '';
}
break;
case ParsingMode::BODY:
if (strlen($this->buffer) === $this->contentLength) {
if (isset($this->listener)) {
$msg = new Message(MessageBody::parse($this->buffer), $this->headers);
$listener = $this->listener;
$listener($msg);
while(($c = fgetc($this->input)) !== false) {
$this->buffer .= $c;
switch ($this->parsingMode) {
case ParsingMode::HEADERS:
if ($this->buffer === "\r\n") {
$this->parsingMode = ParsingMode::BODY;
$this->contentLength = (int)$this->headers['Content-Length'];
$this->buffer = '';
} else if (substr($this->buffer, -2) === "\r\n") {
$parts = explode(':', $this->buffer);
$this->headers[$parts[0]] = trim($parts[1]);
$this->buffer = '';
}
$this->parsingMode = ParsingMode::HEADERS;
$this->headers = [];
$this->buffer = '';
}
break;
break;
case ParsingMode::BODY:
if (strlen($this->buffer) === $this->contentLength) {
if (isset($this->listener)) {
$msg = new Message(MessageBody::parse($this->buffer), $this->headers);
$listener = $this->listener;
$listener($msg);
}
$this->parsingMode = ParsingMode::HEADERS;
$this->headers = [];
$this->buffer = '';
// after reading a full message, leave to allow different tasks to run
return;
}
break;
}
}
});
}

View File

@ -31,6 +31,11 @@ class Workspace
*/
private $client;
/**
* The current project database
*
* @var Project
*/
private $project;
public function __construct(Project $project, LanguageClient $client)
@ -50,24 +55,4 @@ class Workspace
{
return $this->project->findSymbols($query);
}
/**
* A notification sent from the client to the server to signal the change of configuration settings.
*
* @param The actual changed settings
* @return void
*/
public function didChangeConfiguration($settings)
{
}
/**
* The document change notification is sent from the client to the server to signal changes to a text document.
*
* @param \LanguageServer\Protocol\FileEvent[] $textDocument
* @return void
*/
public function didChangeWatchedFiles(array $changes)
{
}
}

View File

@ -4,6 +4,9 @@ declare(strict_types = 1);
namespace LanguageServer;
use PhpParser\{NodeVisitorAbstract, Node};
use PhpParser\Builder\Function_;
use PhpParser\Node\Stmt\ClassMethod;
use LanguageServer\Protocol\{SymbolInformation, SymbolKind, Range, Position, Location};
class SymbolFinder extends NodeVisitorAbstract
@ -75,7 +78,7 @@ class SymbolFinder extends NodeVisitorAbstract
}
// if we enter a method or function, increase the function counter
if ($class === Node\Stmt\Function_::class || $class === Node\Stmt\ClassMethod::class) {
if ($node instanceof Function_ || $node instanceof ClassMethod) {
$this->functionCount++;
}
@ -107,8 +110,7 @@ class SymbolFinder extends NodeVisitorAbstract
array_pop($this->nameStack);
// if we leave a method or function, decrease the function counter
$class = get_class($node);
if ($class === Node\Stmt\Function_::class || $class === Node\Stmt\ClassMethod::class) {
if ($node instanceof Function_ || $node instanceof ClassMethod) {
$this->functionCount--;
}
}

View File

@ -5,7 +5,7 @@ namespace LanguageServer\Tests\Server;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{Server, Client, LanguageClient};
use LanguageServer\{Server, Client, LanguageClient, Project, PhpDocument};
use LanguageServer\Protocol\{TextDocumentItem, TextDocumentIdentifier, SymbolKind, DiagnosticSeverity, FormattingOptions};
use AdvancedJsonRpc\{Request as RequestBody, Response as ResponseBody};
@ -13,7 +13,9 @@ class TextDocumentTest extends TestCase
{
public function testDocumentSymbol()
{
$textDocument = new Server\TextDocument(new LanguageClient(new MockProtocolStream()));
$client = new LanguageClient(new MockProtocolStream());
$project = new Project($client);
$textDocument = new Server\TextDocument($project, $client);
// Trigger parsing of source
$textDocumentItem = new TextDocumentItem();
$textDocumentItem->uri = 'whatever';
@ -94,7 +96,7 @@ class TextDocumentTest extends TestCase
]
]
],
'containerName' => null
'containerName' => 'TestClass'
],
[
'name' => 'TestTrait',
@ -151,7 +153,11 @@ class TextDocumentTest extends TestCase
$this->args = func_get_args();
}
};
$textDocument = new Server\TextDocument($client);
$project = new Project($client);
$textDocument = new Server\TextDocument($project, $client);
// Trigger parsing of source
$textDocumentItem = new TextDocumentItem();
$textDocumentItem->uri = 'whatever';
@ -182,7 +188,10 @@ class TextDocumentTest extends TestCase
public function testFormatting()
{
$textDocument = new Server\TextDocument(new LanguageClient(new MockProtocolStream()));
$client = new LanguageClient(new MockProtocolStream());
$project = new Project($client);
$textDocument = new Server\TextDocument($project, $client);
// Trigger parsing of source
$textDocumentItem = new TextDocumentItem();
$textDocumentItem->uri = 'whatever';