/** * Compacts the docblock and its annotations. * * @param string $docblock The docblock. * * @return string The compacted docblock. */ private function compactAnnotations($docblock) { $annotations = array(); $index = -1; $inside = 0; $tokens = $this->tokenizer->parse($docblock); if (empty($tokens)) { return str_repeat("\n", substr_count($docblock, "\n")); } foreach ($tokens as $token) { if (0 === $inside && DocLexer::T_AT === $token[0]) { $index++; } elseif (DocLexer::T_OPEN_PARENTHESIS === $token[0]) { $inside++; } elseif (DocLexer::T_CLOSE_PARENTHESIS === $token[0]) { $inside--; } if (!isset($annotations[$index])) { $annotations[$index] = array(); } $annotations[$index][] = $token; } $breaks = substr_count($docblock, "\n"); $docblock = "/**"; foreach ($annotations as $annotation) { $annotation = new Tokens($annotation); $docblock .= "\n" . $this->converter->convert($annotation); } $breaks -= count($annotations); if ($breaks > 0) { $docblock .= str_repeat("\n", $breaks - 1); $docblock .= "\n*/"; } else { $docblock .= ' */'; } return $docblock; }
/** * Will return one pointcut which does specifically only match the joinpoints of the structure * which this docblock belongs to * * @param string $docBlock The DocBlock to search in * @param string $targetType Type of the target any resulting joinpoints have, e.g. Joinpoint::TARGET_METHOD * @param string $targetName Name of the target any resulting joinpoints have * * @return \AppserverIo\Doppelgaenger\Entities\Lists\PointcutExpressionList */ public function getPointcutExpressions($docBlock, $targetType, $targetName) { $pointcutExpressions = new PointcutExpressionList(); // get our tokenizer and parse the doc Block $tokenizer = new Tokenizer(); $tokenizer->ignore(array('param', 'return', 'throws')); $tokens = new Tokens($tokenizer->parse($docBlock)); // convert to array and run it through our advice factory $toArray = new ToArray(); $annotations = $toArray->convert($tokens); // create the entities for the join-points and advices the pointcut describes foreach ($annotations as $annotation) { // filter out the annotations which are no proper join-points if (!class_exists('\\AppserverIo\\Psr\\MetaobjectProtocol\\Aop\\Annotations\\Advices\\' . $annotation->name)) { continue; } // build the join-point $joinpoint = new Joinpoint(); $joinpoint->setTarget($targetType); $joinpoint->setCodeHook($annotation->name); $joinpoint->setStructure($this->currentDefinition->getQualifiedName()); $joinpoint->setTargetName($targetName); // build the pointcut(s) foreach ($annotation->values as $rawAdvice) { // as it might be an array we have to sanitize it first if (!is_array($rawAdvice)) { $rawAdvice = array($rawAdvice); } foreach ($rawAdvice as $adviceString) { // create the pointcut $pointcutExpression = new PointcutExpression($adviceString); $pointcutExpression->setJoinpoint($joinpoint); $pointcutExpressions->add($pointcutExpression); } } } return $pointcutExpressions; }
/** * @param $comment * @return mixed */ public function parse($comment) { return $this->annotationToArray->convert(new Tokens($this->annotationTokenizer->parse($comment))); }
/** * Returns the property type found in the properties configuration * annotation. * * @param \ReflectionProperty $reflectionProperty The property to return the type for * * @throws \Exception Is thrown if the property has NO bean annotation * @return Mapping The found property type mapping */ public function getPropertyTypeFromDocComment(\ReflectionProperty $reflectionProperty) { // initialize the annotation tokenizer $tokenizer = new Tokenizer(); // set the aliases $aliases = array('AS' => 'AppserverIo\\Description\\Api\\Node'); // parse the doc block $parsed = $tokenizer->parse($reflectionProperty->getDocComment(), $aliases); // convert tokens and return one $tokens = new Tokens($parsed); $toArray = new ToArray(); // iterate over the tokens foreach ($toArray->convert($tokens) as $token) { if ($token->name == 'AppserverIo\\Description\\Api\\Node\\Mapping') { return new $token->name($token); } } }
public function testParseInvalidMatchAny() { $this->setExpectedException('Herrera\\Annotations\\Exception\\SyntaxException', 'Expected Doctrine\\Common\\Annotations\\DocLexer::T_INTEGER or Doctrine\\Common\\Annotations\\DocLexer::T_STRING, received \'@\' at position 4.'); $this->tokenizer->parse('/**@a({@:1})'); }
/** * Will register a complete aspect to the AspectRegister. * This include its advices and pointcuts which can be looked up from this point on * * @param \AppserverIo\Doppelgaenger\Entities\Definitions\AspectDefinition $aspectDefinition Structure to register as an aspect * * @return null */ public function register(AspectDefinition $aspectDefinition) { // create the new aspect and fill it with things we already know $aspect = new Aspect(); $aspect->setName($aspectDefinition->getName()); $aspect->setNamespace($aspectDefinition->getNamespace()); // prepare the tokenizer we will need for further processing $needles = array(AfterReturning::ANNOTATION, AfterThrowing::ANNOTATION, After::ANNOTATION, Around::ANNOTATION, Before::ANNOTATION); $tokenizer = new Tokenizer(); $tokenizer->ignore(array('param', 'return', 'throws')); // iterate the functions and filter out the ones used as advices $scheduledAdviceDefinitions = array(); foreach ($aspectDefinition->getFunctionDefinitions() as $functionDefinition) { $foundNeedle = false; foreach ($needles as $needle) { // create the advice if (strpos($functionDefinition->getDocBlock(), '@' . $needle) !== false) { $foundNeedle = true; $scheduledAdviceDefinitions[$needle][] = $functionDefinition; break; } } // create the pointcut if (!$foundNeedle && strpos($functionDefinition->getDocBlock(), '@' . Pointcut::ANNOTATION) !== false) { $pointcut = new PointcutDefinition(); $pointcut->setName($functionDefinition->getName()); $tokens = new Tokens($tokenizer->parse($functionDefinition->getDocBlock())); // convert to array and run it through our advice factory $toArray = new ToArray(); $annotations = $toArray->convert($tokens); // create the entities for the join-points and advices the pointcut describes $pointcut->setPointcutExpression(new PointcutExpression(array_pop(array_pop($annotations)->values))); $aspect->getPointcuts()->add($pointcut); } } $this->add($aspect); // do the pointcut lookups where we will need the pointcut factory for later use $pointcutFactory = new PointcutFactory(); foreach ($scheduledAdviceDefinitions as $codeHook => $hookedAdviceDefinitions) { foreach ($hookedAdviceDefinitions as $scheduledAdviceDefinition) { // create our advice $advice = new Advice(); $advice->setAspectName($aspectDefinition->getQualifiedName()); $advice->setName($scheduledAdviceDefinition->getName()); $advice->setCodeHook((string) $codeHook); $tokens = new Tokens($tokenizer->parse($scheduledAdviceDefinition->getDocBlock())); // convert to array and run it through our advice factory $toArray = new ToArray(); $annotations = $toArray->convert($tokens); // create the entities for the join-points and advices the pointcut describes foreach ($annotations as $annotation) { $pointcut = $pointcutFactory->getInstance(array_pop($annotation->values)); if ($pointcut instanceof PointcutPointcut) { // get the referenced pointcuts for the split parts of the expression $expressionParts = explode(PointcutPointcut::EXPRESSION_CONNECTOR, $pointcut->getExpression()); // lookup all the referenced pointcuts $referencedPointcuts = array(); foreach ($expressionParts as $expressionPart) { $referencedPointcuts = array_merge($referencedPointcuts, $this->lookupPointcuts($expressionPart)); } $pointcut->setReferencedPointcuts($referencedPointcuts); } $advice->getPointcuts()->add($pointcut); } $aspect->getAdvices()->add($advice); } } $this->set($aspectDefinition->getQualifiedName(), $aspect); }
/** * Initializes and returns an array with annotation instances from the * passed doc comment. * * @param string $docComment The doc comment to initialize the annotations from * @param array $ignore Array with annotations we want to ignore * @param array $aliases Array with aliases to create annotation instances with * * @return array The array with the ReflectionAnnotation instances loaded from the passed doc comment */ public static function fromDocComment($docComment, array $ignore = array(), array $aliases = array()) { // initialize the array for the annotations $annotations = array(); // initialize the annotation tokenizer $tokenizer = new Tokenizer(); $tokenizer->ignore($ignore); // parse the doc block $parsed = $tokenizer->parse($docComment, $aliases); // convert tokens and return one $tokens = new Tokens($parsed); $toArray = new ToArray(); // register annotations with the real annotation name (not the alias) foreach ($toArray->convert($tokens) as $token) { // check if we've an annotation that matched an alias if (array_key_exists($token->name, $flipped = array_flip($aliases))) { $annotationName = $flipped[$token->name]; } else { $annotationName = $token->name; } // register the annotation with the real annotation name (not the alias) $annotations[$annotationName] = ReflectionAnnotation::fromStdClass($token, $aliases); } // return the list with the annotation instances return $annotations; }