AbstractFunctionReferenceFixer.php 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  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;
  13. use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer;
  14. use PhpCsFixer\Tokenizer\Tokens;
  15. /**
  16. * @internal
  17. *
  18. * @author Vladimir Reznichenko <kalessil@gmail.com>
  19. */
  20. abstract class AbstractFunctionReferenceFixer extends AbstractFixer
  21. {
  22. /**
  23. * @var null|FunctionsAnalyzer
  24. */
  25. private $functionsAnalyzer;
  26. public function isCandidate(Tokens $tokens): bool
  27. {
  28. return $tokens->isTokenKindFound(T_STRING);
  29. }
  30. public function isRisky(): bool
  31. {
  32. return true;
  33. }
  34. /**
  35. * Looks up Tokens sequence for suitable candidates and delivers boundaries information,
  36. * which can be supplied by other methods in this abstract class.
  37. *
  38. * @return ?array{int, int, int} returns $functionName, $openParenthesis, $closeParenthesis packed into array
  39. */
  40. protected function find(string $functionNameToSearch, Tokens $tokens, int $start = 0, ?int $end = null): ?array
  41. {
  42. if (null === $this->functionsAnalyzer) {
  43. $this->functionsAnalyzer = new FunctionsAnalyzer();
  44. }
  45. // make interface consistent with findSequence
  46. $end ??= $tokens->count();
  47. // find raw sequence which we can analyse for context
  48. $candidateSequence = [[T_STRING, $functionNameToSearch], '('];
  49. $matches = $tokens->findSequence($candidateSequence, $start, $end, false);
  50. if (null === $matches) {
  51. return null; // not found, simply return without further attempts
  52. }
  53. // translate results for humans
  54. [$functionName, $openParenthesis] = array_keys($matches);
  55. if (!$this->functionsAnalyzer->isGlobalFunctionCall($tokens, $functionName)) {
  56. return $this->find($functionNameToSearch, $tokens, $openParenthesis, $end);
  57. }
  58. return [$functionName, $openParenthesis, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openParenthesis)];
  59. }
  60. }