ArraySyntaxFixer.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer\Fixer\ArrayNotation;
  13. use PhpCsFixer\AbstractFixer;
  14. use PhpCsFixer\Fixer\ConfigurableFixerInterface;
  15. use PhpCsFixer\Fixer\ConfigurableFixerTrait;
  16. use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
  17. use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
  18. use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
  19. use PhpCsFixer\FixerDefinition\CodeSample;
  20. use PhpCsFixer\FixerDefinition\FixerDefinition;
  21. use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
  22. use PhpCsFixer\Tokenizer\CT;
  23. use PhpCsFixer\Tokenizer\Token;
  24. use PhpCsFixer\Tokenizer\Tokens;
  25. /**
  26. * @author Gregor Harlan <gharlan@web.de>
  27. * @author Sebastiaan Stok <s.stok@rollerscapes.net>
  28. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  29. *
  30. * @implements ConfigurableFixerInterface<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration>
  31. *
  32. * @phpstan-type _AutogeneratedInputConfiguration array{
  33. * syntax?: 'long'|'short'
  34. * }
  35. * @phpstan-type _AutogeneratedComputedConfiguration array{
  36. * syntax: 'long'|'short'
  37. * }
  38. */
  39. final class ArraySyntaxFixer extends AbstractFixer implements ConfigurableFixerInterface
  40. {
  41. /** @use ConfigurableFixerTrait<_AutogeneratedInputConfiguration, _AutogeneratedComputedConfiguration> */
  42. use ConfigurableFixerTrait;
  43. /**
  44. * @var CT::T_ARRAY_SQUARE_BRACE_OPEN|T_ARRAY
  45. */
  46. private $candidateTokenKind;
  47. public function getDefinition(): FixerDefinitionInterface
  48. {
  49. return new FixerDefinition(
  50. 'PHP arrays should be declared using the configured syntax.',
  51. [
  52. new CodeSample(
  53. "<?php\narray(1,2);\n"
  54. ),
  55. new CodeSample(
  56. "<?php\n[1,2];\n",
  57. ['syntax' => 'long']
  58. ),
  59. ]
  60. );
  61. }
  62. /**
  63. * {@inheritdoc}
  64. *
  65. * Must run before BinaryOperatorSpacesFixer, SingleSpaceAfterConstructFixer, SingleSpaceAroundConstructFixer, TernaryOperatorSpacesFixer.
  66. */
  67. public function getPriority(): int
  68. {
  69. return 37;
  70. }
  71. public function isCandidate(Tokens $tokens): bool
  72. {
  73. return $tokens->isTokenKindFound($this->candidateTokenKind);
  74. }
  75. protected function configurePostNormalisation(): void
  76. {
  77. $this->resolveCandidateTokenKind();
  78. }
  79. protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
  80. {
  81. for ($index = $tokens->count() - 1; 0 <= $index; --$index) {
  82. if ($tokens[$index]->isGivenKind($this->candidateTokenKind)) {
  83. if ('short' === $this->configuration['syntax']) {
  84. $this->fixToShortArraySyntax($tokens, $index);
  85. } else {
  86. $this->fixToLongArraySyntax($tokens, $index);
  87. }
  88. }
  89. }
  90. }
  91. protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
  92. {
  93. return new FixerConfigurationResolver([
  94. (new FixerOptionBuilder('syntax', 'Whether to use the `long` or `short` array syntax.'))
  95. ->setAllowedValues(['long', 'short'])
  96. ->setDefault('short')
  97. ->getOption(),
  98. ]);
  99. }
  100. private function fixToLongArraySyntax(Tokens $tokens, int $index): void
  101. {
  102. $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, $index);
  103. $tokens[$index] = new Token('(');
  104. $tokens[$closeIndex] = new Token(')');
  105. $tokens->insertAt($index, new Token([T_ARRAY, 'array']));
  106. }
  107. private function fixToShortArraySyntax(Tokens $tokens, int $index): void
  108. {
  109. $openIndex = $tokens->getNextTokenOfKind($index, ['(']);
  110. $closeIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openIndex);
  111. $tokens[$openIndex] = new Token([CT::T_ARRAY_SQUARE_BRACE_OPEN, '[']);
  112. $tokens[$closeIndex] = new Token([CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']']);
  113. $tokens->clearTokenAndMergeSurroundingWhitespace($index);
  114. }
  115. private function resolveCandidateTokenKind(): void
  116. {
  117. $this->candidateTokenKind = 'long' === $this->configuration['syntax'] ? CT::T_ARRAY_SQUARE_BRACE_OPEN : T_ARRAY;
  118. }
  119. }