Skip to content
This repository has been archived by the owner on Dec 3, 2023. It is now read-only.

Commit

Permalink
Merge pull request #745 from Symplify/array-line-fixer-line-lenght-ad…
Browse files Browse the repository at this point in the history
…option

[CodingStandard] Array line fixer line lenght adoption
  • Loading branch information
Tomáš Votruba committed Mar 29, 2018
2 parents d5ab44d + a7829dd commit f864c07
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 206 deletions.
Expand Up @@ -10,84 +10,48 @@
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use SplFileInfo;
use Symplify\CodingStandard\Fixer\LineLength\BreakArrayListFixer;
use Symplify\TokenRunner\Analyzer\FixerAnalyzer\IndentDetector;
use Symplify\TokenRunner\Analyzer\FixerAnalyzer\TokenSkipper;
use Symplify\TokenRunner\Configuration\Configuration;
use Symplify\TokenRunner\Analyzer\FixerAnalyzer\BlockStartAndEndFinder;
use Symplify\TokenRunner\Transformer\FixerTransformer\LineLengthTransformer;
use Symplify\TokenRunner\Wrapper\FixerWrapper\ArrayWrapper;
use Symplify\TokenRunner\Wrapper\FixerWrapper\ArrayWrapperFactory;

/**
* @todo consider to make part of
* @see BreakArrayListFixer
*/
final class StandaloneLineInMultilineArrayFixer implements DefinedFixerInterface
{
/**
* @var int[]
*/
private const ARRAY_OPEN_TOKENS = [T_ARRAY, CT::T_ARRAY_SQUARE_BRACE_OPEN];

/**
* @var bool
*/
private $isOldArray = false;

/**
* @var string
*/
private $indentWhitespace;

/**
* @var string
*/
private $newlineIndentWhitespace;

/**
* @var IndentDetector
*/
private $indentDetector;

/**
* @var string
*/
private $closingBracketNewlineIndentWhitespace;

/**
* @var ArrayWrapperFactory
*/
private $arrayWrapperFactory;

/**
* @var TokenSkipper
* @var LineLengthTransformer
*/
private $tokenSkipper;
private $lineLengthTransformer;

/**
* @var Configuration
* @var BlockStartAndEndFinder
*/
private $configuration;
private $blockStartAndEndFinder;

public function __construct(
ArrayWrapperFactory $arrayWrapperFactory,
TokenSkipper $tokenSkipper,
IndentDetector $indentDetector,
Configuration $configuration
LineLengthTransformer $lineLengthTransformer,
BlockStartAndEndFinder $blockStartAndEndFinder
) {
$this->arrayWrapperFactory = $arrayWrapperFactory;
$this->tokenSkipper = $tokenSkipper;
$this->indentDetector = $indentDetector;
$this->configuration = $configuration;
$this->lineLengthTransformer = $lineLengthTransformer;
$this->blockStartAndEndFinder = $blockStartAndEndFinder;
}

public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Indexed PHP arrays with 2 and more items should have 1 item per line.',
[
new CodeSample('<?php $values = [1 => \'hey\', 2 => \'hello\'];'),
]
);
return new FixerDefinition('Indexed PHP arrays with 2 and more items should have 1 item per line.', [
new CodeSample('<?php [1 => \'hey\', 2 => \'hello\'];'),
]);
}

public function isCandidate(Tokens $tokens): bool
Expand All @@ -98,19 +62,26 @@ public function isCandidate(Tokens $tokens): bool

