You are here

protected function VariableAnalysisSniff::checkForFunctionPrototype in Coder 8.2

Checks the function prototype.

Parameters

\PHP_CodeSniffer\Files\File $phpcsFile:

int $stackPtr:

string $varName:

string $currScope:

Return value

bool

1 call to VariableAnalysisSniff::checkForFunctionPrototype()
VariableAnalysisSniff::processVariable in coder_sniffer/DrupalPractice/Sniffs/CodeAnalysis/VariableAnalysisSniff.php
Called to process normal member vars.

File

coder_sniffer/DrupalPractice/Sniffs/CodeAnalysis/VariableAnalysisSniff.php, line 1214

Class

VariableAnalysisSniff
Checks the for undefined function variables.

Namespace

DrupalPractice\Sniffs\CodeAnalysis

Code

protected function checkForFunctionPrototype(File $phpcsFile, $stackPtr, $varName, $currScope) {
  $tokens = $phpcsFile
    ->getTokens();

  // Are we a function or closure parameter?
  // It would be nice to get the list of function parameters from watching for
  // T_FUNCTION, but AbstractVariableSniff and AbstractScopeSniff define everything
  // we need to do that as private or final, so we have to do it this hackish way.
  if (($openPtr = $this
    ->findContainingBrackets($phpcsFile, $stackPtr)) === false) {
    return false;
  }

  // Function names are T_STRING, and return-by-reference is T_BITWISE_AND,
  // so we look backwards from the opening bracket for the first thing that
  // isn't a function name, reference sigil or whitespace and check if
  // it's a function keyword.
  $functionPtr = $phpcsFile
    ->findPrevious(array(
    T_STRING,
    T_WHITESPACE,
    T_BITWISE_AND,
  ), $openPtr - 1, null, true, null, true);
  if ($functionPtr !== false && ($tokens[$functionPtr]['code'] === T_FUNCTION || $tokens[$functionPtr]['code'] === T_CLOSURE)) {

    // TODO: typeHint.
    $this
      ->markVariableDeclaration($varName, 'param', null, $stackPtr, $functionPtr);

    // Are we pass-by-reference?
    $referencePtr = $phpcsFile
      ->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true, null, true);
    if ($referencePtr !== false && $tokens[$referencePtr]['code'] === T_BITWISE_AND) {
      $varInfo = $this
        ->getVariableInfo($varName, $functionPtr);
      $varInfo->passByReference = true;
    }

    // Are we optional with a default?
    if ($this
      ->isNextThingAnAssign($phpcsFile, $stackPtr) !== false) {
      $this
        ->markVariableAssignment($varName, $stackPtr, $functionPtr);
    }
    return true;
  }

  //end if

  // Is it a use keyword?  Use is both a read and a define, fun!
  if ($functionPtr !== false && $tokens[$functionPtr]['code'] === T_USE) {
    $this
      ->markVariableRead($varName, $stackPtr, $currScope);
    if ($this
      ->isVariableUndefined($varName, $stackPtr, $currScope) === true) {

      // We haven't been defined by this point.
      $phpcsFile
        ->addWarning("Variable %s is undefined.", $stackPtr, 'UndefinedVariable', array(
        "\${$varName}",
      ));
      return true;
    }

    // $functionPtr is at the use, we need the function keyword for start of scope.
    $functionPtr = $phpcsFile
      ->findPrevious(T_CLOSURE, $functionPtr - 1, $currScope + 1, false, null, true);
    if ($functionPtr !== false) {

      // TODO: typeHints in use?
      $this
        ->markVariableDeclaration($varName, 'bound', null, $stackPtr, $functionPtr);
      $this
        ->markVariableAssignment($varName, $stackPtr, $functionPtr);

      // Are we pass-by-reference?
      $referencePtr = $phpcsFile
        ->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true, null, true);
      if ($referencePtr !== false && $tokens[$referencePtr]['code'] === T_BITWISE_AND) {
        $varInfo = $this
          ->getVariableInfo($varName, $functionPtr);
        $varInfo->passByReference = true;
      }
      return true;
    }

    //end if
  }

  //end if
  return false;
}