/**
  * Returns a FunctionDefinition from a token array.
  *
  * This method will use a set of other methods to parse a token array and retrieve any
  * possible information from it. This information will be entered into a FunctionDefinition object.
  *
  * @param array   $tokens       The token array
  * @param boolean $getRecursive Do we have to get the ancestral conditions as well?
  *
  * @return \TechDivision\PBC\Entities\Definitions\FunctionDefinition
  */
 protected function getDefinitionFromTokens(array $tokens, $getRecursive)
 {
     // First of all we need a new FunctionDefinition to fill
     $functionDefinition = new FunctionDefinition();
     // For our next step we would like to get the doc comment (if any)
     $functionDefinition->docBlock = $this->getDocBlock($tokens, T_FUNCTION);
     // Get the function signature
     $functionDefinition->isFinal = $this->hasSignatureToken($tokens, T_FINAL, T_FUNCTION);
     $functionDefinition->isAbstract = $this->hasSignatureToken($tokens, T_ABSTRACT, T_FUNCTION);
     $functionDefinition->visibility = $this->getFunctionVisibility($tokens);
     $functionDefinition->isStatic = $this->hasSignatureToken($tokens, T_STATIC, T_FUNCTION);
     $functionDefinition->name = $this->getFunctionName($tokens);
     // Lets also get out parameters
     $functionDefinition->parameterDefinitions = $this->getParameterDefinitionList($tokens);
     // Do we have a private context here? If so we have to tell the annotation parser
     $privateContext = false;
     if ($functionDefinition->getVisibility() === 'private') {
         $privateContext = true;
     }
     // So we got our docBlock, now we can parse the precondition annotations from it
     $annotationParser = new AnnotationParser($this->file, $this->config, $this->tokens, $this->currentDefinition);
     $functionDefinition->preconditions = $annotationParser->getConditions($functionDefinition->getDocBlock(), PBC_KEYWORD_PRE, $privateContext);
     // Does this method require the use of our "old" mechanism?
     $functionDefinition->usesOld = $this->usesKeyword($functionDefinition->getDocBlock(), PBC_KEYWORD_OLD);
     // We have to get the body of the function, so we can recreate it
     $functionDefinition->body = $this->getFunctionBody($tokens);
     // So we got our docBlock, now we can parse the postcondition annotations from it
     $functionDefinition->postconditions = $annotationParser->getConditions($functionDefinition->getDocBlock(), PBC_KEYWORD_POST, $privateContext);
     // If we have to parse the definition in a recursive manner, we have to get the parent invariants
     if ($getRecursive === true) {
         // Add all the assertions we might get from ancestral dependencies
         $this->addAncestralAssertions($functionDefinition);
     }
     // All done? Then lock the definition to make it a DTO
     $functionDefinition->lock();
     return $functionDefinition;
 }
 /**
  * Will generate the code used before the original function body
  *
  * @param bool               $injectNeeded       Determine if we have to use a try...catch block
  * @param FunctionDefinition $functionDefinition The function definition object
  *
  * @return string
  */
 protected function generateBeforeCode($injectNeeded, FunctionDefinition $functionDefinition)
 {
     $suffix = PBC_ORIGINAL_FUNCTION_SUFFIX . str_replace('.', '', microtime(true));
     $code = PBC_CONTRACT_CONTEXT . ' = \\TechDivision\\PBC\\ContractContext::open();';
     // Invariant is not needed in private or static functions.
     // Also make sure that there is none in front of the constructor check
     if ($functionDefinition->getVisibility() !== 'private' && !$functionDefinition->getIsStatic() && $functionDefinition->getName() !== '__construct') {
         $code .= PBC_INVARIANT_PLACEHOLDER . PBC_PLACEHOLDER_CLOSE;
     }
     $code .= PBC_PRECONDITION_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE . PBC_OLD_SETUP_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE;
     // If we inject something we might need a try ... catch around the original call.
     if ($injectNeeded === true) {
         $code .= 'try {';
     }
     // Build up the call to the original function.
     $code .= PBC_KEYWORD_RESULT . ' = ' . $functionDefinition->getHeader('call', $suffix) . ';';
     // Finish the try ... catch and place the inject marker
     if ($injectNeeded === true) {
         $code .= '} catch (\\Exception $e) {}' . PBC_METHOD_INJECT_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE;
     }
     // No just place all the other placeholder for other filters to come
     $code .= PBC_POSTCONDITION_PLACEHOLDER . $functionDefinition->getName() . PBC_PLACEHOLDER_CLOSE;
     // Invariant is not needed in private or static functions
     if ($functionDefinition->getVisibility() !== 'private' && !$functionDefinition->getIsStatic()) {
         $code .= PBC_INVARIANT_PLACEHOLDER . PBC_PLACEHOLDER_CLOSE;
     }
     $code .= 'if (' . PBC_CONTRACT_CONTEXT . ') {\\TechDivision\\PBC\\ContractContext::close();}
         return ' . PBC_KEYWORD_RESULT . ';}';
     $code .= $functionDefinition->getHeader('definition', $suffix, true) . '{';
     return $code;
 }