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 May 1, 2021
1 parent 37e0776 commit 9695171
Show file tree
Hide file tree
Showing 18 changed files with 794 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
56 changes: 56 additions & 0 deletions src/Application/FileFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?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->createEditorConfigConfigurationBuilder()
);

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

namespace Rector\Core\Contract\EditorConfig;

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

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';

/**
* @var string
*/
public const INSERT_FINAL_NEWLINE = 'insert_final_newline';

/**
* @var string
*/
public const TAB_WIDTH = 'tab_width';

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

namespace Rector\Core\Contract\Formatter;

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

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

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

public function createEditorConfigConfigurationBuilder(): EditorConfigConfigurationBuilder;
}
58 changes: 58 additions & 0 deletions src/EditorConfig/EditorConfigIdiosyncraticParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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;
use Rector\Core\ValueObjectFactory\EditorConfigConfigurationBuilder;

/**
* @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,
EditorConfigConfigurationBuilder $editorConfigConfigurationBuilder
): EditorConfigConfiguration {
$smartFileInfo = $file->getSmartFileInfo();
$configuration = $this->editorConfig->getConfigForPath($smartFileInfo->getRealPath());

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

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

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

if (array_key_exists(self::INSERT_FINAL_NEWLINE, $configuration)) {
$editorConfigConfigurationBuilder->withInsertFinalNewline(
$configuration[self::INSERT_FINAL_NEWLINE]->getValue()
);
}

if (array_key_exists(self::TAB_WIDTH, $configuration)) {
$editorConfigConfigurationBuilder->withTabWidth($configuration[self::TAB_WIDTH]->getValue());
}

return $editorConfigConfigurationBuilder->build();
}
}
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
{
}
57 changes: 57 additions & 0 deletions src/Formatter/JsonFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?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;
use Rector\Core\ValueObjectFactory\EditorConfigConfigurationBuilder;

/**
* @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
{
$newContent = $this->jsonPrinter->print(
$file->getFileContent(),
$editorConfigConfiguration->getIndent(),
$editorConfigConfiguration->getEndOfLine()
);

$newContent .= $editorConfigConfiguration->getFinalNewline();

$file->changeFileContent($newContent);
}

public function createEditorConfigConfigurationBuilder(): EditorConfigConfigurationBuilder
{
$editorConfigConfigurationBuilder = EditorConfigConfigurationBuilder::anEditorConfigConfiguration();
$editorConfigConfigurationBuilder->withLineFeed();
$editorConfigConfigurationBuilder->withSpace();
$editorConfigConfigurationBuilder->withIndentSize(4);
$editorConfigConfigurationBuilder->withFinalNewline();

return $editorConfigConfigurationBuilder;
}
}

0 comments on commit 9695171

Please sign in to comment.