public function fix(SplFileInfo $file, Tokens $tokens): void
{
foreach ($tokens as $index => $token) {
/** @var Token[] $reversedTokens */
$reversedTokens = array_reverse($tokens->toArray(), true);

foreach ($reversedTokens as $index => $token) {
if (! $token->isGivenKind(self::ARRAY_OPEN_TOKENS)) {
continue;
}

$arrayWrapper = $this->arrayWrapperFactory->createFromTokensArrayStartPosition($tokens, $index);
$this->isOldArray = $arrayWrapper->isOldArray();
$blockStartAndEndInfo = $this->blockStartAndEndFinder->findInTokensByBlockStart($tokens, $index);

if (! $arrayWrapper->isAssociativeArray()) {
$arrayWrapper = $this->arrayWrapperFactory->createFromTokensAndBlockStartAndEndInfo(
$tokens,
$blockStartAndEndInfo
);
if ($this->shouldSkip($arrayWrapper)) {
continue;
}

$this->fixArray($tokens, $arrayWrapper);
// $blockStartAndEndInfo = $this->blockStartAndEndFinder->findInTokensByBlockStart($tokens, $index);
$this->lineLengthTransformer->breakItems($blockStartAndEndInfo, $tokens);
}
}

Expand All @@ -134,66 +105,12 @@ public function supports(SplFileInfo $file): bool
return true;
}

private function fixArray(Tokens $tokens, ArrayWrapper $arrayWrapper): void
{
$itemCount = $arrayWrapper->getItemCount();
if ($itemCount <= 1) {
return;
}

$this->prepareIndentWhitespaces($tokens, $arrayWrapper->getStartIndex());

for ($i = $arrayWrapper->getEndIndex() - 1; $i >= $arrayWrapper->getStartIndex(); --$i) {
$i = $this->tokenSkipper->skipBlocksReversed($tokens, $i);

$token = $tokens[$i];

if (! $token->equals(',')) { // item separator behind it
continue;
}

$nextToken = $tokens[$i + 1];

$nextNextToken = $tokens[$i + 2];
// if next token is just space, turn it to newline
if ($nextToken->isWhitespace(' ') && ! $nextNextToken->isComment()) {
$tokens->ensureWhitespaceAtIndex($i + 1, 0, $this->newlineIndentWhitespace);
++$i;
}
}

$this->insertNewlineBeforeClosingIfNeeded($tokens, $arrayWrapper->getEndIndex());
$this->insertNewlineAfterOpeningIfNeeded($tokens, $arrayWrapper->getStartIndex());
}

private function insertNewlineAfterOpeningIfNeeded(Tokens $tokens, int $arrayStartIndex): void
private function shouldSkip(ArrayWrapper $arrayWrapper): bool
{
$offset = $this->isOldArray ? 1 : 0;
if ($tokens[$arrayStartIndex + $offset + 1]->isGivenKind(T_WHITESPACE)) {
return;
if (! $arrayWrapper->isAssociativeArray()) {
return true;
}

$tokens->ensureWhitespaceAtIndex($arrayStartIndex + $offset, 1, $this->newlineIndentWhitespace);
}

private function insertNewlineBeforeClosingIfNeeded(Tokens $tokens, int $arrayEndIndex): void
{
if ($tokens[$arrayEndIndex - 1]->isGivenKind(T_WHITESPACE)) {
$tokens[$arrayEndIndex - 1] = new Token([T_WHITESPACE, $this->closingBracketNewlineIndentWhitespace]);
} else {
$tokens->ensureWhitespaceAtIndex($arrayEndIndex, 0, $this->closingBracketNewlineIndentWhitespace);
}
}

private function prepareIndentWhitespaces(Tokens $tokens, int $arrayStartIndex): void
{
$indentLevel = $this->indentDetector->detectOnPosition($tokens, $arrayStartIndex, $this->configuration);

$this->indentWhitespace = str_repeat($this->configuration->getIndent(), $indentLevel + 1);
$this->closingBracketNewlineIndentWhitespace = $this->configuration->getLineEnding() . str_repeat(
$this->configuration->getIndent(),
$indentLevel
);
$this->newlineIndentWhitespace = $this->configuration->getLineEnding() . $this->indentWhitespace;
return $arrayWrapper->getItemCount() <= 1;
}
}
Expand Up @@ -107,7 +107,7 @@ public function supports(SplFileInfo $file): bool
private function shouldSkip(Tokens $tokens, BlockStartAndEndInfo $blockStartAndEndInfo): bool
{
// no arguments => skip
if (($blockStartAndEndInfo->geEnd() - $blockStartAndEndInfo->getStart()) <= 1) {
if (($blockStartAndEndInfo->getEnd() - $blockStartAndEndInfo->getStart()) <= 1) {
return true;
}

Expand Down
Expand Up @@ -7,7 +7,7 @@
/**
* @see \Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer
*/
final class ArrayNotationTest extends AbstractCheckerTestCase
final class StandaloneLineInMultilineArrayFixerTest extends AbstractCheckerTestCase
{
/**
* @dataProvider provideCorrectCases()
Expand Down
@@ -1,5 +1,6 @@
<?php declare(strict_types=1);

$array = [
'looooooooooooooooooooooooooooooooongArraaaaaaaaaaay', 'looooooooooooooooooooooooooooooooongArraaaaaaaaaaaaaaay'
'looooooooooooooooooooooooooooooooongArraaaaaaaaaaay',
'looooooooooooooooooooooooooooooooongArraaaaaaaaaaaaaaay'
];
Expand Up @@ -5,7 +5,8 @@ class SomeClass
public function someFunction()
{
$result = [
'loooooooooooooooooooooooooooooooongArraaaaaaaaaaay', 'loooooooooooooooooooooongArraaaaaaaaaaaaaaay'
'loooooooooooooooooooooooooooooooongArraaaaaaaaaaay',
'loooooooooooooooooooooongArraaaaaaaaaaaaaaay'
];
}
}
Expand Up @@ -7,9 +7,10 @@ class SomeClass
return [
# form chain method calls
[
__DIR__ . '/NestedMethodCallSource/FormChainMethodCalls.php.inc', 0, 'addRule', [
'Stub_Nette\Forms\Rules'
]
__DIR__ . '/NestedMethodCallSource/FormChainMethodCalls.php.inc',
0,
'addRule',
['Stub_Nette\Forms\Rules']
],
];
}
Expand Down
Expand Up @@ -3,6 +3,7 @@
namespace Symplify\TokenRunner\Analyzer\FixerAnalyzer;

use PhpCsFixer\Tokenizer\Tokens;
use Symplify\TokenRunner\Exception\MissingImplementationException;

final class BlockStartAndEndFinder
{
Expand All @@ -18,6 +19,12 @@ public function findInTokensByBlockStart(Tokens $tokens, int $blockStart): Block
{
$token = $tokens[$blockStart];

// shift "array" to "("
if ($token->isGivenKind(T_ARRAY)) {
$blockStart = $tokens->getNextMeaningfulToken($blockStart);
$token = $tokens[$blockStart];
}

$blockType = $this->getBlockTypeByContent($token->getContent());

return new BlockStartAndEndInfo($blockStart, $tokens->findBlockEnd($blockType, $blockStart));
Expand All @@ -34,15 +41,21 @@ public function findInTokensByPositionAndContent(
}

$blockType = $this->getBlockTypeByContent($content);
if ($blockType === null) {
return null;
}

return new BlockStartAndEndInfo($blockStart, $tokens->findBlockEnd($blockType, $blockStart));
}

private function getBlockTypeByContent(string $content): ?int
private function getBlockTypeByContent(string $content): int
{
return $this->contentToBlockType[$content] ?? null;
if (isset($this->contentToBlockType[$content])) {
return $this->contentToBlockType[$content];
}

throw new MissingImplementationException(sprintf(
'Implementation is missing for "%s" in "%s". Just add it to "%s" property with proper bock type',
$content,
__METHOD__,
'$contentToBlockType'
));
}
}
Expand Up @@ -25,7 +25,7 @@ public function getStart(): int
return $this->start;
}

public function geEnd(): int
public function getEnd(): int
{
return $this->end;
}
Expand Down
@@ -0,0 +1,9 @@
<?php declare(strict_types=1);

namespace Symplify\TokenRunner\Exception;

use Exception;

final class MissingImplementationException extends Exception
{
}

0 comments on commit f864c07

Please sign in to comment.