Linting (#107)
* Update travis config. * Add phpcs config file. * Exclude rules * Ignore failures in tests * Automatic fixes * Inline ParsingMode enum as class constants * Loosen FormatTest because of excluded rulepull/111/head
parent
83afa0c1b8
commit
5ecab683eb
|
@ -11,6 +11,7 @@ install:
|
||||||
- composer install
|
- composer install
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
- vendor/bin/phpcs -n
|
||||||
- vendor/bin/phpunit --coverage-clover=coverage.xml
|
- vendor/bin/phpunit --coverage-clover=coverage.xml
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
|
|
|
@ -13,7 +13,7 @@ class TestClass
|
||||||
{
|
{
|
||||||
$testVariable = 123;
|
$testVariable = 123;
|
||||||
|
|
||||||
if ( empty($testParameter)){
|
if (empty($testParameter)){
|
||||||
echo 'Empty';
|
echo 'Empty';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="PHP Language Server">
|
||||||
|
<file>src</file>
|
||||||
|
<file>tests</file>
|
||||||
|
<rule ref="PSR2">
|
||||||
|
<exclude name="PSR2.Namespaces.UseDeclaration.MultipleDeclarations"/>
|
||||||
|
<exclude name="PSR2.ControlStructures.ElseIfDeclaration.NotAllowed"/>
|
||||||
|
<exclude name="PSR2.ControlStructures.ControlStructureSpacing.SpacingAfterOpenBrace"/>
|
||||||
|
</rule>
|
||||||
|
</ruleset>
|
|
@ -4,8 +4,8 @@ declare(strict_types = 1);
|
||||||
namespace LanguageServer;
|
namespace LanguageServer;
|
||||||
|
|
||||||
use LanguageServer\Protocol\ {
|
use LanguageServer\Protocol\ {
|
||||||
TextEdit,
|
TextEdit,
|
||||||
Range,
|
Range,
|
||||||
Position
|
Position
|
||||||
};
|
};
|
||||||
use PHP_CodeSniffer;
|
use PHP_CodeSniffer;
|
||||||
|
@ -42,9 +42,9 @@ abstract class Formatter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate position of last character.
|
* Calculate position of last character.
|
||||||
*
|
*
|
||||||
* @param string $content document as string
|
* @param string $content document as string
|
||||||
*
|
*
|
||||||
* @return \LanguageServer\Protocol\Position
|
* @return \LanguageServer\Protocol\Position
|
||||||
*/
|
*/
|
||||||
private static function calculateEndPosition(string $content): Position
|
private static function calculateEndPosition(string $content): Position
|
||||||
|
@ -54,10 +54,10 @@ abstract class Formatter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for PHP_CodeSniffer configuration file at given directory or its parents.
|
* Search for PHP_CodeSniffer configuration file at given directory or its parents.
|
||||||
* If no configuration found then PSR2 standard is loaded by default.
|
* If no configuration found then PSR2 standard is loaded by default.
|
||||||
*
|
*
|
||||||
* @param string $path path to file or directory
|
* @param string $path path to file or directory
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
private static function findConfiguration(string $path)
|
private static function findConfiguration(string $path)
|
||||||
|
@ -85,5 +85,4 @@ abstract class Formatter
|
||||||
$standard = PHP_CodeSniffer::getConfigData('default_standard') ?? 'PSR2';
|
$standard = PHP_CodeSniffer::getConfigData('default_standard') ?? 'PSR2';
|
||||||
return explode(',', $standard);
|
return explode(',', $standard);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
|
||||||
$startTime = microtime(true);
|
$startTime = microtime(true);
|
||||||
$fileNum = 0;
|
$fileNum = 0;
|
||||||
|
|
||||||
$processFile = function() use (&$fileList, &$fileNum, &$processFile, $numTotalFiles, $startTime) {
|
$processFile = function () use (&$fileList, &$fileNum, &$processFile, $numTotalFiles, $startTime) {
|
||||||
if ($fileNum < $numTotalFiles) {
|
if ($fileNum < $numTotalFiles) {
|
||||||
$file = $fileList[$fileNum];
|
$file = $fileList[$fileNum];
|
||||||
$uri = pathToUri($file);
|
$uri = pathToUri($file);
|
||||||
|
|
|
@ -178,7 +178,8 @@ class Project
|
||||||
* @param string $fqn The fully qualified name of the symbol
|
* @param string $fqn The fully qualified name of the symbol
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeSymbol(string $fqn) {
|
public function removeSymbol(string $fqn)
|
||||||
|
{
|
||||||
unset($this->symbols[$fqn]);
|
unset($this->symbols[$fqn]);
|
||||||
unset($this->references[$fqn]);
|
unset($this->references[$fqn]);
|
||||||
}
|
}
|
||||||
|
@ -207,7 +208,8 @@ class Project
|
||||||
* @param string $uri The URI
|
* @param string $uri The URI
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeReferenceUri(string $fqn, string $uri) {
|
public function removeReferenceUri(string $fqn, string $uri)
|
||||||
|
{
|
||||||
if (!isset($this->references[$fqn])) {
|
if (!isset($this->references[$fqn])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ namespace LanguageServer\Protocol;
|
||||||
/**
|
/**
|
||||||
* The kind of a completion entry.
|
* The kind of a completion entry.
|
||||||
*/
|
*/
|
||||||
abstract class CompletionItemKind {
|
abstract class CompletionItemKind
|
||||||
|
{
|
||||||
const TEXT = 1;
|
const TEXT = 1;
|
||||||
const METHOD = 2;
|
const METHOD = 2;
|
||||||
const FUNCTION = 3;
|
const FUNCTION = 3;
|
||||||
|
|
|
@ -4,10 +4,10 @@ namespace LanguageServer\Protocol;
|
||||||
|
|
||||||
class ReferenceContext
|
class ReferenceContext
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Include the declaration of the current symbol.
|
* Include the declaration of the current symbol.
|
||||||
*
|
*
|
||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
public $includeDeclaration;
|
public $includeDeclaration;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,13 @@ use AdvancedJsonRpc\Message as MessageBody;
|
||||||
use Sabre\Event\Loop;
|
use Sabre\Event\Loop;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
|
||||||
abstract class ParsingMode
|
|
||||||
{
|
|
||||||
const HEADERS = 1;
|
|
||||||
const BODY = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProtocolStreamReader implements ProtocolReader
|
class ProtocolStreamReader implements ProtocolReader
|
||||||
{
|
{
|
||||||
|
const PARSE_HEADERS = 1;
|
||||||
|
const PARSE_BODY = 2;
|
||||||
|
|
||||||
private $input;
|
private $input;
|
||||||
private $parsingMode = ParsingMode::HEADERS;
|
private $parsingMode = self::PARSE_HEADERS;
|
||||||
private $buffer = '';
|
private $buffer = '';
|
||||||
private $headers = [];
|
private $headers = [];
|
||||||
private $contentLength;
|
private $contentLength;
|
||||||
|
@ -29,7 +26,7 @@ class ProtocolStreamReader implements ProtocolReader
|
||||||
public function __construct($input)
|
public function __construct($input)
|
||||||
{
|
{
|
||||||
$this->input = $input;
|
$this->input = $input;
|
||||||
Loop\addReadStream($this->input, function() {
|
Loop\addReadStream($this->input, function () {
|
||||||
if (feof($this->input)) {
|
if (feof($this->input)) {
|
||||||
throw new RuntimeException('Stream is closed');
|
throw new RuntimeException('Stream is closed');
|
||||||
}
|
}
|
||||||
|
@ -37,9 +34,9 @@ class ProtocolStreamReader implements ProtocolReader
|
||||||
while (($c = fgetc($this->input)) !== false && $c !== '') {
|
while (($c = fgetc($this->input)) !== false && $c !== '') {
|
||||||
$this->buffer .= $c;
|
$this->buffer .= $c;
|
||||||
switch ($this->parsingMode) {
|
switch ($this->parsingMode) {
|
||||||
case ParsingMode::HEADERS:
|
case self::PARSE_HEADERS:
|
||||||
if ($this->buffer === "\r\n") {
|
if ($this->buffer === "\r\n") {
|
||||||
$this->parsingMode = ParsingMode::BODY;
|
$this->parsingMode = self::PARSE_BODY;
|
||||||
$this->contentLength = (int)$this->headers['Content-Length'];
|
$this->contentLength = (int)$this->headers['Content-Length'];
|
||||||
$this->buffer = '';
|
$this->buffer = '';
|
||||||
} else if (substr($this->buffer, -2) === "\r\n") {
|
} else if (substr($this->buffer, -2) === "\r\n") {
|
||||||
|
@ -48,14 +45,14 @@ class ProtocolStreamReader implements ProtocolReader
|
||||||
$this->buffer = '';
|
$this->buffer = '';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ParsingMode::BODY:
|
case self::PARSE_BODY:
|
||||||
if (strlen($this->buffer) === $this->contentLength) {
|
if (strlen($this->buffer) === $this->contentLength) {
|
||||||
if (isset($this->listener)) {
|
if (isset($this->listener)) {
|
||||||
$msg = new Message(MessageBody::parse($this->buffer), $this->headers);
|
$msg = new Message(MessageBody::parse($this->buffer), $this->headers);
|
||||||
$listener = $this->listener;
|
$listener = $this->listener;
|
||||||
$listener($msg);
|
$listener($msg);
|
||||||
}
|
}
|
||||||
$this->parsingMode = ParsingMode::HEADERS;
|
$this->parsingMode = self::PARSE_HEADERS;
|
||||||
$this->headers = [];
|
$this->headers = [];
|
||||||
$this->buffer = '';
|
$this->buffer = '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@ use InvalidArgumentException;
|
||||||
* @param string $pattern
|
* @param string $pattern
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function findFilesRecursive(string $path, string $pattern): array {
|
function findFilesRecursive(string $path, string $pattern): array
|
||||||
|
{
|
||||||
$dir = new \RecursiveDirectoryIterator($path);
|
$dir = new \RecursiveDirectoryIterator($path);
|
||||||
$ite = new \RecursiveIteratorIterator($dir);
|
$ite = new \RecursiveIteratorIterator($dir);
|
||||||
$files = new \RegexIterator($ite, $pattern, \RegexIterator::GET_MATCH);
|
$files = new \RegexIterator($ite, $pattern, \RegexIterator::GET_MATCH);
|
||||||
|
@ -29,7 +30,8 @@ function findFilesRecursive(string $path, string $pattern): array {
|
||||||
* @param string $filepath
|
* @param string $filepath
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function pathToUri(string $filepath): string {
|
function pathToUri(string $filepath): string
|
||||||
|
{
|
||||||
$filepath = trim(str_replace('\\', '/', $filepath), '/');
|
$filepath = trim(str_replace('\\', '/', $filepath), '/');
|
||||||
$parts = explode('/', $filepath);
|
$parts = explode('/', $filepath);
|
||||||
// Don't %-encode the colon after a Windows drive letter
|
// Don't %-encode the colon after a Windows drive letter
|
||||||
|
|
|
@ -36,4 +36,3 @@ class MockProtocolStream implements ProtocolReader, ProtocolWriter
|
||||||
$this->listener = $listener;
|
$this->listener = $listener;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ abstract class ServerTestCase extends TestCase
|
||||||
$this->project->loadDocument($globalReferencesUri);
|
$this->project->loadDocument($globalReferencesUri);
|
||||||
$this->project->loadDocument($useUri);
|
$this->project->loadDocument($useUri);
|
||||||
|
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
$this->definitionLocations = [
|
$this->definitionLocations = [
|
||||||
|
|
||||||
// Global
|
// Global
|
||||||
|
@ -166,6 +167,7 @@ abstract class ServerTestCase extends TestCase
|
||||||
0 => new Location($globalReferencesUri, new Range(new Position(10, 0), new Position(10, 13)))
|
0 => new Location($globalReferencesUri, new Range(new Position(10, 0), new Position(10, 13)))
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDefinitionLocation(string $fqn): Location
|
protected function getDefinitionLocation(string $fqn): Location
|
||||||
|
|
|
@ -9,13 +9,15 @@ use function LanguageServer\pathToUri;
|
||||||
|
|
||||||
class GlobalTest extends ServerTestCase
|
class GlobalTest extends ServerTestCase
|
||||||
{
|
{
|
||||||
public function testDefinitionFileBeginning() {
|
public function testDefinitionFileBeginning()
|
||||||
|
{
|
||||||
// |<?php
|
// |<?php
|
||||||
$result = $this->textDocument->definition(new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))), new Position(0, 0));
|
$result = $this->textDocument->definition(new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))), new Position(0, 0));
|
||||||
$this->assertEquals([], $result);
|
$this->assertEquals([], $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDefinitionEmptyResult() {
|
public function testDefinitionEmptyResult()
|
||||||
|
{
|
||||||
// namespace keyword
|
// namespace keyword
|
||||||
$result = $this->textDocument->definition(new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))), new Position(2, 4));
|
$result = $this->textDocument->definition(new TextDocumentIdentifier(pathToUri(realpath(__DIR__ . '/../../../../fixtures/references.php'))), new Position(2, 4));
|
||||||
$this->assertEquals([], $result);
|
$this->assertEquals([], $result);
|
||||||
|
|
|
@ -16,6 +16,7 @@ class DocumentSymbolTest extends ServerTestCase
|
||||||
// Request symbols
|
// Request symbols
|
||||||
$uri = pathToUri(realpath(__DIR__ . '/../../../fixtures/symbols.php'));
|
$uri = pathToUri(realpath(__DIR__ . '/../../../fixtures/symbols.php'));
|
||||||
$result = $this->textDocument->documentSymbol(new TextDocumentIdentifier($uri));
|
$result = $this->textDocument->documentSymbol(new TextDocumentIdentifier($uri));
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'),
|
new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'),
|
||||||
new SymbolInformation('TestClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestClass'), 'TestNamespace'),
|
new SymbolInformation('TestClass', SymbolKind::CLASS_, $this->getDefinitionLocation('TestNamespace\\TestClass'), 'TestNamespace'),
|
||||||
|
@ -28,5 +29,6 @@ class DocumentSymbolTest extends ServerTestCase
|
||||||
new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestNamespace\\TestInterface'), 'TestNamespace'),
|
new SymbolInformation('TestInterface', SymbolKind::INTERFACE, $this->getDefinitionLocation('TestNamespace\\TestInterface'), 'TestNamespace'),
|
||||||
new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\test_function()'), 'TestNamespace'),
|
new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('TestNamespace\\test_function()'), 'TestNamespace'),
|
||||||
], $result);
|
], $result);
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ class ParseErrorsTest extends TestCase
|
||||||
$this->textDocument = new Server\TextDocument($project, $client);
|
$this->textDocument = new Server\TextDocument($project, $client);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function openFile($file) {
|
private function openFile($file)
|
||||||
|
{
|
||||||
$textDocumentItem = new TextDocumentItem();
|
$textDocumentItem = new TextDocumentItem();
|
||||||
$textDocumentItem->uri = 'whatever';
|
$textDocumentItem->uri = 'whatever';
|
||||||
$textDocumentItem->languageId = 'php';
|
$textDocumentItem->languageId = 'php';
|
||||||
|
|
|
@ -16,6 +16,7 @@ class SymbolTest extends ServerTestCase
|
||||||
{
|
{
|
||||||
// Request symbols
|
// Request symbols
|
||||||
$result = $this->workspace->symbol('');
|
$result = $this->workspace->symbol('');
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
// Namespaced
|
// Namespaced
|
||||||
new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'),
|
new SymbolInformation('TEST_CONST', SymbolKind::CONSTANT, $this->getDefinitionLocation('TestNamespace\\TEST_CONST'), 'TestNamespace'),
|
||||||
|
@ -42,17 +43,20 @@ class SymbolTest extends ServerTestCase
|
||||||
new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('test_function()'), ''),
|
new SymbolInformation('test_function', SymbolKind::FUNCTION, $this->getDefinitionLocation('test_function()'), ''),
|
||||||
new SymbolInformation('whatever', SymbolKind::FUNCTION, $this->getDefinitionLocation('whatever()'), '')
|
new SymbolInformation('whatever', SymbolKind::FUNCTION, $this->getDefinitionLocation('whatever()'), '')
|
||||||
], $result);
|
], $result);
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testQueryFiltersResults()
|
public function testQueryFiltersResults()
|
||||||
{
|
{
|
||||||
// Request symbols
|
// Request symbols
|
||||||
$result = $this->workspace->symbol('testmethod');
|
$result = $this->workspace->symbol('testmethod');
|
||||||
|
// @codingStandardsIgnoreStart
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
new SymbolInformation('staticTestMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestNamespace\\TestClass::staticTestMethod()'), 'TestNamespace\\TestClass'),
|
new SymbolInformation('staticTestMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestNamespace\\TestClass::staticTestMethod()'), 'TestNamespace\\TestClass'),
|
||||||
new SymbolInformation('testMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestNamespace\\TestClass::testMethod()'), 'TestNamespace\\TestClass'),
|
new SymbolInformation('testMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestNamespace\\TestClass::testMethod()'), 'TestNamespace\\TestClass'),
|
||||||
new SymbolInformation('staticTestMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestClass::staticTestMethod()'), 'TestClass'),
|
new SymbolInformation('staticTestMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestClass::staticTestMethod()'), 'TestClass'),
|
||||||
new SymbolInformation('testMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestClass::testMethod()'), 'TestClass')
|
new SymbolInformation('testMethod', SymbolKind::METHOD, $this->getDefinitionLocation('TestClass::testMethod()'), 'TestClass')
|
||||||
], $result);
|
], $result);
|
||||||
|
// @codingStandardsIgnoreEnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue