예제 #1
0
 /**
  * Locate every function or static method call.
  *
  * @param array $tokens
  * @param int   $functionLevel Internal constant used for parsing.
  */
 private function locateCalls(array $tokens, $functionLevel = 0)
 {
     //Multiple "(" and ")" statements nested.
     $parenthesisLevel = 0;
     //Skip all tokens until next function
     $skipTokens = false;
     //Were function was found
     $functionTID = $line = 0;
     //Parsed arguments and their first token id
     $arguments = [];
     $argumentsTID = false;
     //Tokens used to re-enable token detection
     $stopTokens = [T_STRING, T_WHITESPACE, T_DOUBLE_COLON, T_NS_SEPARATOR];
     foreach ($tokens as $TID => $token) {
         $tokenType = $token[self::TOKEN_TYPE];
         //We are not indexing function declarations or functions called from $objects.
         if ($tokenType == T_FUNCTION || $tokenType == T_OBJECT_OPERATOR || $tokenType == T_NEW) {
             //Not a call, function declaration, or object method
             if (!$argumentsTID) {
                 $skipTokens = true;
                 continue;
             }
         } elseif ($skipTokens) {
             if (!in_array($tokenType, $stopTokens)) {
                 //Returning to search
                 $skipTokens = false;
             }
             continue;
         }
         //We are inside function, and there is "(", indexing arguments.
         if ($functionTID && $tokenType == '(') {
             if (!$argumentsTID) {
                 $argumentsTID = $TID;
             }
             $parenthesisLevel++;
             if ($parenthesisLevel != 1) {
                 //Not arguments beginning, but arguments part
                 $arguments[$TID] = $token;
             }
             continue;
         }
         //We are inside function arguments and ")" met.
         if ($functionTID && $tokenType == ')') {
             $parenthesisLevel--;
             if ($parenthesisLevel == -1) {
                 $functionTID = false;
                 $parenthesisLevel = 0;
                 continue;
             }
             //Function fully indexed, we can process it now.
             if (!$parenthesisLevel) {
                 $source = '';
                 for ($tokenID = $functionTID; $tokenID <= $TID; $tokenID++) {
                     //Collecting function usage source
                     $source .= $tokens[$tokenID][self::TOKEN_CODE];
                 }
                 //Will be fixed in future
                 $class = $this->fetchClass($tokens, $functionTID, $argumentsTID);
                 $call = null;
                 if ($class != 'self' && $class != 'static') {
                     $call = new ReflectionCall($this->filename, $line, $class, $this->fetchName($tokens, $functionTID, $argumentsTID), ReflectionArgument::fetchArguments($arguments), $source, $functionTID, $TID, $functionLevel);
                 }
                 //Nested functions can be function in usage arguments.
                 $this->locateCalls($arguments, $functionLevel + 1);
                 !empty($call) && ($this->calls[] = $call);
                 //Closing search
                 $arguments = [];
                 $argumentsTID = $functionTID = false;
             } else {
                 //Not arguments beginning, but arguments part
                 $arguments[$TID] = $token;
             }
             continue;
         }
         //Still inside arguments.
         if ($functionTID && $parenthesisLevel) {
             $arguments[$TID] = $token;
             continue;
         }
         //Nothing valuable to remember, will be parsed later.
         if ($functionTID && in_array($tokenType, $stopTokens)) {
             continue;
         }
         //Seems like we found function/method call
         if ($tokenType == T_STRING || $tokenType == T_STATIC || $tokenType == T_NS_SEPARATOR) {
             $functionTID = $TID;
             $line = $token[self::TOKEN_LINE];
             $parenthesisLevel = 0;
             $argumentsTID = false;
             continue;
         }
         //Returning to search
         $functionTID = false;
         $arguments = [];
     }
 }
예제 #2
0
 /**
  * Registering invocation.
  *
  * @param int   $invocationID
  * @param int   $argumentsID
  * @param int   $endID
  * @param array $arguments
  * @param int   $invocationLevel
  */
 private function registerInvocation($invocationID, $argumentsID, $endID, array $arguments, $invocationLevel)
 {
     //Nested invocations
     $this->locateInvocations($arguments, $invocationLevel + 1);
     list($class, $operator, $name) = $this->fetchContext($invocationID, $argumentsID);
     if (!empty($operator) && empty($class)) {
         //Non detectable
         return;
     }
     $this->invocations[] = new ReflectionInvocation($this->filename, $this->lineNumber($invocationID), $class, $operator, $name, ReflectionArgument::locateArguments($arguments), $this->getSource($invocationID, $endID), $invocationLevel);
 }