예제 #1
0
 /**
  * @param ParsedReflectionClass|ParsedReflectionMethod|ParsedReflectionProperty $point
  * {@inheritdoc}
  */
 public function matches($point)
 {
     $expectedClass = $this->expectedClass;
     if (!$point instanceof $expectedClass) {
         return false;
     }
     $aliases = $point->getNamespaceAliases();
     $this->annotationReader->setImports($aliases);
     $annotation = $this->annotationReader->{$this->annotationMethod}($point, $this->annotationName);
     return (bool) $annotation;
 }
예제 #2
0
    /**
     * Creates definition for trait method body
     *
     * @param ParsedMethod $method Method reflection
     *
     * @return string new method body
     */
    protected function getJoinpointInvocationBody(ParsedMethod $method)
    {
        $isStatic = $method->isStatic();
        $class = '\\' . __CLASS__;
        $scope = $isStatic ? $this->staticLsbExpression : '$this';
        $prefix = $isStatic ? AspectContainer::STATIC_METHOD_PREFIX : AspectContainer::METHOD_PREFIX;
        $args = join(', ', array_map(function (ParsedParameter $param) {
            $byReference = $param->isPassedByReference() ? '&' : '';
            return $byReference . '$' . $param->name;
        }, $method->getParameters()));
        $args = $scope . ($args ? ", array({$args})" : '');
        return <<<BODY
static \$__joinPoint = null;
if (!\$__joinPoint) {
    \$__joinPoint = {$class}::getJoinPoint(__TRAIT__, __CLASS__, '{$prefix}', '{$method->name}');
}
return \$__joinPoint->__invoke({$args});
BODY;
    }
