* Dariusz Rumiński * * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. */ namespace PhpCsFixer\Tests\Fixer\FunctionNotation; use PhpCsFixer\ConfigurationException\InvalidConfigurationException; use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\FunctionNotation\NativeFunctionInvocationFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Andreas Möller * * @internal * * @covers \PhpCsFixer\Fixer\FunctionNotation\NativeFunctionInvocationFixer * * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\FunctionNotation\NativeFunctionInvocationFixer> * * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\FunctionNotation\NativeFunctionInvocationFixer */ final class NativeFunctionInvocationFixerTest extends AbstractFixerTestCase { public function testConfigureRejectsUnknownConfigurationKey(): void { $key = 'foo'; $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage(\sprintf( '[native_function_invocation] Invalid configuration: The option "%s" does not exist.', $key )); $this->fixer->configure([ $key => 'bar', ]); } /** * @dataProvider provideConfigureRejectsInvalidConfigurationElementCases * * @param mixed $element */ public function testConfigureRejectsInvalidConfigurationElement($element, string $expectedExceptionMessage): void { $this->expectException(InvalidConfigurationException::class); $this->expectExceptionMessage($expectedExceptionMessage); $this->fixer->configure([ 'exclude' => [$element], ]); } public static function provideConfigureRejectsInvalidConfigurationElementCases(): iterable { yield 'null' => [ null, '[native_function_invocation] Invalid configuration: The option "exclude" with value array is expected to be of type "string[]", but one of the elements is of type "null".', ]; yield 'false' => [ false, '[native_function_invocation] Invalid configuration: The option "exclude" with value array is expected to be of type "string[]", but one of the elements is of type "bool".', ]; yield 'true' => [ true, '[native_function_invocation] Invalid configuration: The option "exclude" with value array is expected to be of type "string[]", but one of the elements is of type "bool".', ]; yield 'int' => [ 1, '[native_function_invocation] Invalid configuration: The option "exclude" with value array is expected to be of type "string[]", but one of the elements is of type "int".', ]; yield 'array' => [ [], '[native_function_invocation] Invalid configuration: The option "exclude" with value array is expected to be of type "string[]", but one of the elements is of type "array".', ]; yield 'float' => [ 0.1, '[native_function_invocation] Invalid configuration: The option "exclude" with value array is expected to be of type "string[]", but one of the elements is of type "float".', ]; yield 'object' => [ new \stdClass(), '[native_function_invocation] Invalid configuration: The option "exclude" with value array is expected to be of type "string[]", but one of the elements is of type "stdClass".', ]; yield 'not-trimmed' => [ ' is_string ', '[native_function_invocation] Invalid configuration: Each element must be a non-empty, trimmed string, got "string" instead.', ]; } /** * @param _AutogeneratedInputConfiguration['include'] $include * @param class-string<\Throwable> $expectedExceptionClass * * @dataProvider provideConfigureIncludeSetsCases */ public function testConfigureIncludeSets( array $include, ?string $expectedExceptionClass = null, ?string $expectedExceptionMessage = null ): void { if (null !== $expectedExceptionClass) { $this->expectException($expectedExceptionClass); $this->expectExceptionMessageMatches(\sprintf('#^%s$#', preg_quote($expectedExceptionMessage, '#'))); } $this->fixer->configure([ 'include' => $include, ]); if (null === $expectedExceptionClass) { $this->addToAssertionCount(1); } } public static function provideConfigureIncludeSetsCases(): iterable { yield [['foo', 'bar']]; yield [[NativeFunctionInvocationFixer::SET_ALL]]; yield [[NativeFunctionInvocationFixer::SET_ALL, 'bar']]; yield [ ['@xxx'], InvalidFixerConfigurationException::class, '[native_function_invocation] Invalid configuration: Unknown set "@xxx", known sets are "@all", "@internal" and "@compiler_optimized".', ]; yield [ [' x '], InvalidFixerConfigurationException::class, '[native_function_invocation] Invalid configuration: Each element must be a non-empty, trimmed string, got "string" instead.', ]; } public function testConfigureResetsExclude(): void { $this->fixer->configure([ 'exclude' => [ 'is_string', ], ]); $before = <<<'PHP' doTest($before); $this->fixer->configure([]); $this->doTest($after, $before); } /** * @dataProvider provideFixWithDefaultConfigurationCases */ public function testFixWithDefaultConfiguration(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } /** * @return iterable */ public static function provideFixWithDefaultConfigurationCases(): iterable { yield [ ' [ 'fixer->configure([ 'exclude' => [ 'is_string', ], ]); $this->doTest($expected, $input); } /** * @return iterable */ public static function provideFixWithConfiguredExcludeCases(): iterable { yield [ 'fixer->configure(['scope' => $scope]); $this->doTest($expected, $input); } /** * @return iterable */ public static function provideFixWithNamespaceConfigurationCases(): iterable { yield [ ' ', ' ', ]; yield [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public static function provideFixWithConfiguredIncludeCases(): iterable { yield 'include set + 1, exclude 1' => [ ' [NativeFunctionInvocationFixer::SET_INTERNAL, 'some_other'], 'exclude' => ['strlen'], ], ]; yield 'include @all' => [ ' [NativeFunctionInvocationFixer::SET_ALL], ], ]; yield 'include @compiler_optimized' => [ ' [NativeFunctionInvocationFixer::SET_COMPILER_OPTIMIZED], ], ]; yield [ ' [ ' 'namespaced', 'strict' => true, ], ]; yield [ ' [NativeFunctionInvocationFixer::SET_ALL], ], ]; } /** * @param _AutogeneratedInputConfiguration $configuration * * @dataProvider provideFixPre80Cases * * @requires PHP <8.0 */ public function testFixPre80(string $expected, ?string $input = null, array $configuration = []): void { $this->fixer->configure($configuration); $this->doTest($expected, $input); } /** * @return iterable}> */ public static function provideFixPre80Cases(): iterable { yield 'include @compiler_optimized with strict enabled' => [ ' [NativeFunctionInvocationFixer::SET_COMPILER_OPTIMIZED], 'strict' => true, ], ]; yield [ 'fixer->configure($config); $this->doTest($expected, $input); } public static function provideFix80Cases(): iterable { yield 'attribute and strict' => [ ' true], ]; yield 'null safe operator' => ['count();']; yield 'multiple function-calls-like in attribute' => [ ' ['@all']], ]; } }