From 64b92f36d0c6cb140a8f014121711a00639e35bc Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 4 Sep 2026 23:58:42 +0200 Subject: [PATCH] Deprecate withEditorConfig(), drop EditorConfig support EditorConfig discovery leaked project-wide settings (indent, line ending, quotes, final newline) into ECS, overriding the configured sets. The method now reports a deprecation warning; configure the matching PHP-CS-Fixer rules explicitly instead. Removes the EditorConfig value objects, factory, the builder wiring, and its test. Claude-Session: https://claude.ai/code/session_01A8hvNrf4ZxWkiEjWxecSAa --- build/target-repository/README.md | 21 - ecs.php | 1 - src/Configuration/ECSConfigBuilder.php | 99 +---- .../EditorConfig/EditorConfig.php | 21 - .../EditorConfig/EditorConfigFactory.php | 76 ---- src/Configuration/EditorConfig/EndOfLine.php | 14 - .../EditorConfig/IndentStyle.php | 12 - src/Configuration/EditorConfig/QuoteType.php | 17 - .../EditorConfig/EditorConfigFactoryTest.php | 371 ------------------ 9 files changed, 8 insertions(+), 624 deletions(-) delete mode 100644 src/Configuration/EditorConfig/EditorConfig.php delete mode 100644 src/Configuration/EditorConfig/EditorConfigFactory.php delete mode 100644 src/Configuration/EditorConfig/EndOfLine.php delete mode 100644 src/Configuration/EditorConfig/IndentStyle.php delete mode 100644 src/Configuration/EditorConfig/QuoteType.php delete mode 100644 tests/Configuration/EditorConfig/EditorConfigFactoryTest.php diff --git a/build/target-repository/README.md b/build/target-repository/README.md index 4706b19cce..d809cd6fca 100644 --- a/build/target-repository/README.md +++ b/build/target-repository/README.md @@ -248,27 +248,6 @@ vendor/bin/ecs list-checkers --output-format json
-### Can I Use My [`.editorconfig`](https://editorconfig.org/)? - -Mostly! By using `->withEditorConfig()` in `ecs.php`, ECS will automatically discover -the `.editorconfig` file in the project's root directory. It will use any -rules under `[*]` or `[*.php]` (the latter taking priority) and respect the -settings for: - -- `indent_style` -- `end_of_line` -- `max_line_length` -- `trim_trailing_whitespace` -- `insert_final_newline` -- [`quote_type`](https://github.com/jednano/codepainter#quote_type-single-double-auto) - - Only `single` and `auto` are respected. - - Warning: this is a proposed field, but not fully standard. - -These settings will take precedence over similar rules configured through sets -like PSR12, to avoid conflicting with other tooling using your `.editorconfig`. - -
- ## How to Migrate from another coding standard tool? Do you use another tool and want to migrate? It's pretty straightforward - here is "how to": diff --git a/ecs.php b/ecs.php index eb36b8ac48..b892bff131 100644 --- a/ecs.php +++ b/ecs.php @@ -6,7 +6,6 @@ return ECSConfig::configure() ->withPaths([__DIR__ . '/bin', __DIR__ . '/config', __DIR__ . '/packages', __DIR__ . '/src', __DIR__ . '/tests']) - ->withEditorConfig() ->withRootFiles() ->withSkip(['*/Source/*', '*/Fixture/*']) ->withPreparedSets(psr12: true, common: true); diff --git a/src/Configuration/ECSConfigBuilder.php b/src/Configuration/ECSConfigBuilder.php index e685c0cea9..5695e957cd 100644 --- a/src/Configuration/ECSConfigBuilder.php +++ b/src/Configuration/ECSConfigBuilder.php @@ -7,26 +7,13 @@ use Entropy\Console\Output\OutputColorizer; use Entropy\Console\Output\OutputPrinter; use PHP_CodeSniffer\Sniffs\Sniff; -use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\EndFileNewlineSniff as GenericEndFileNewlineSniff; -use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\EndFileNoNewlineSniff; -use PHP_CodeSniffer\Standards\PSR2\Sniffs\Files\EndFileNewlineSniff as Psr2EndFileNewlineSniff; -use PHP_CodeSniffer\Standards\Squiz\Sniffs\Strings\DoubleQuoteUsageSniff; -use PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\SuperfluousWhitespaceSniff; use PhpCsFixer\Fixer\FixerInterface; -use PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer; -use PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer; -use PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer; use Symfony\Component\Finder\Finder; -use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer; use Symplify\EasyCodingStandard\Config\ECSConfig; use Symplify\EasyCodingStandard\Config\Level\ArrayLevel; use Symplify\EasyCodingStandard\Config\Level\ControlStructuresLevel; use Symplify\EasyCodingStandard\Config\Level\DocblockLevel; use Symplify\EasyCodingStandard\Config\Level\SpacesLevel; -use Symplify\EasyCodingStandard\Configuration\EditorConfig\EditorConfigFactory; -use Symplify\EasyCodingStandard\Configuration\EditorConfig\EndOfLine; -use Symplify\EasyCodingStandard\Configuration\EditorConfig\IndentStyle; -use Symplify\EasyCodingStandard\Configuration\EditorConfig\QuoteType; use Symplify\EasyCodingStandard\Configuration\Levels\LevelRulesResolver; use Symplify\EasyCodingStandard\Exception\Configuration\InitializationException; use Symplify\EasyCodingStandard\Exception\Configuration\SuperfluousConfigurationException; @@ -89,8 +76,6 @@ final class ECSConfigBuilder private ?bool $reportingRealPath = null; - private ?bool $useEditorConfig = null; - /** * To make sure each common set and its corresponding level are not * duplicated, as both contain the same rules. @@ -105,8 +90,6 @@ final class ECSConfigBuilder public function __invoke(ECSConfig $ecsConfig): void { - $this->applyEditorConfigSettings(); - $this->assertLevelAndSetNotMixed($this->isArrayLevelUsed, SetList::ARRAY, 'array', 'withArrayLevel'); $this->assertLevelAndSetNotMixed( @@ -382,10 +365,15 @@ public function withCache(?string $directory = null, ?string $namespace = null): return $this; } - public function withEditorConfig(bool $enabled = true): self + /** + * @deprecated EditorConfig support is deprecated, as it leaks project-wide settings into ECS. Configure the matching PHP-CS-Fixer rules explicitly instead. + */ + public function withEditorConfig(): self { - $this->useEditorConfig = $enabled; - + $outputPrinter = new OutputPrinter(new OutputColorizer()); + $outputPrinter->warning( + 'The "withEditorConfig()" method is deprecated, as it leaks project-wide settings into ECS. Configure the matching PHP-CS-Fixer rules explicitly instead.' + ); return $this; } @@ -547,75 +535,4 @@ private function assertLevelAndSetNotMixed( )); } } - - private function applyEditorConfigSettings(): void - { - if (! $this->useEditorConfig) { - return; - } - - /** - * PHP CS Fixer handles most of this, code sniffer just needs to stay - * out of out way. Luckily, we have a pass to make sure it does! - * - * This does introduce a quirk that if someone manually disables a Fixer - * rule, but does not enable the equivalent Sniffer rule, that - * EditorConfig setting won't be respected. But why would they do that? - * - * @see \Symplify\EasyCodingStandard\DependencyInjection\CompilerPass\RemoveMutualCheckersCompilerPass - */ - $editorConfig = new EditorConfigFactory() - ->load(); - - if ($editorConfig->indentStyle !== null) { - $this->indentation = match ($editorConfig->indentStyle) { - IndentStyle::Space => Option::INDENTATION_SPACES, - IndentStyle::Tab => Option::INDENTATION_TAB, - default => Option::INDENTATION_SPACES, - }; - } - - if ($editorConfig->endOfLine !== null) { - $this->lineEnding = match ($editorConfig->endOfLine) { - EndOfLine::Posix => "\n", - EndOfLine::Legacy => "\r", - EndOfLine::Windows => "\r\n", - default => "\n", - }; - } - - if ($editorConfig->maxLineLength) { - $this->rulesWithConfiguration[LineLengthFixer::class] = [ - ...($this->rulesWithConfiguration[LineLengthFixer::class] ?? []), - 'line_length' => $editorConfig->maxLineLength, - ]; - } - - if ($editorConfig->trimTrailingWhitespace === true) { - $this->rules[] = NoTrailingWhitespaceFixer::class; - } elseif ($editorConfig->trimTrailingWhitespace === false) { - $this->skip = [...$this->skip, NoTrailingWhitespaceFixer::class, SuperfluousWhitespaceSniff::class]; - } - - if ($editorConfig->insertFinalNewline === true) { - $this->rules[] = SingleBlankLineAtEofFixer::class; - } elseif ($editorConfig->insertFinalNewline === false) { - $this->rules[] = EndFileNoNewlineSniff::class; - $this->skip[] = [ - SingleBlankLineAtEofFixer::class, - Psr2EndFileNewlineSniff::class, - GenericEndFileNewlineSniff::class, - ]; - } - - if ($editorConfig->quoteType === QuoteType::Auto) { - $this->rules[] = SingleQuoteFixer::class; - } elseif ($editorConfig->quoteType === QuoteType::Single) { - $this->rulesWithConfiguration[SingleQuoteFixer::class] = [ - 'strings_containing_single_quote_chars' => true, - ]; - } elseif ($editorConfig->quoteType === QuoteType::Double) { - $this->skip = [...$this->skip, SingleQuoteFixer::class, DoubleQuoteUsageSniff::class]; - } - } } diff --git a/src/Configuration/EditorConfig/EditorConfig.php b/src/Configuration/EditorConfig/EditorConfig.php deleted file mode 100644 index 80cddad5fc..0000000000 --- a/src/Configuration/EditorConfig/EditorConfig.php +++ /dev/null @@ -1,21 +0,0 @@ -parse($configFileContent); - } - - public function parse(string $editorConfigFileContents): EditorConfig - { - $fullConfig = parse_ini_string($editorConfigFileContents, true, INI_SCANNER_TYPED); - - if ($fullConfig === false) { - throw new Exception('Unable to parse .editorconfig.'); - } - - $config = [...$fullConfig['*'] ?? [], ...$fullConfig['*.php'] ?? []]; - - // Just letting "validation" happen with PHP's type hints. - return new EditorConfig( - indentStyle: $config['indent_style'] ?? null, - endOfLine: $config['end_of_line'] ?? null, - trimTrailingWhitespace: $this->field($config, 'trim_trailing_whitespace', $this->id(...)), - insertFinalNewline: $this->field($config, 'insert_final_newline', $this->id(...)), - maxLineLength: $this->field($config, 'max_line_length', $this->id(...)), - quoteType: $config['quote_type'] ?? null - ); - } - - /** - * @template From - * @template To - * @param mixed[] $config - * @param callable(From): To $transform - * @return To|null - */ - private function field(array $config, string $field, callable $transform): mixed - { - if (! isset($config[$field])) { - return null; - } - - return $transform($config[$field]); - } - - /** - * @template T - * @param T $value - * @return T - */ - private function id(mixed $value): mixed - { - return $value; - } -} diff --git a/src/Configuration/EditorConfig/EndOfLine.php b/src/Configuration/EditorConfig/EndOfLine.php deleted file mode 100644 index 6e65fecd77..0000000000 --- a/src/Configuration/EditorConfig/EndOfLine.php +++ /dev/null @@ -1,14 +0,0 @@ -load(); - - $this->assertEquals($editorConfig, new EditorConfig( - indentStyle: IndentStyle::Space, - endOfLine: EndOfLine::Posix, - trimTrailingWhitespace: true, - insertFinalNewline: true, - maxLineLength: null, - quoteType: null - )); - } - - #[RunInSeparateProcess] - public function testLoadingBadFilepath(): void - { - chdir(__DIR__); - - $this->expectException(Exception::class); - - $editorConfigFactory = new EditorConfigFactory(); - $editorConfigFactory->load(); - } - - public function testParsingInvalidIniFile(): void - { - $this->expectException(Exception::class); - - $editorConfigFactory = new EditorConfigFactory(); - @$editorConfigFactory->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse(''), - new EditorConfig( - indentStyle: null, - endOfLine: null, - trimTrailingWhitespace: null, - insertFinalNewline: null, - maxLineLength: null, - quoteType: null - ) - ); - } - - public function testIndentStyleSpaces(): void - { - $this->assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<assertEquals( - new EditorConfigFactory() - ->parse( - <<