Skip to content

Commit

Permalink
[TASK] Take .editorconfig into account
Browse files Browse the repository at this point in the history
Resolves: #6215
  • Loading branch information
sabbelasichon committed Apr 30, 2021
1 parent 5b386ab commit b8ccbd6
Show file tree
Hide file tree
Showing 17 changed files with 571 additions and 3 deletions.
10 changes: 7 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"composer/xdebug-handler": "^1.4|^2.0",
"danielstjules/stringy": "^3.1",
"doctrine/inflector": "^2.0",
"ergebnis/json-printer": "^3.1",
"idiosyncratic/editorconfig": "dev-master",
"jean85/pretty-package-versions": "^1.6",
"nette/caching": "^3.1",
"nette/robot-loader": "^3.4",
Expand Down Expand Up @@ -63,8 +65,8 @@
"symplify/skipper": "^9.3",
"symplify/smart-file-system": "^9.3",
"symplify/symfony-php-config": "^9.3",
"webmozart/assert": "^1.10",
"tracy/tracy": "^2.8"
"tracy/tracy": "^2.8",
"webmozart/assert": "^1.10"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.18.6",
Expand Down Expand Up @@ -155,5 +157,7 @@
"config": {
"sort-packages": true,
"platform-check": false
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
8 changes: 8 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use Composer\Semver\VersionParser;
use Doctrine\Inflector\Inflector;
use Doctrine\Inflector\Rules\English\InflectorFactory;
use Ergebnis\Json\Printer\Printer;
use Idiosyncratic\EditorConfig\EditorConfig;
use Nette\Caching\Cache;
use PhpParser\BuilderFactory;
use PhpParser\Lexer;
Expand All @@ -25,6 +27,8 @@
use Rector\BetterPhpDocParser\PhpDocParser\BetterTypeParser;
use Rector\Caching\Cache\NetteCacheFactory;
use Rector\Core\Console\ConsoleApplication;
use Rector\Core\Contract\EditorConfig\EditorConfigParserInterface;
use Rector\Core\EditorConfig\EditorConfigIdiosyncraticParser;
use Rector\Core\PhpParser\Parser\NikicPhpParserFactory;
use Rector\Core\PhpParser\Parser\PhpParserLexerFactory;
use Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory;
Expand Down Expand Up @@ -142,4 +146,8 @@
->factory([service(PHPStanServicesFactory::class), 'createTypeNodeResolver']);
$services->set(DynamicSourceLocatorProvider::class)
->factory([service(PHPStanServicesFactory::class), 'createDynamicSourceLocatorProvider']);

$services->set(Printer::class);
$services->set(EditorConfig::class);
$services->alias(EditorConfigParserInterface::class, EditorConfigIdiosyncraticParser::class);
};
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,8 @@ parameters:
- '#Method Rector\\Core\\Tests\\DependencyInjection\\ConfigurableRectorImportConfigCallsMergeTest\:\:provideData\(\) return type has no value type specified in iterable type Iterator#'
- '#Class with base "PhpVersion" name is already used in "PHPStan\\Php\\PhpVersion", "Rector\\Core\\ValueObject\\PhpVersion"\. Use unique name to make classes easy to recognize#'

- '#Method Rector\\Core\\Tests\\Formatter\\JsonFormatter\\JsonFormatterTest\:\:provideData\(\) return type has no value type specified in iterable type Iterator#'

-
message: '#Use dependency injection instead of dependency juggling#'
path: src/HttpKernel/RectorKernel.php
Expand Down
9 changes: 9 additions & 0 deletions src/Application/ApplicationFileProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,26 @@ final class ApplicationFileProcessor
*/
private $fileDiffFileDecorator;

/**
* @var FileFormatter
*/
private $fileFormatter;

/**
* @param FileProcessorInterface[] $fileProcessors
*/
public function __construct(
Configuration $configuration,
SmartFileSystem $smartFileSystem,
FileDiffFileDecorator $fileDiffFileDecorator,
FileFormatter $fileFormatter,
array $fileProcessors = []
) {
$this->fileProcessors = $fileProcessors;
$this->smartFileSystem = $smartFileSystem;
$this->configuration = $configuration;
$this->fileDiffFileDecorator = $fileDiffFileDecorator;
$this->fileFormatter = $fileFormatter;
}

/**
Expand All @@ -54,6 +61,8 @@ public function run(array $files): void
{
$this->processFiles($files);

$this->fileFormatter->format($files);

$this->fileDiffFileDecorator->decorate($files);

$this->printFiles($files);
Expand Down
55 changes: 55 additions & 0 deletions src/Application/FileFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);

namespace Rector\Core\Application;

use Rector\Core\Contract\EditorConfig\EditorConfigParserInterface;
use Rector\Core\Contract\Formatter\FormatterInterface;
use Rector\Core\ValueObject\Application\File;

final class FileFormatter
{
/**
* @var EditorConfigParserInterface
*/
private $editorConfigParser;

/**
* @var FormatterInterface[]
*/
private $fileFormatters;

/**
* @param FormatterInterface[] $fileFormatters
*/
public function __construct(EditorConfigParserInterface $editorConfigParser, array $fileFormatters = [])
{
$this->editorConfigParser = $editorConfigParser;
$this->fileFormatters = $fileFormatters;
}