예제 #3
0
 /**
  * Parses child reflection objects from the token stream.
  *
  * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream
  * @param \TokenReflection\IReflection $parent Parent reflection object
  * @return \TokenReflection\ReflectionClass
  * @throws \TokenReflection\Exception\ParseException If a parse error was detected.
  */
 protected function parseChildren(Stream $tokenStream, IReflection $parent)
 {
     while (true) {
         switch ($type = $tokenStream->getType()) {
             case null:
                 break 2;
             case T_COMMENT:
             case T_DOC_COMMENT:
                 $docblock = $tokenStream->getTokenValue();
                 if (preg_match('~^' . preg_quote(self::DOCBLOCK_TEMPLATE_START, '~') . '~', $docblock)) {
                     array_unshift($this->docblockTemplates, new ReflectionAnnotation($this, $docblock));
                 } elseif (self::DOCBLOCK_TEMPLATE_END === $docblock) {
                     array_shift($this->docblockTemplates);
                 }
                 $tokenStream->next();
                 break;
             case '}':
                 break 2;
             case T_PUBLIC:
             case T_PRIVATE:
             case T_PROTECTED:
             case T_STATIC:
             case T_VAR:
             case T_VARIABLE:
                 static $searching = array(T_VARIABLE => true, T_FUNCTION => true);
                 if (T_VAR !== $tokenStream->getType()) {
                     $position = $tokenStream->key();
                     while (null !== ($type = $tokenStream->getType($position)) && !isset($searching[$type])) {
                         $position++;
                     }
                 }
                 if (T_VARIABLE === $type || T_VAR === $type) {
                     $property = new ReflectionProperty($tokenStream, $this->getBroker(), $this);
                     $this->properties[$property->getName()] = $property;
                     $tokenStream->next();
                     break;
                 }
                 // Break missing on purpose
             // Break missing on purpose
             case T_FINAL:
             case T_ABSTRACT:
             case T_FUNCTION:
                 $method = new ReflectionMethod($tokenStream, $this->getBroker(), $this);
                 $this->methods[$method->getName()] = $method;
                 $tokenStream->next();
                 break;
             case T_CONST:
                 $tokenStream->skipWhitespaces(true);
                 while ($tokenStream->is(T_STRING)) {
                     $constant = new ReflectionConstant($tokenStream, $this->getBroker(), $this);
                     $this->constants[$constant->getName()] = $constant;
                     if ($tokenStream->is(',')) {
                         $tokenStream->skipWhitespaces(true);
                     } else {
                         $tokenStream->next();
                     }
                 }
                 break;
             case T_USE:
                 $tokenStream->skipWhitespaces(true);
                 while (true) {
                     $traitName = '';
                     $type = $tokenStream->getType();
                     while (T_STRING === $type || T_NS_SEPARATOR === $type) {
                         $traitName .= $tokenStream->getTokenValue();
                         $type = $tokenStream->skipWhitespaces(true)->getType();
                     }
                     if ('' === trim($traitName, '\\')) {
                         throw new Exception\ParseException($this, $tokenStream, 'An empty trait name found.', Exception\ParseException::LOGICAL_ERROR);
                     }
                     $this->traits[] = Resolver::resolveClassFQN($traitName, $this->aliases, $this->namespaceName);
                     if (';' === $type) {
                         // End of "use"
                         $tokenStream->skipWhitespaces();
                         break;
                     } elseif (',' === $type) {
                         // Next trait name follows
                         $tokenStream->skipWhitespaces();
                         continue;
                     } elseif ('{' !== $type) {
                         // Unexpected token
                         throw new Exception\ParseException($this, $tokenStream, 'Unexpected token found: "%s".', Exception\ParseException::UNEXPECTED_TOKEN);
                     }
                     // Aliases definition
                     $type = $tokenStream->skipWhitespaces(true)->getType();
                     while (true) {
                         if ('}' === $type) {
                             $tokenStream->skipWhitespaces();
                             break 2;
                         }
                         $leftSide = '';
                         $rightSide = array('', null);
                         $alias = true;
                         while (T_STRING === $type || T_NS_SEPARATOR === $type || T_DOUBLE_COLON === $type) {
                             $leftSide .= $tokenStream->getTokenValue();
                             $type = $tokenStream->skipWhitespaces(true)->getType();
                         }
                         if (T_INSTEADOF === $type) {
                             $alias = false;
                         } elseif (T_AS !== $type) {
                             throw new Exception\ParseException($this, $tokenStream, 'Unexpected token found.', Exception\ParseException::UNEXPECTED_TOKEN);
                         }
                         $type = $tokenStream->skipWhitespaces(true)->getType();
                         if (T_PUBLIC === $type || T_PROTECTED === $type || T_PRIVATE === $type) {
                             if (!$alias) {
                                 throw new Exception\ParseException($this, $tokenStream, 'Unexpected token found.', Exception\ParseException::UNEXPECTED_TOKEN);
                             }
                             switch ($type) {
                                 case T_PUBLIC:
                                     $type = InternalReflectionMethod::IS_PUBLIC;
                                     break;
                                 case T_PROTECTED:
                                     $type = InternalReflectionMethod::IS_PROTECTED;
                                     break;
                                 case T_PRIVATE:
                                     $type = InternalReflectionMethod::IS_PRIVATE;
                                     break;
                                 default:
                                     break;
                             }
                             $rightSide[1] = $type;
                             $type = $tokenStream->skipWhitespaces(true)->getType();
                         }
                         while (T_STRING === $type || T_NS_SEPARATOR === $type && !$alias) {
                             $rightSide[0] .= $tokenStream->getTokenValue();
                             $type = $tokenStream->skipWhitespaces(true)->getType();
                         }
                         if (empty($leftSide)) {
                             throw new Exception\ParseException($this, $tokenStream, 'An empty method name was found.', Exception\ParseException::LOGICAL_ERROR);
                         }
                         if ($alias) {
                             // Alias
                             if ($pos = strpos($leftSide, '::')) {
                                 $methodName = substr($leftSide, $pos + 2);
                                 $className = Resolver::resolveClassFQN(substr($leftSide, 0, $pos), $this->aliases, $this->namespaceName);
                                 $leftSide = $className . '::' . $methodName;
                                 $this->traitAliases[$rightSide[0]] = $leftSide;
                             } else {
                                 $this->traitAliases[$rightSide[0]] = '(null)::' . $leftSide;
                             }
                             $this->traitImports[$leftSide][] = $rightSide;
                         } else {
                             // Insteadof
                             if ($pos = strpos($leftSide, '::')) {
                                 $methodName = substr($leftSide, $pos + 2);
                             } else {
                                 throw new Exception\ParseException($this, $tokenStream, 'A T_DOUBLE_COLON has to be present when using T_INSTEADOF.', Exception\ParseException::UNEXPECTED_TOKEN);
                             }
                             $this->traitImports[Resolver::resolveClassFQN($rightSide[0], $this->aliases, $this->namespaceName) . '::' . $methodName][] = null;
                         }
                         if (',' === $type) {
                             $tokenStream->skipWhitespaces(true);
                             continue;
                         } elseif (';' !== $type) {
                             throw new Exception\ParseException($this, $tokenStream, 'Unexpected token found.', Exception\ParseException::UNEXPECTED_TOKEN);
                         }
                         $type = $tokenStream->skipWhitespaces()->getType();
                     }
                 }
                 break;
             default:
                 $tokenStream->next();
                 break;
         }
     }
     return $this;
 }
