Example #1
0
 public function testIsFollowedWorks()
 {
     $code = '<?php class A { public function foo(){} }';
     $tokens = new TokenCollection(token_get_all($code));
     $searcher = new Searcher();
     $this->assertTrue($searcher->isFollowedBy(T_FUNCTION, 7, $tokens));
 }
Example #2
0
 /**
  * Extract infos from file
  *
  * @param $filename
  * @return Result
  */
 public function extract($filename)
 {
     $result = new Result();
     $tokens = $this->tokenizer->tokenize($filename);
     $nameResolver = new NameResolver();
     // default current values
     $class = $interface = $function = $method = null;
     //        $mapOfAliases = array();
     $len = sizeof($tokens, COUNT_NORMAL);
     for ($n = 0; $n < $len; $n++) {
         $token = $tokens[$n];
         switch ($token->getType()) {
             case T_USE:
                 $alias = $this->extractors->alias->extract($n, $tokens);
                 if (null !== $alias->name && null !== $alias->alias) {
                     $nameResolver->pushAlias($alias);
                 }
                 break;
             case T_NAMESPACE:
                 $namespace = '\\' . $this->searcher->getFollowingName($n, $tokens);
                 $this->extractors->class->setNamespace($namespace);
                 $this->extractors->interface->setNamespace($namespace);
                 break;
             case T_INTERFACE:
                 $class = $this->extractors->interface->extract($n, $tokens);
                 $class->setNameResolver($nameResolver);
                 // push class AND in global AND in local class map
                 $this->result->pushClass($class);
                 $result->pushClass($class);
                 break;
             case T_EXTENDS:
                 $i = $n;
                 $parent = $this->searcher->getFollowingName($i, $tokens);
                 $class->setParent(trim($parent));
                 break;
             case T_CLASS:
                 $class = $this->extractors->class->extract($n, $tokens);
                 $class->setNameResolver($nameResolver);
                 // push class AND in global AND in local class map
                 $this->result->pushClass($class);
                 $result->pushClass($class);
                 break;
             case T_FUNCTION:
                 if ($class) {
                     // avoid closure
                     $next = $tokens[$n + 1];
                     if (T_WHITESPACE != $next->getType()) {
                         continue;
                     }
                     $method = $this->extractors->method->extract($n, $tokens);
                     $method->setNameResolver($nameResolver);
                     $class->pushMethod($method);
                 }
                 break;
         }
     }
     return $result;
 }
Example #3
0
 /**
  * Extract class from position
  *
  * @param $n
  * @param TokenCollection $tokens
  * @return ReflectedClass
  */
 public function extract(&$n, TokenCollection $tokens)
 {
     // is abstract ?
     $prev = $this->searcher->getPrevious($n, $tokens);
     $isAbstract = $prev && T_ABSTRACT === $prev->getType();
     $classname = $this->searcher->getFollowingName($n, $tokens);
     $class = new ReflectedClass($this->namespace, trim($classname));
     $class->setAbstract($isAbstract);
     return $class;
 }
Example #4
0
 /**
  * Extract alias from position
  *
  * @param $n
  * @param TokenCollection $tokens
  * @return ReflectedMethod
  */
 public function extract(&$n, TokenCollection $tokens)
 {
     $alias = $real = null;
     $expression = $this->searcher->getUnder(array(';'), $n, $tokens);
     if (preg_match('!use\\s+(.*)\\s+as\\s+(.*)!i', $expression, $matches)) {
         list(, $real, $alias) = $matches;
     } else {
         if (preg_match('!use\\s+([^\\s\\(]+)\\s*!i', $expression, $matches)) {
             list(, $real) = $matches;
             $alias = $real;
         }
     }
     return (object) array('name' => $real, 'alias' => $alias);
 }
Example #5
0
 /**
  * Extract dependency from call
  *
  * @param $n
  * @param TokenCollection $tokens
  * @return string
  * @throws \LogicException
  */
 public function extract(&$n, TokenCollection $tokens)
 {
     $token = $tokens[$n];
     switch ($token->getType()) {
         case T_PAAMAYIM_NEKUDOTAYIM:
             $prev = $n - 1;
             return $this->searcher->getUnder(array('::'), $prev, $tokens);
             break;
         case T_NEW:
             return $this->searcher->getFollowingName($n, $tokens);
             break;
     }
     throw new \LogicException('Classname of call not found');
 }
