false, self::C_DEFAULTS => false], ), ], ); } public function isCandidate(Tokens $tokens): bool { return $tokens->isAnyTokenKindsFound([T_FUNCTION, T_FN]); } /** * Must run after StatementIndentationFixer, MethodArgumentSpaceFixer */ public function getPriority(): int { return -10; } protected function createConfigurationDefinition(): FixerConfigurationResolverInterface { return new FixerConfigurationResolver([ (new FixerOptionBuilder(self::C_VARIABLES, 'on null no value alignment, on bool forces alignment')) ->setAllowedTypes(['bool', 'null']) ->setDefault(true) ->getOption(), (new FixerOptionBuilder(self::C_DEFAULTS, 'on null no value alignment, on bool forces alignment')) ->setAllowedTypes(['bool', 'null']) ->setDefault(null) ->getOption(), ]); } protected function applyFix(SplFileInfo $file, Tokens $tokens): void { // There is nothing to do if ($this->configuration[self::C_VARIABLES] === null && $this->configuration[self::C_DEFAULTS] === null) { return; } $tokensAnalyzer = new TokensAnalyzer($tokens); $functionsAnalyzer = new FunctionsAnalyzer(); /** @var \PhpCsFixer\Tokenizer\Token $functionToken */ foreach ($tokens as $i => $functionToken) { if (!$functionToken->isGivenKind([T_FUNCTION, T_FN])) { continue; } $openBraceIndex = $tokens->getNextTokenOfKind($i, ['(']); $isMultiline = $tokensAnalyzer->isBlockMultiline($tokens, $openBraceIndex); if (!$isMultiline) { continue; } /** @var \PhpCsFixer\Tokenizer\Analyzer\Analysis\ArgumentAnalysis[] $arguments */ $arguments = $functionsAnalyzer->getFunctionArguments($tokens, $i); if (empty($arguments)) { continue; } $longestType = 0; $longestVariableName = 0; $hasAtLeastOneTypedArgument = false; foreach ($arguments as $argument) { $typeAnalysis = $argument->getTypeAnalysis(); if ($typeAnalysis) { $hasAtLeastOneTypedArgument = true; $typeLength = strlen($typeAnalysis->getName()); if ($typeLength > $longestType) { $longestType = $typeLength; } } $variableNameLength = strlen($argument->getName()); if ($variableNameLength > $longestVariableName) { $longestVariableName = $variableNameLength; } } $argsIndent = WhitespacesAnalyzer::detectIndent($tokens, $i) . $this->whitespacesConfig->getIndent(); foreach ($arguments as $argument) { if ($this->configuration[self::C_VARIABLES] !== null) { $whitespaceIndex = $argument->getNameIndex() - 1; if ($this->configuration[self::C_VARIABLES] === true) { $typeLen = 0; if ($argument->getTypeAnalysis() !== null) { $typeLen = strlen($argument->getTypeAnalysis()->getName()); } $appendix = str_repeat(' ', $longestType - $typeLen + (int)$hasAtLeastOneTypedArgument); if ($argument->hasTypeAnalysis()) { $whitespace = $appendix; } else { $whitespace = $this->whitespacesConfig->getLineEnding() . $argsIndent . $appendix; } } else { if ($argument->hasTypeAnalysis()) { $whitespace = ' '; } else { $whitespace = $this->whitespacesConfig->getLineEnding() . $argsIndent; } } $tokens->ensureWhitespaceAtIndex($whitespaceIndex, 0, $whitespace); } if ($this->configuration[self::C_DEFAULTS] !== null) { // Can't use $argument->hasDefault() because it's null when it's default for a type (e.g. 0 for int) /** @var \PhpCsFixer\Tokenizer\Token $equalToken */ $equalToken = $tokens[$tokens->getNextMeaningfulToken($argument->getNameIndex())]; if ($equalToken->getContent() === '=') { $nameLen = strlen($argument->getName()); $whitespaceIndex = $argument->getNameIndex() + 1; if ($this->configuration[self::C_DEFAULTS] === true) { $tokens->ensureWhitespaceAtIndex($whitespaceIndex, 0, str_repeat(' ', $longestVariableName - $nameLen + 1)); } else { $tokens->ensureWhitespaceAtIndex($whitespaceIndex, 0, ' '); } } } } } } }