예제 #4
0
 /**
  * Creates a method code from Reflection
  *
  * @param ParsedMethod $method Reflection for method
  * @param string $body Body of method
  *
  * @return string
  */
 protected function getOverriddenMethod(ParsedMethod $method, $body)
 {
     $code = preg_replace('/ {4}|\\t/', '', $method->getDocComment()) . "\n" . join(' ', Reflection::getModifierNames($method->getModifiers())) . ' function ' . ($method->returnsReference() ? '&' : '') . $method->name . '(' . join(', ', $this->getParameters($method->getParameters())) . ")\n" . "{\n" . $this->indent($body) . "\n" . "}\n";
     return $code;
 }
예제 #5
0
 /**
  * Creates a parameter alias for the given method.
  *
  * @param \TokenReflection\ReflectionMethod $parent New parent method
  * @return \TokenReflection\ReflectionParameter
  */
 public function alias(ReflectionMethod $parent)
 {
     $parameter = clone $this;
     $parameter->declaringClassName = $parent->getDeclaringClassName();
     $parameter->declaringFunctionName = $parent->getName();
     return $parameter;
 }
 /**
  * Tests export.
  */
 public function testToString()
 {
     $tests = array('lines', 'docComment', 'noComment', 'prototype', 'noPrototype', 'parameters', 'reference', 'noReference', 'noClosure', 'noNamespace', 'userDefined', 'shadow');
     foreach ($tests as $test) {
         $rfl = $this->getMethodReflection($test);
         $this->assertSame($rfl->internal->__toString(), $rfl->token->__toString());
         $this->assertSame(InternalReflectionMethod::export($this->getClassName($test), $test, true), ReflectionMethod::export($this->getBroker(), $this->getClassName($test), $test, true));
         $rfl = $this->getMethodReflection($test, true);
         $this->assertSame($rfl->internal->__toString(), $rfl->token->__toString());
         $this->assertSame(InternalReflectionMethod::export($this->getClassName($test), $test, true), ReflectionMethod::export($this->getBroker(), $this->getClassName($test), $test, true));
     }
     $tests = array('constructorDestructor' => array('__construct', '__destruct'), 'clone' => array('__clone', 'noClone'), 'declaringClass' => array('parent', 'child', 'parentOverlay'), 'invoke' => array('publicInvoke', 'protectedInvoke'), 'accessLevel' => array('privateExtended', 'privateNoExtended', 'protectedExtended', 'protectedNoExtended'), 'modifiers' => array('publicAbstract', 'publicFinal', 'publicStatic', 'publicNoStatic', 'protectedAbstract', 'protectedFinal', 'protectedStatic', 'protectedNoStatic', 'privateFinal', 'privateStatic', 'privateNoStatic'));
     foreach ($tests as $class => $classTests) {
         $rfl = $this->getClassReflection($class);
         $rfl_fromString = $this->getClassReflection($class, true);
         foreach ($classTests as $method) {
             // @todo inherits not supported yet
             $this->assertSame(preg_replace('~, inherits [\\w]+~', '', $rfl->internal->getMethod($method)->__toString()), $rfl->token->getMethod($method)->__toString());
             $this->assertSame(preg_replace('~, inherits [\\w]+~', '', InternalReflectionMethod::export($this->getClassName($class), $method, true)), ReflectionMethod::export($this->getBroker(), $this->getClassName($class), $method, true));
             $this->assertSame(preg_replace('~, inherits [\\w]+~', '', $rfl_fromString->internal->getMethod($method)->__toString()), $rfl_fromString->token->getMethod($method)->__toString());
         }
     }
     $this->assertSame(InternalReflectionMethod::export('ReflectionMethod', 'isFinal', true), ReflectionMethod::export($this->getBroker(), 'ReflectionMethod', 'isFinal', true));
     $this->assertSame(InternalReflectionMethod::export(new InternalReflectionMethod('ReflectionMethod', 'isFinal'), 'isFinal', true), ReflectionMethod::export($this->getBroker(), new InternalReflectionMethod('ReflectionMethod', 'isFinal'), 'isFinal', true));
 }
예제 #7
0
 /**
  * Gets the annotations applied to a method.
  *
  * @param ParsedReflectionMethod $method The ReflectionMethod of the method from which
  *                                   the annotations should be read.
  * @return array An array of Annotations.
  */
 public function getMethodAnnotations(ParsedReflectionMethod $method)
 {
     $this->parser->setTarget(Target::TARGET_METHOD);
     return $this->parser->parse($method->getDocComment(), 'method ' . $method->getDeclaringClass()->name . '::' . $method->getName() . '()');
 }