Example #6
0
 /**
  * Extract the list of returned values
  *
  * @param ReflectedMethod $method
  * @return $this
  */
 private function extractReturns(ReflectedMethod $method, $n, TokenCollection $tokens)
 {
     $resolver = new TypeResolver();
     // PHP 7
     // we cannot use specific token. The ":" delimiter is a T_STRING token
     $following = $this->searcher->getUnder(array('{', ';'), $n, $tokens);
     if (preg_match('!:(.*)!', $following, $matches)) {
         $type = trim($matches[1]);
         if (empty($type)) {
             return $this;
         }
         $return = new ReflectedReturn($type, ReflectedReturn::VALUE_UNKNOW, ReflectedReturn::STRICT_TYPE_HINT);
         $method->pushReturn($return);
         return $this;
     }
     // array of available values based on code
     if (preg_match_all('!([\\s;]return\\s|^return\\s+)(.*?);!', $method->getContent(), $matches)) {
         foreach ($matches[2] as $m) {
             $value = trim($m, ";\t\n\r\v");
             $return = new ReflectedReturn($resolver->resolve($m), $value, ReflectedReturn::ESTIMATED_TYPE_HINT);
             $method->pushReturn($return);
         }
     }
     return $this;
 }
Example #7
0
 /**
  * Extract class from position
  *
  * @param $n
  * @param TokenCollection $tokens
  * @return ReflectedClass
  */
 public function extract(&$n, TokenCollection $tokens)
 {
     // is PHP7 ?
     $previous = $tokens->get($n - 2);
     if ($previous && T_NEW === $previous->getType()) {
         // anonymous class
         $class = new ReflectedAnonymousClass($this->namespace, 'class@anonymous');
         return $class;
     }
     // is abstract ?
     $prev = $this->searcher->getPrevious($n, $tokens);
     $isAbstract = $prev && T_ABSTRACT === $prev->getType();
     $classname = $this->searcher->getFollowingName($n, $tokens);
     $class = new ReflectedClass($this->namespace, trim($classname));
     $class->setAbstract($isAbstract);
     return $class;
 }
Example #8
0
 /**
  * Extracts content of method
  *
  * @param ReflectedMethod $method
  * @param integer $n
  * @param TokenCollection $tokens
  * @return $this
  */
 private function extractContent(ReflectedMethod $method, $n, TokenCollection $tokens)
 {
     $end = $this->searcher->getPositionOfClosingBrace($n, $tokens);
     if ($end > 0) {
         $collection = $tokens->extract($n, $end);
         $method->setContent($collection->asString());
     }
     return $this;
 }
Example #9
0
 /**
  * Extract dependency from call
  *
  * @param $n
  * @param TokenCollection $tokens
  * @return string
  * @throws \LogicException
  */
 public function extract(&$n, TokenCollection $tokens)
 {
     $token = $tokens[$n];
     switch ($token->getType()) {
         case T_PAAMAYIM_NEKUDOTAYIM:
             $prev = $n - 1;
             $value = $this->searcher->getUnder(array('::'), $prev, $tokens);
             if ($value === 'parent') {
                 $extendPosition = $this->searcher->getExtendPostition($tokens);
                 $parentName = $this->searcher->getFollowingName($extendPosition, $tokens);
                 return $parentName;
             }
             if ($value === 'self' || $value === 'static') {
                 $extendPosition = $this->searcher->getClassNamePosition($tokens);
                 $className = $this->searcher->getFollowingName($extendPosition, $tokens);
                 return $className;
             }
             return $value;
         case T_NEW:
             return $this->searcher->getFollowingName($n, $tokens);
     }
     throw new \LogicException('Classname of call not found');
 }
Example #10
0
 /**
  * Extract dependency from call
  *
  * @param $n
  * @param TokenCollection $tokens
  * @return string
  * @throws \LogicException
  */
 public function extract(&$n, TokenCollection $tokens)
 {
     $token = $tokens[$n];
     $call = null;
     switch ($token->getType()) {
         case T_PAAMAYIM_NEKUDOTAYIM:
             $prev = $n - 1;
             $value = $this->searcher->getUnder(array('::'), $prev, $tokens);
             switch (true) {
                 case $value == 'parent' && $this->currentClass:
                     return $this->currentClass->getParent();
                 case $value == 'parent':
                     // we try to get the name of the parent class
                     $extendPosition = $this->searcher->getExtendPosition($tokens, $n);
                     return $this->searcher->getFollowingName($extendPosition, $tokens);
                 case ($value == 'static' || $value === 'self') && $this->currentClass:
                     return $this->currentClass->getFullname();
                 case $value == 'static' || $value === 'self':
                     $extendPosition = $this->searcher->getClassNamePosition($tokens);
                     return $this->searcher->getFollowingName($extendPosition, $tokens);
                 default:
                     return $value;
             }
         case T_NEW:
             $call = $this->searcher->getFollowingName($n, $tokens);
             if (preg_match('!^(\\w+)!', $call, $matches)) {
                 // fixes PHP 5.4:    (new MyClass)->foo()
                 $call = $matches[1];
             }
             break;
     }
     if (null === $call) {
         throw new \LogicException('Classname of call not found');
     }
     return $call;
 }
