FunctionCallSpaceFixer.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <?php
  2. /*
  3. * This file is part of the PHP CS utility.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace Symfony\CS\Fixer\PSR2;
  11. use Symfony\CS\AbstractFixer;
  12. use Symfony\CS\Tokenizer\Tokens;
  13. /**
  14. * Fixer for rules defined in PSR2 ¶4.6.
  15. *
  16. * @author Varga Bence <vbence@czentral.org>
  17. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  18. */
  19. class FunctionCallSpaceFixer extends AbstractFixer
  20. {
  21. /**
  22. * {@inheritdoc}
  23. */
  24. public function fix(\SplFileInfo $file, $content)
  25. {
  26. $tokens = Tokens::fromCode($content);
  27. $functionyTokens = $this->getFunctionyTokenKinds();
  28. $languageConstructionTokens = $this->getLanguageConstructionTokenKinds();
  29. foreach ($tokens as $index => $token) {
  30. // looking for start brace
  31. if (!$token->equals('(')) {
  32. continue;
  33. }
  34. // last non-whitespace token
  35. $lastTokenIndex = $tokens->getPrevNonWhitespace($index);
  36. if (null === $lastTokenIndex) {
  37. continue;
  38. }
  39. // check for ternary operator
  40. $endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index);
  41. $nextNonWhiteSpace = $tokens->getNextMeaningfulToken($endParenthesisIndex);
  42. if (
  43. !empty($nextNonWhiteSpace)
  44. && $tokens[$nextNonWhiteSpace]->equals('?')
  45. && $tokens[$lastTokenIndex]->isGivenKind($languageConstructionTokens)
  46. ) {
  47. continue;
  48. }
  49. // check if it is a function call
  50. if ($tokens[$lastTokenIndex]->isGivenKind($functionyTokens)) {
  51. $this->fixFunctionCall($tokens, $index);
  52. }
  53. }
  54. return $tokens->generateCode();
  55. }
  56. /**
  57. * {@inheritdoc}
  58. */
  59. public function getDescription()
  60. {
  61. return 'When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis.';
  62. }
  63. /**
  64. * Fixes whitespaces around braces of a function(y) call.
  65. *
  66. * @param Tokens $tokens tokens to handle
  67. * @param int $index index of token
  68. */
  69. private function fixFunctionCall(Tokens $tokens, $index)
  70. {
  71. // remove space before opening brace
  72. if ($tokens[$index - 1]->isWhitespace()) {
  73. $tokens[$index - 1]->clear();
  74. }
  75. }
  76. /**
  77. * Gets the token kinds which can work as function calls.
  78. *
  79. * @return int[] Token names.
  80. */
  81. private function getFunctionyTokenKinds()
  82. {
  83. static $tokens = null;
  84. if (null === $tokens) {
  85. $tokens = array(
  86. T_ARRAY,
  87. T_ECHO,
  88. T_EMPTY,
  89. T_EVAL,
  90. T_EXIT,
  91. T_INCLUDE,
  92. T_INCLUDE_ONCE,
  93. T_ISSET,
  94. T_LIST,
  95. T_PRINT,
  96. T_REQUIRE,
  97. T_REQUIRE_ONCE,
  98. T_STRING, // for real function calls
  99. T_UNSET,
  100. );
  101. }
  102. return $tokens;
  103. }
  104. /**
  105. * Gets the token kinds of actually language construction.
  106. *
  107. * @return int[]
  108. */
  109. private function getLanguageConstructionTokenKinds()
  110. {
  111. static $languageConstructionTokens = array(
  112. T_ECHO,
  113. T_PRINT,
  114. T_INCLUDE,
  115. T_INCLUDE_ONCE,
  116. T_REQUIRE,
  117. T_REQUIRE_ONCE,
  118. );
  119. return $languageConstructionTokens;
  120. }
  121. }