/**
* @param File[] $files
*/
public function format(array $files): void
{
foreach ($files as $file) {
if (! $file->hasChanged()) {
continue;
}

foreach ($this->fileFormatters as $fileFormatter) {
if (! $fileFormatter->supports($file)) {
continue;
}

$editorConfiguration = $this->editorConfigParser->extractConfigurationForFile(
$file,
$fileFormatter->getDefaultEditorConfiguration()
);

$fileFormatter->format($file, $editorConfiguration);
}
}
}
}
29 changes: 29 additions & 0 deletions src/Contract/EditorConfig/EditorConfigParserInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Rector\Core\Contract\EditorConfig;

use Rector\Core\ValueObject\Application\File;
use Rector\Core\ValueObject\EditorConfigConfiguration;

interface EditorConfigParserInterface
{
/**
* @var string
*/
public const INDENT_STYLE = 'indent_style';

/**
* @var string
*/
public const INDENT_SIZE = 'indent_size';

/**
* @var string
*/
public const END_OF_LINE = 'end_of_line';

public function extractConfigurationForFile(
File $file,
EditorConfigConfiguration $defaultEditorConfiguration
): EditorConfigConfiguration;
}
15 changes: 15 additions & 0 deletions src/Contract/Formatter/FormatterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Rector\Core\Contract\Formatter;

use Rector\Core\ValueObject\Application\File;
use Rector\Core\ValueObject\EditorConfigConfiguration;

interface FormatterInterface
{
public function supports(File $file): bool;

public function format(File $file, EditorConfigConfiguration $editorConfigConfiguration): void;

public function getDefaultEditorConfiguration(): EditorConfigConfiguration;
}
51 changes: 51 additions & 0 deletions src/EditorConfig/EditorConfigIdiosyncraticParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);

namespace Rector\Core\EditorConfig;

use Idiosyncratic\EditorConfig\EditorConfig;
use Rector\Core\Contract\EditorConfig\EditorConfigParserInterface;
use Rector\Core\ValueObject\Application\File;
use Rector\Core\ValueObject\EditorConfigConfiguration;

/**
* @see \Rector\Core\Tests\EditorConfig\EditorConfigIdiosyncraticParser\EditorConfigIdiosyncraticParserTest
*/
final class EditorConfigIdiosyncraticParser implements EditorConfigParserInterface
{
/**
* @var EditorConfig
*/
private $editorConfig;

public function __construct(EditorConfig $editorConfig)
{
$this->editorConfig = $editorConfig;
}

public function extractConfigurationForFile(
File $file,
EditorConfigConfiguration $defaultEditorConfiguration
): EditorConfigConfiguration {
$smartFileInfo = $file->getSmartFileInfo();
$configuration = $this->editorConfig->getConfigForPath($smartFileInfo->getRealPath());

$identStyle = $defaultEditorConfiguration->getIndentStyle();
$identSize = $defaultEditorConfiguration->getIndentSize();
$endOfLine = $defaultEditorConfiguration->getEndOfLine();

if (array_key_exists(self::INDENT_STYLE, $configuration)) {
$identStyle = $configuration[self::INDENT_STYLE]->getValue();
}

if (array_key_exists(self::INDENT_SIZE, $configuration)) {
$identSize = $configuration[self::INDENT_SIZE]->getValue();
}

if (array_key_exists(self::END_OF_LINE, $configuration)) {
$endOfLine = $configuration[self::END_OF_LINE]->getValue();
}

return new EditorConfigConfiguration($identStyle, $identSize, $endOfLine);
}
}
10 changes: 10 additions & 0 deletions src/Exception/EditorConfigConfigurationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);

namespace Rector\Core\Exception;

use InvalidArgumentException;

final class EditorConfigConfigurationException extends InvalidArgumentException
{
}
53 changes: 53 additions & 0 deletions src/Formatter/JsonFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);

namespace Rector\Core\Formatter;

use Ergebnis\Json\Printer\Printer;
use Rector\Core\Contract\Formatter\FormatterInterface;
use Rector\Core\ValueObject\Application\File;
use Rector\Core\ValueObject\EditorConfigConfiguration;

/**
* @see \Rector\Core\Tests\Formatter\JsonFormatter\JsonFormatterTest
*/
final class JsonFormatter implements FormatterInterface
{
/**
* @var Printer
*/
private $jsonPrinter;

public function __construct(Printer $jsonPrinter)
{
$this->jsonPrinter = $jsonPrinter;
}

public function supports(File $file): bool
{
$smartFileInfo = $file->getSmartFileInfo();

return in_array($smartFileInfo->getExtension(), ['json'], true);
}

public function format(File $file, EditorConfigConfiguration $editorConfigConfiguration): void
{
$indent = str_pad('', $editorConfigConfiguration->getIndentSize());
if ($editorConfigConfiguration->getIsTab()) {
$indent = "\t";
}

$newContent = $this->jsonPrinter->print(
$file->getFileContent(),
$indent,
$editorConfigConfiguration->getEndOfLine()
);

$file->changeFileContent($newContent);
}

public function getDefaultEditorConfiguration(): EditorConfigConfiguration
{
return new EditorConfigConfiguration(EditorConfigConfiguration::SPACE, 2, EditorConfigConfiguration::LINE_FEED);
}
}

0 comments on commit b8ccbd6

Please sign in to comment.