diff --git a/src/Fixer/ClassNotation/FinalClassFixer.php b/src/Fixer/ClassNotation/FinalClassFixer.php index e13cc8f4876..5695edf35d4 100644 --- a/src/Fixer/ClassNotation/FinalClassFixer.php +++ b/src/Fixer/ClassNotation/FinalClassFixer.php @@ -36,10 +36,10 @@ class MyApp {} ), ], 'No exception and no configuration are intentional. Beside Doctrine entities and of course abstract classes, there is no single reason not to declare all classes final. ' - .'If you want to subclass a class, mark the parent class as abstract and create two child classes, one empty if necessary: you\'ll gain much more fine grained type-hinting. ' - .'If you need to mock a standalone class, create an interface, or maybe it\'s a value-object that shouldn\'t be mocked at all. ' - .'If you need to extend a standalone class, create an interface and use the Composite pattern. ' - .'If you aren\'t ready yet for serious OOP, go with FinalInternalClassFixer, it\'s fine.', + .'If you want to subclass a class, mark the parent class as abstract and create two child classes, one empty if necessary: you\'ll gain much more fine grained type-hinting. ' + .'If you need to mock a standalone class, create an interface, or maybe it\'s a value-object that shouldn\'t be mocked at all. ' + .'If you need to extend a standalone class, create an interface and use the Composite pattern. ' + .'If you aren\'t ready yet for serious OOP, go with FinalInternalClassFixer, it\'s fine.', 'Risky when subclassing non-abstract classes.' ); } diff --git a/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php b/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php index ed9a7ac7a57..8576a033d47 100644 --- a/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php +++ b/src/Fixer/ClassNotation/FinalPublicMethodForAbstractClassFixer.php @@ -64,7 +64,7 @@ public function start() ), ], 'Enforce API encapsulation in an inheritance architecture. ' - .'If you want to override a method, use the Template method pattern.', + .'If you want to override a method, use the Template method pattern.', 'Risky when overriding `public` methods of `abstract` classes.' ); } diff --git a/src/Fixer/ClassNotation/OrderedInterfacesFixer.php b/src/Fixer/ClassNotation/OrderedInterfacesFixer.php index 985c9e83b70..8a061dfc40b 100644 --- a/src/Fixer/ClassNotation/OrderedInterfacesFixer.php +++ b/src/Fixer/ClassNotation/OrderedInterfacesFixer.php @@ -178,8 +178,8 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void ? \strlen($first['normalized']) - \strlen($second['normalized']) : ( true === $this->configuration['case_sensitive'] - ? $first['normalized'] <=> $second['normalized'] - : strcasecmp($first['normalized'], $second['normalized']) + ? $first['normalized'] <=> $second['normalized'] + : strcasecmp($first['normalized'], $second['normalized']) ); if (self::DIRECTION_DESCEND === $this->configuration[self::OPTION_DIRECTION]) { diff --git a/src/Fixer/FunctionNotation/VoidReturnFixer.php b/src/Fixer/FunctionNotation/VoidReturnFixer.php index 150931dd400..475de0b10bb 100644 --- a/src/Fixer/FunctionNotation/VoidReturnFixer.php +++ b/src/Fixer/FunctionNotation/VoidReturnFixer.php @@ -176,7 +176,7 @@ private function hasVoidReturn(Tokens $tokens, int $startIndex, int $endIndex): if ( // skip anonymous classes ($tokens[$i]->isGivenKind(T_CLASS) && $tokensAnalyzer->isAnonymousClass($i)) - // skip lambda functions + // skip lambda functions || ($tokens[$i]->isGivenKind(T_FUNCTION) && $tokensAnalyzer->isLambda($i)) ) { $i = $tokens->getNextTokenOfKind($i, ['{']); diff --git a/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php b/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php index c72a783a2de..edbd0e1847f 100644 --- a/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php +++ b/src/Fixer/LanguageConstruct/NoUnsetOnPropertyFixer.php @@ -34,9 +34,9 @@ public function getDefinition(): FixerDefinitionInterface [new CodeSample("a);\n")], null, 'Risky when relying on attributes to be removed using `unset` rather than be set to `null`.'. - ' Changing variables to `null` instead of unsetting means these still show up when looping over class variables'. - ' and reference properties remain unbroken.'. - ' With PHP 7.4, this rule might introduce `null` assignments to properties whose type declaration does not allow it.' + ' Changing variables to `null` instead of unsetting means these still show up when looping over class variables'. + ' and reference properties remain unbroken.'. + ' With PHP 7.4, this rule might introduce `null` assignments to properties whose type declaration does not allow it.' ); } diff --git a/src/Fixer/PhpUnit/PhpUnitDataProviderStaticFixer.php b/src/Fixer/PhpUnit/PhpUnitDataProviderStaticFixer.php index a28603250d4..aa1e655b3fd 100644 --- a/src/Fixer/PhpUnit/PhpUnitDataProviderStaticFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitDataProviderStaticFixer.php @@ -93,8 +93,8 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn (new FixerOptionBuilder( 'force', 'Whether to make the data providers static even if they have a dynamic class call' - .' (may introduce fatal error "using $this when not in object context",' - .' and you may have to adjust the code manually by converting dynamic calls to static ones).' + .' (may introduce fatal error "using $this when not in object context",' + .' and you may have to adjust the code manually by converting dynamic calls to static ones).' )) ->setAllowedTypes(['bool']) ->setDefault(false) diff --git a/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php b/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php index d521007dbb5..c8b4bb00272 100644 --- a/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitNamespacedFixer.php @@ -68,9 +68,9 @@ public function testSomething() new CodeSample($codeSample, ['target' => PhpUnitTargetVersion::VERSION_4_8]), ], "PHPUnit v6 has finally fully switched to namespaces.\n" - ."You could start preparing the upgrade by switching from non-namespaced TestCase to namespaced one.\n" - .'Forward compatibility layer (`\PHPUnit\Framework\TestCase` class) was backported to PHPUnit v4.8.35 and PHPUnit v5.4.0.'."\n" - .'Extended forward compatibility layer (`PHPUnit\Framework\Assert`, `PHPUnit\Framework\BaseTestListener`, `PHPUnit\Framework\TestListener` classes) was introduced in v5.7.0.'."\n", + ."You could start preparing the upgrade by switching from non-namespaced TestCase to namespaced one.\n" + .'Forward compatibility layer (`\PHPUnit\Framework\TestCase` class) was backported to PHPUnit v4.8.35 and PHPUnit v5.4.0.'."\n" + .'Extended forward compatibility layer (`PHPUnit\Framework\Assert`, `PHPUnit\Framework\BaseTestListener`, `PHPUnit\Framework\TestListener` classes) was introduced in v5.7.0.'."\n", 'Risky when PHPUnit classes are overridden or not accessible, or when project has PHPUnit incompatibilities.' ); } diff --git a/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php b/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php index 3fbd98ce4db..ca3f99679c5 100644 --- a/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitSetUpTearDownVisibilityFixer.php @@ -52,7 +52,7 @@ public function tearDown() ], null, 'This fixer may change functions named `setUp()` or `tearDown()` outside of PHPUnit tests, '. - 'when a class is wrongly seen as a PHPUnit test.' + 'when a class is wrongly seen as a PHPUnit test.' ); } diff --git a/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php b/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php index 3ae0ca06a28..d67c842de0f 100644 --- a/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php +++ b/src/Fixer/PhpUnit/PhpUnitTestAnnotationFixer.php @@ -60,7 +60,7 @@ public function testItDoesSomething() {}}'.$this->whitespacesConfig->getLineEndi ], null, 'This fixer may change the name of your tests, and could cause incompatibility with'. - ' abstract classes or interfaces.' + ' abstract classes or interfaces.' ); } diff --git a/src/Fixer/Phpdoc/PhpdocAlignFixer.php b/src/Fixer/Phpdoc/PhpdocAlignFixer.php index 454f84c8eb2..dc54f3d9724 100644 --- a/src/Fixer/Phpdoc/PhpdocAlignFixer.php +++ b/src/Fixer/Phpdoc/PhpdocAlignFixer.php @@ -373,8 +373,8 @@ private function fixDocBlock(DocBlock $docBlock): void .$item['var'] .( '' !== $item['desc'] - ? $this->getIndent($varMax - \strlen($item['var']) + $spacingForTag, $spacingForTag).$item['desc'] - : '' + ? $this->getIndent($varMax - \strlen($item['var']) + $spacingForTag, $spacingForTag).$item['desc'] + : '' ); } elseif ('' !== $item['desc']) { $line .= $this->getIndent($hintMax - \strlen($item['hint']) + $spacingForTag, $spacingForTag).$item['desc']; diff --git a/src/Fixer/Phpdoc/PhpdocSeparationFixer.php b/src/Fixer/Phpdoc/PhpdocSeparationFixer.php index 838c519faf2..4263cd070ed 100644 --- a/src/Fixer/Phpdoc/PhpdocSeparationFixer.php +++ b/src/Fixer/Phpdoc/PhpdocSeparationFixer.php @@ -154,13 +154,13 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn if ($groupIndex === $tags[$member]) { throw new InvalidOptionsException( 'The option "groups" value is invalid. '. - 'The "'.$member.'" tag is specified more than once.' + 'The "'.$member.'" tag is specified more than once.' ); } throw new InvalidOptionsException( 'The option "groups" value is invalid. '. - 'The "'.$member.'" tag belongs to more than one group.' + 'The "'.$member.'" tag belongs to more than one group.' ); } $tags[$member] = $groupIndex; diff --git a/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php b/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php index 786134ff4a3..7209abf66e7 100644 --- a/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php +++ b/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php @@ -70,12 +70,12 @@ public function getDefinition(): FixerDefinitionInterface ), ], 'In PHP double-quoted strings and heredocs some chars like `n`, `$` or `u` have special meanings if preceded by a backslash ' - .'(and some are special only if followed by other special chars), while a backslash preceding other chars are interpreted like a plain ' - .'backslash. The precise list of those special chars is hard to remember and to identify quickly: this fixer escapes backslashes ' - ."that do not start a special interpretation with the char after them.\n" - .'It is possible to fix also single-quoted strings: in this case there is no special chars apart from single-quote and backslash ' - .'itself, so the fixer simply ensure that all backslashes are escaped. Both single and double backslashes are allowed in single-quoted ' - .'strings, so the purpose in this context is mainly to have a uniformed way to have them written all over the codebase.' + .'(and some are special only if followed by other special chars), while a backslash preceding other chars are interpreted like a plain ' + .'backslash. The precise list of those special chars is hard to remember and to identify quickly: this fixer escapes backslashes ' + ."that do not start a special interpretation with the char after them.\n" + .'It is possible to fix also single-quoted strings: in this case there is no special chars apart from single-quote and backslash ' + .'itself, so the fixer simply ensure that all backslashes are escaped. Both single and double backslashes are allowed in single-quoted ' + .'strings, so the purpose in this context is mainly to have a uniformed way to have them written all over the codebase.' ); } diff --git a/src/Fixer/StringNotation/ExplicitStringVariableFixer.php b/src/Fixer/StringNotation/ExplicitStringVariableFixer.php index 5194a72e813..a6890fcf18d 100644 --- a/src/Fixer/StringNotation/ExplicitStringVariableFixer.php +++ b/src/Fixer/StringNotation/ExplicitStringVariableFixer.php @@ -45,7 +45,7 @@ public function getDefinition(): FixerDefinitionInterface ."\n".'- PHP manual marks `"$var"` syntax as implicit and `"${var}"` syntax as explicit: explicit code should always be preferred.' ."\n".'- Explicit syntax allows word concatenation inside strings, e.g. `"${var}IsAVar"`, implicit doesn\'t.' ."\n".'- Explicit syntax is easier to detect for IDE/editors and therefore has colors/highlight with higher contrast, which is easier to read.' - ."\n".'Backtick operator is skipped because it is harder to handle; you can use `backtick_to_shell_exec` fixer to normalize backticks to strings.' + ."\n".'Backtick operator is skipped because it is harder to handle; you can use `backtick_to_shell_exec` fixer to normalize backticks to strings.' ); } diff --git a/src/Fixer/StringNotation/StringImplicitBackslashesFixer.php b/src/Fixer/StringNotation/StringImplicitBackslashesFixer.php index da3535761e8..20418c1bd7b 100644 --- a/src/Fixer/StringNotation/StringImplicitBackslashesFixer.php +++ b/src/Fixer/StringNotation/StringImplicitBackslashesFixer.php @@ -65,12 +65,12 @@ public function getDefinition(): FixerDefinitionInterface ), ], 'In PHP double-quoted strings and heredocs some chars like `n`, `$` or `u` have special meanings if preceded by a backslash ' - .'(and some are special only if followed by other special chars), while a backslash preceding other chars are interpreted like a plain ' - .'backslash. The precise list of those special chars is hard to remember and to identify quickly: this fixer escapes backslashes ' - ."that do not start a special interpretation with the char after them.\n" - .'It is possible to fix also single-quoted strings: in this case there is no special chars apart from single-quote and backslash ' - .'itself, so the fixer simply ensure that all backslashes are escaped. Both single and double backslashes are allowed in single-quoted ' - .'strings, so the purpose in this context is mainly to have a uniformed way to have them written all over the codebase.' + .'(and some are special only if followed by other special chars), while a backslash preceding other chars are interpreted like a plain ' + .'backslash. The precise list of those special chars is hard to remember and to identify quickly: this fixer escapes backslashes ' + ."that do not start a special interpretation with the char after them.\n" + .'It is possible to fix also single-quoted strings: in this case there is no special chars apart from single-quote and backslash ' + .'itself, so the fixer simply ensure that all backslashes are escaped. Both single and double backslashes are allowed in single-quoted ' + .'strings, so the purpose in this context is mainly to have a uniformed way to have them written all over the codebase.' ); } diff --git a/src/Fixer/Whitespace/StatementIndentationFixer.php b/src/Fixer/Whitespace/StatementIndentationFixer.php index ca448fb4305..45434b6662f 100644 --- a/src/Fixer/Whitespace/StatementIndentationFixer.php +++ b/src/Fixer/Whitespace/StatementIndentationFixer.php @@ -136,6 +136,8 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void T_CASE, T_DEFAULT, T_TRY, + T_CATCH, + T_FINALLY, T_CLASS, T_INTERFACE, T_TRAIT, @@ -143,6 +145,10 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void T_IMPLEMENTS, T_CONST, ]; + if (\defined('T_ENUM')) { // @TODO: drop condition when PHP 8.1+ is required + $blockSignatureFirstTokens[] = T_ENUM; + } + $controlStructurePossibiblyWithoutBracesTokens = [ T_IF, T_ELSE, @@ -156,7 +162,12 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $blockSignatureFirstTokens[] = T_MATCH; } - $blockFirstTokens = ['{', [CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN], [CT::T_USE_TRAIT], [CT::T_GROUP_IMPORT_BRACE_OPEN]]; + $blockFirstTokens = [ + '{', + [CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN], + [CT::T_USE_TRAIT], + [CT::T_GROUP_IMPORT_BRACE_OPEN], + ]; if (\defined('T_ATTRIBUTE')) { // @TODO: drop condition when PHP 8.0+ is required $blockFirstTokens[] = [T_ATTRIBUTE]; } @@ -174,13 +185,15 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void /** * @var list $scopes */ $scopes = [ @@ -190,7 +203,9 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void 'end_index' => $endIndex, 'end_index_inclusive' => true, 'initial_indent' => $lastIndent, + 'base_indent' => $lastIndent, 'is_indented_block' => false, + 'statement_inner_indent' => true, ], ]; @@ -204,13 +219,17 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $currentScope = \count($scopes) - 1; if (isset($noBracesBlockStarts[$index])) { + $currentIndent = $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent); + $scopes[] = [ 'type' => 'block', 'skip' => false, 'end_index' => $this->findStatementEndIndex($tokens, $index, \count($tokens) - 1), 'end_index_inclusive' => true, - 'initial_indent' => $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent), + 'initial_indent' => $currentIndent, + 'base_indent' => $currentIndent, 'is_indented_block' => true, + 'statement_inner_indent' => true, ]; ++$currentScope; } @@ -262,13 +281,27 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } } + $innerIndent = true; + if ($token->equals('(')) { + $prevToken = $tokens[$tokens->getPrevMeaningfulToken($index)]; + + if ( + !$prevToken->isGivenKind([T_ARRAY, T_STRING, T_VARIABLE, T_FN, T_FUNCTION, T_CLASS, CT::T_BRACE_CLASS_INSTANTIATION_CLOSE]) + && !$prevToken->equals(')') + ) { + $innerIndent = false; + } + } + $scopes[] = [ 'type' => 'block', 'skip' => $skip, 'end_index' => $endIndex, 'end_index_inclusive' => $endIndexInclusive, 'initial_indent' => $initialIndent, + 'base_indent' => $initialIndent, 'is_indented_block' => true, + 'statement_inner_indent' => $innerIndent, ]; ++$currentScope; @@ -281,20 +314,48 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } + while ($index >= $scopes[$currentScope]['end_index']) { + array_pop($scopes); + + if ([] === $scopes) { + return; + } + + --$currentScope; + } + if ( $token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_OPEN) - || ($token->equals('(') && $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_ARRAY)) + || $token->equals('(') ) { $blockType = $token->equals('(') ? Tokens::BLOCK_TYPE_PARENTHESIS_BRACE : Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE; $scopes[] = [ - 'type' => 'statement', - 'skip' => true, + 'type' => 'array', + 'skip' => false, 'end_index' => $tokens->findBlockEnd($blockType, $index), 'end_index_inclusive' => true, 'initial_indent' => $previousLineInitialIndent, + 'base_indent' => $previousLineInitialIndent, 'new_indent' => $previousLineNewIndent, - 'is_indented_block' => false, + 'is_indented_block' => true, + 'statement_inner_indent' => true, + ]; + + continue; + } + + if ($token->equals('[')) { + $scopes[] = [ + 'type' => 'array_access', + 'skip' => false, + 'end_index' => $tokens->findBlockEnd(Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE, $index), + 'end_index_inclusive' => true, + 'initial_indent' => $previousLineInitialIndent, + 'base_indent' => $previousLineInitialIndent, + 'new_indent' => $previousLineNewIndent, + 'is_indented_block' => true, + 'statement_inner_indent' => true, ]; continue; @@ -349,13 +410,17 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } } + $currentIndent = $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent); + $scopes[] = [ 'type' => 'block_signature', 'skip' => false, 'end_index' => $endIndex, 'end_index_inclusive' => true, - 'initial_indent' => $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent), + 'initial_indent' => $currentIndent, + 'base_indent' => $currentIndent, 'is_indented_block' => $isPropertyStart || $token->isGivenKind([T_EXTENDS, T_IMPLEMENTS, T_CONST]), + 'statement_inner_indent' => true, ]; continue; @@ -376,18 +441,40 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } } + $currentIndent = $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent); + $scopes[] = [ 'type' => 'block_signature', 'skip' => false, 'end_index' => $endIndex, 'end_index_inclusive' => true, - 'initial_indent' => $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent), + 'initial_indent' => $currentIndent, + 'base_indent' => $currentIndent, 'is_indented_block' => false, + 'statement_inner_indent' => true, ]; continue; } + $nextToken = $tokens->getNextMeaningfulToken($index); + if ( + null !== $nextToken + && $tokens[$nextToken]->equals('?') + ) { + $scopes[] = [ + 'type' => 'statement', + 'skip' => false, + 'end_index' => $this->findStatementEndIndex($tokens, $index, $scopes[$currentScope]['end_index']), + 'end_index_inclusive' => true, + 'initial_indent' => $previousLineInitialIndent, + 'new_indent' => $previousLineNewIndent, + 'base_indent' => $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent), + 'is_indented_block' => true, + 'statement_inner_indent' => true, + ]; + } + if ( $token->isWhitespace() || ($index > 0 && $tokens[$index - 1]->isGivenKind(T_OPEN_TAG)) @@ -413,7 +500,10 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void continue; } - if ('block' === $scopes[$currentScope]['type'] || 'block_signature' === $scopes[$currentScope]['type']) { + if ( + 'array' !== $scopes[$currentScope]['type'] + && (null === $nextToken || !$nextToken->isGivenKind(T_OBJECT_OPERATOR)) + ) { $indent = false; if ($scopes[$currentScope]['is_indented_block']) { @@ -464,9 +554,11 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $nextIndex = $tokens->getNextMeaningfulToken($firstNonWhitespaceTokenIndex); $nextNextIndex = $tokens->getNextMeaningfulToken($nextIndex); - if (null !== $nextNextIndex && $tokens[$nextNextIndex]->isGivenKind([T_ELSE, T_ELSEIF])) { - $indent = true !== $this->configuration['stick_comment_to_next_continuous_control_statement']; - } else { + if ( + null === $nextNextIndex + || !$tokens[$nextNextIndex]->isGivenKind([T_ELSE, T_ELSEIF]) + || false === $this->configuration['stick_comment_to_next_continuous_control_statement'] + ) { $indent = true; } } @@ -481,7 +573,20 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void if ($scopes[$currentScope]['skip']) { $whitespaces = $previousLineInitialIndent; } else { - $whitespaces = $scopes[$currentScope]['initial_indent'].($indent ? $this->whitespacesConfig->getIndent() : ''); + $baseIndent = $scopes[$currentScope]['base_indent']; + + if ('statement' === $scopes[$currentScope]['type'] && !$scopes[$currentScope]['statement_inner_indent']) { + $indent = false; + } + + $whitespaces = $baseIndent.($indent ? $this->whitespacesConfig->getIndent() : ''); + + if ('statement' === $scopes[$currentScope]['type']) { + $minimumIndent = $scopes[$currentScope - 1]['base_indent'].$this->whitespacesConfig->getIndent(); + if (\strlen($minimumIndent) > \strlen($whitespaces)) { + $whitespaces = $minimumIndent; + } + } } $content = Preg::replace( @@ -531,21 +636,11 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void $lastIndent = $this->extractIndent($this->computeNewLineContent($tokens, $index)); } - while ($index >= $scopes[$currentScope]['end_index']) { - array_pop($scopes); - - if ([] === $scopes) { - return; - } - - --$currentScope; - } - if ($token->isComment() || $token->equalsAny([';', ',', '}', [T_OPEN_TAG], [T_CLOSE_TAG], [CT::T_ATTRIBUTE_CLOSE]])) { continue; } - if ('statement' !== $scopes[$currentScope]['type'] && 'block_signature' !== $scopes[$currentScope]['type']) { + if (0 !== $index && 'block' === $scopes[$currentScope]['type']) { $endIndex = $this->findStatementEndIndex($tokens, $index, $scopes[$currentScope]['end_index']); if ($endIndex === $index) { @@ -559,7 +654,9 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void 'end_index_inclusive' => false, 'initial_indent' => $previousLineInitialIndent, 'new_indent' => $previousLineNewIndent, + 'base_indent' => $this->getLineIndentationWithBracesCompatibility($tokens, $index, $lastIndent), 'is_indented_block' => true, + 'statement_inner_indent' => $scopes[$currentScope]['statement_inner_indent'] && !$token->isGivenKind(T_INLINE_HTML), ]; } } diff --git a/tests/Console/Command/DescribeCommandTest.php b/tests/Console/Command/DescribeCommandTest.php index 67a74b3459e..4dd3c819746 100644 --- a/tests/Console/Command/DescribeCommandTest.php +++ b/tests/Console/Command/DescribeCommandTest.php @@ -436,7 +436,7 @@ public function testCommandDescribesCustomFixer(): void ]); $expected = -"Description of the `Vendor/describe_fixture` rule. + "Description of the `Vendor/describe_fixture` rule. Fixture for describe command. diff --git a/tests/Fixer/Operator/TernaryToNullCoalescingFixerTest.php b/tests/Fixer/Operator/TernaryToNullCoalescingFixerTest.php index bac81035a4e..239b6c0e1bd 100644 --- a/tests/Fixer/Operator/TernaryToNullCoalescingFixerTest.php +++ b/tests/Fixer/Operator/TernaryToNullCoalescingFixerTest.php @@ -36,7 +36,7 @@ public function testFix(string $expected, ?string $input = null): void public static function provideFixCases(): iterable { yield // Do not fix cases. - ['expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessage( 'The option "groups" value is invalid. '. - 'The "param" tag belongs to more than one group.' + 'The "param" tag belongs to more than one group.' ); $this->fixer->configure(['groups' => [['param', 'return'], ['param', 'throws']]]); @@ -667,7 +667,7 @@ public function testTagSpecifiedTwoTimesInGroupConfiguration(): void $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessage( 'The option "groups" value is invalid. '. - 'The "param" tag is specified more than once.' + 'The "param" tag is specified more than once.' ); $this->fixer->configure(['groups' => [['param', 'return', 'param', 'throws']]]); diff --git a/tests/Fixer/Whitespace/StatementIndentationFixerTest.php b/tests/Fixer/Whitespace/StatementIndentationFixerTest.php index 5f71e28d694..17e07caeb94 100644 --- a/tests/Fixer/Whitespace/StatementIndentationFixerTest.php +++ b/tests/Fixer/Whitespace/StatementIndentationFixerTest.php @@ -589,8 +589,8 @@ class Foo { ' [ ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + '#!/usr/bin/env php + [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + 'getFileName() )); } diff --git a/tests/Tokenizer/TokensAnalyzerTest.php b/tests/Tokenizer/TokensAnalyzerTest.php index 5e80ef71a8a..cbce3a4a67d 100644 --- a/tests/Tokenizer/TokensAnalyzerTest.php +++ b/tests/Tokenizer/TokensAnalyzerTest.php @@ -2358,45 +2358,45 @@ class TestClass { public function testIsWhilePartOfDoWhile(): void { $source = -<<<'SRC' - - + - + ?> + - + - - + false,