1
0
Fork 0

fix(formatting): drop PHP CodeSniffer (#504)

At this point there are countless issues about the formatting done by CodeSniffer. It plain out doesn't work in many cases, overrides format options that are contributed by other extensions in VS Code and does not reuse any of our AST parsing. For that reason, I am starting to think there is no reason to keep it in here until we have proper pretty-printing support from https://github.com/Microsoft/tolerant-php-parser that actually reuses our ASTs and can work while editing. For people who want to use CodeSniffer to format their code, there could be a standalone CodeSniffer language server (like there is a TSLint language server and ESLint language server). As said, we don't reuse our state anyway.

BREAKING CHANGE: removes formatting support

closes #501
closes #474
closes #473
closes #468
closes #450
closes #445
closes #443
closes #423
closes #343
closes #296
closes #293
closes #499
closes #471
pull/517/head v5.0.0
Felix Becker 2017-11-04 23:57:51 -07:00 committed by GitHub
parent e9fc97d430
commit f00fd1b62c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2 additions and 259 deletions

View File

@ -42,9 +42,6 @@ For Parameters, it will return the `@param` tag.
The query is matched case-insensitively against the fully qualified name of the symbol. The query is matched case-insensitively against the fully qualified name of the symbol.
Non-Standard: An empty query will return _all_ symbols found in the workspace. Non-Standard: An empty query will return _all_ symbols found in the workspace.
### [Document Formatting](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#document-formatting-request)
![Document Formatting demo](images/formatDocument.gif)
### Error reporting through [Publish Diagnostics](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#publishdiagnostics-notification) ### Error reporting through [Publish Diagnostics](https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#publishdiagnostics-notification)
![Error reporting demo](images/publishDiagnostics.png) ![Error reporting demo](images/publishDiagnostics.png)

View File

@ -30,12 +30,12 @@
"phpdocumentor/reflection-docblock": "^4.0.0", "phpdocumentor/reflection-docblock": "^4.0.0",
"sabre/event": "^5.0", "sabre/event": "^5.0",
"sabre/uri": "^2.0", "sabre/uri": "^2.0",
"squizlabs/php_codesniffer": "3.0.0RC3",
"webmozart/glob": "^4.1", "webmozart/glob": "^4.1",
"webmozart/path-util": "^2.3" "webmozart/path-util": "^2.3"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.3" "phpunit/phpunit": "^6.3",
"squizlabs/php_codesniffer": "^3.1"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@ -1,20 +0,0 @@
<?php
namespace TestNamespace;
use SomeNamespace\Goo;
class TestClass
{
public $testProperty;
public function testMethod($testParameter)
{
$testVariable = 123;
if (empty($testParameter)){
echo 'Empty';
}
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace TestNamespace;
use SomeNamespace\Goo;
class TestClass
{
public $testProperty;
public function testMethod($testParameter)
{
$testVariable = 123;
if (empty($testParameter)) {
echo 'Empty';
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,107 +0,0 @@
<?php
declare(strict_types = 1);
namespace LanguageServer;
use LanguageServer\Protocol\{
TextEdit,
Range,
Position
};
use Exception;
use PHP_CodeSniffer\{
Config,
Ruleset
};
use PHP_CodeSniffer\Files\DummyFile;
use PHP_CodeSniffer\Util\Tokens;
abstract class Formatter
{
/**
* Generate array of TextEdit changes for content formatting.
*
* @param string $content source code to format
* @param string $uri URI of document
*
* @return \LanguageServer\Protocol\TextEdit[]
* @throws \Exception
*/
public static function format(string $content, string $uri)
{
if (!defined('PHP_CODESNIFFER_CBF')) {
define('PHP_CODESNIFFER_CBF', true);
}
if (!defined('PHP_CODESNIFFER_VERBOSITY')) {
define('PHP_CODESNIFFER_VERBOSITY', false);
}
$path = uriToPath($uri);
$config = new Config(['dummy'], false);
$config->standards = self::findConfiguration($path);
// Autoload class to set up a bunch of PHP_CodeSniffer-specific token type constants
spl_autoload_call(Tokens::class);
$file = new DummyFile($content, new Ruleset($config), $config);
$file->process();
$fixed = $file->fixer->fixFile();
if (!$fixed && $file->getErrorCount() > 0) {
throw new Exception('Unable to format file');
}
$new = $file->fixer->getContents();
if ($content === $new) {
return [];
}
return [new TextEdit(new Range(new Position(0, 0), self::calculateEndPosition($content)), $new)];
}
/**
* Calculate position of last character.
*
* @param string $content document as string
*
* @return \LanguageServer\Protocol\Position
*/
private static function calculateEndPosition(string $content): Position
{
$lines = explode("\n", $content);
return new Position(count($lines) - 1, strlen(end($lines)));
}
/**
* Search for PHP_CodeSniffer configuration file at given directory or its parents.
* If no configuration found then PSR2 standard is loaded by default.
*
* @param string $path path to file or directory
* @return string[]
*/
private static function findConfiguration(string $path)
{
if (is_dir($path)) {
$currentDir = $path;
} else {
$currentDir = dirname($path);
}
do {
$default = $currentDir . DIRECTORY_SEPARATOR . 'phpcs.xml';
if (is_file($default)) {
return [$default];
}
$default = $currentDir . DIRECTORY_SEPARATOR . 'phpcs.xml.dist';
if (is_file($default)) {
return [$default];
}
$lastDir = $currentDir;
$currentDir = dirname($currentDir);
} while ($currentDir !== '.' && $currentDir !== $lastDir);
$standard = Config::getConfigData('default_standard') ?? 'PSR2';
return explode(',', $standard);
}
}

View File

@ -265,8 +265,6 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
$serverCapabilities->documentSymbolProvider = true; $serverCapabilities->documentSymbolProvider = true;
// Support "Find all symbols in workspace" // Support "Find all symbols in workspace"
$serverCapabilities->workspaceSymbolProvider = true; $serverCapabilities->workspaceSymbolProvider = true;
// Support "Format Code"
$serverCapabilities->documentFormattingProvider = true;
// Support "Go to definition" // Support "Go to definition"
$serverCapabilities->definitionProvider = true; $serverCapabilities->definitionProvider = true;
// Support "Find all references" // Support "Find all references"

View File

@ -166,19 +166,6 @@ class PhpDocument
$this->sourceFileNode = $treeAnalyzer->getSourceFileNode(); $this->sourceFileNode = $treeAnalyzer->getSourceFileNode();
} }
/**
* Returns array of TextEdit changes to format this document.
*
* @return \LanguageServer\Protocol\TextEdit[]
*/
public function getFormattedText()
{
if (empty($this->getContent())) {
return [];
}
return Formatter::format($this->getContent(), $this->uri);
}
/** /**
* Returns this document's text content. * Returns this document's text content.
* *

View File

@ -159,20 +159,6 @@ class TextDocument
$this->documentLoader->close($textDocument->uri); $this->documentLoader->close($textDocument->uri);
} }
/**
* The document formatting request is sent from the server to the client to format a whole document.
*
* @param TextDocumentIdentifier $textDocument The document to format
* @param FormattingOptions $options The format options
* @return Promise <TextEdit[]>
*/
public function formatting(TextDocumentIdentifier $textDocument, FormattingOptions $options)
{
return $this->documentLoader->getOrLoad($textDocument->uri)->then(function (PhpDocument $document) {
return $document->getFormattedText();
});
}
/** /**
* The references request is sent from the client to the server to resolve project-wide references for the symbol * The references request is sent from the client to the server to resolve project-wide references for the symbol
* denoted by the given text document position. * denoted by the given text document position.

View File

@ -1,28 +0,0 @@
<?php
declare(strict_types = 1);
namespace LanguageServer\Tests;
use PHPUnit\Framework\TestCase;
use LanguageServer\Formatter;
class FormatterTest extends TestCase
{
public function testFormat()
{
$input = file_get_contents(__DIR__ . '/../fixtures/format.php');
$output = file_get_contents(__DIR__ . '/../fixtures/format_expected.php');
$edits = Formatter::format($input, 'file:///whatever');
$this->assertSame($output, $edits[0]->newText);
}
public function testFormatNoChange()
{
$expected = file_get_contents(__DIR__ . '/../fixtures/format_expected.php');
$edits = Formatter::format($expected, 'file:///whatever');
$this->assertSame([], $edits);
}
}

View File

@ -34,7 +34,6 @@ class LanguageServerTest extends TestCase
$serverCapabilities->textDocumentSync = TextDocumentSyncKind::FULL; $serverCapabilities->textDocumentSync = TextDocumentSyncKind::FULL;
$serverCapabilities->documentSymbolProvider = true; $serverCapabilities->documentSymbolProvider = true;
$serverCapabilities->workspaceSymbolProvider = true; $serverCapabilities->workspaceSymbolProvider = true;
$serverCapabilities->documentFormattingProvider = true;
$serverCapabilities->definitionProvider = true; $serverCapabilities->definitionProvider = true;
$serverCapabilities->referencesProvider = true; $serverCapabilities->referencesProvider = true;
$serverCapabilities->hoverProvider = true; $serverCapabilities->hoverProvider = true;

View File

@ -1,50 +0,0 @@
<?php
declare(strict_types = 1);
namespace LanguageServer\Tests\Server\TextDocument;
use PHPUnit\Framework\TestCase;
use LanguageServer\Tests\MockProtocolStream;
use LanguageServer\{
Server, LanguageClient, PhpDocumentLoader, DefinitionResolver
};
use LanguageServer\Index\{Index, ProjectIndex, DependenciesIndex};
use LanguageServer\ContentRetriever\FileSystemContentRetriever;
use LanguageServer\Protocol\{
TextDocumentIdentifier,
TextDocumentItem,
FormattingOptions,
TextEdit,
Range,
Position
};
use function LanguageServer\{pathToUri, uriToPath};
class FormattingTest extends TestCase
{
public function testFormatting()
{
$projectIndex = new ProjectIndex(new Index, new DependenciesIndex);
$client = new LanguageClient(new MockProtocolStream, new MockProtocolStream);
$definitionResolver = new DefinitionResolver($projectIndex);
$loader = new PhpDocumentLoader(new FileSystemContentRetriever, $projectIndex, $definitionResolver);
$textDocument = new Server\TextDocument($loader, $definitionResolver, $client, $projectIndex);
$path = realpath(__DIR__ . '/../../../fixtures/format.php');
$uri = pathToUri($path);
// Trigger parsing of source
$textDocumentItem = new TextDocumentItem();
$textDocumentItem->uri = $uri;
$textDocumentItem->languageId = 'php';
$textDocumentItem->version = 1;
$textDocumentItem->text = file_get_contents($path);
$textDocument->didOpen($textDocumentItem);
// how code should look after formatting
$expected = file_get_contents(__DIR__ . '/../../../fixtures/format_expected.php');
// Request formatting
$result = $textDocument->formatting(new TextDocumentIdentifier($uri), new FormattingOptions())->wait();
$this->assertEquals([new TextEdit(new Range(new Position(0, 0), new Position(20, 0)), $expected)], $result);
}
}