Example #11
0
 /**
  * Extract infos from file
  *
  * @param TokenCollection $tokens
  * @return Result
  */
 public function extract($tokens)
 {
     $result = new Result();
     $nameResolver = new NameResolver();
     // default current values
     $class = $interface = $function = $namespace = $method = null;
     $len = sizeof($tokens, COUNT_NORMAL);
     $endAnonymous = 0;
     $mainContextClass = null;
     // class containing a anonymous class
     for ($n = 0; $n < $len; $n++) {
         if ($mainContextClass && $n > $endAnonymous) {
             // anonymous class is finished. We back to parent class
             // methods will be added to the main class now
             $class = $mainContextClass;
             $mainContextClass = null;
         }
         $token = $tokens[$n];
         switch ($token->getType()) {
             case T_USE:
                 $alias = $this->extractors->alias->extract($n, $tokens);
                 if (null !== $alias->name && null !== $alias->alias) {
                     $nameResolver->pushAlias($alias);
                 }
                 break;
             case T_NAMESPACE:
                 $namespace = '\\' . $this->searcher->getFollowingName($n, $tokens);
                 $this->extractors->class->setNamespace($namespace);
                 $this->extractors->interface->setNamespace($namespace);
                 break;
             case T_INTERFACE:
                 $class = $this->extractors->interface->extract($n, $tokens);
                 $class->setNameResolver($nameResolver);
                 // push class AND in global AND in local class map
                 $this->result->pushClass($class);
                 $result->pushClass($class);
                 break;
             case T_EXTENDS:
                 $i = $n;
                 $parent = $this->searcher->getFollowingName($i, $tokens);
                 $class->setParent(trim($parent));
                 break;
             case T_IMPLEMENTS:
                 $i = $n + 1;
                 $contracts = $this->searcher->getUnder(array('{'), $i, $tokens);
                 $contracts = explode(',', $contracts);
                 $contracts = array_map('trim', $contracts);
                 $class->setInterfaces($contracts);
                 break;
             case T_CLASS:
                 $i = $n;
                 // avoid MyClass::class syntax
                 if ($this->searcher->isPrecededBy(T_DOUBLE_COLON, $i, $tokens, 1)) {
                     continue;
                 }
                 $c = $this->extractors->class->extract($n, $tokens);
                 $c->setNameResolver($nameResolver);
                 // push class AND in global AND in local class map
                 $this->result->pushClass($c);
                 $result->pushClass($c);
                 // PHP 7 and inner classes
                 if ($c instanceof ReflectedAnonymousClass) {
                     // avoid to consider anonymous class as main class
                     $p = $n;
                     $endAnonymous = $this->searcher->getPositionOfClosingBrace($p, $tokens);
                     $mainContextClass = $class;
                     // add anonymous class in method
                     if ($method) {
                         $method->pushAnonymousClass($c);
                     }
                 }
                 $class = $c;
                 break;
             case T_FUNCTION:
                 if ($class) {
                     // avoid closure
                     $next = $tokens[$n + 1];
                     if (T_WHITESPACE != $next->getType()) {
                         continue;
                     }
                     $method = $this->extractors->method->extract($n, $tokens, $class);
                     $method->setNamespace($namespace);
                     $class->pushMethod($method);
                 }
                 break;
         }
     }
     return $result;
 }
Example #12
0
 /**
  * Extract class from position
  *
  * @param $n
  * @param TokenCollection $tokens
  * @return ReflectedInterface
  */
 public function extract(&$n, TokenCollection $tokens)
 {
     $classname = $this->searcher->getFollowingName($n, $tokens);
     return new ReflectedInterface($this->namespace, trim($classname));
 }