/**
  * Will flatten all conditions available at the time of the call.
  * That means this method will check which conditions make sense in an inheritance context and will drop the
  * others.
  * This method MUST be protected/private so it will run through \TechDivision\PBC\Entities\AbstractLockableEntity's
  * __call() method which will check the lock status before doing anything.
  *
  * @return bool
  */
 protected function flattenConditions()
 {
     // As our lists only supports unique entries anyway, the only thing left is to check if the condition's
     // assertions can be fulfilled (would be possible as direct assertions), and flatten the contained
     // function definitions as well
     $ancestralConditionIterator = $this->ancestralInvariants->getIterator();
     foreach ($ancestralConditionIterator as $conditionList) {
         $conditionListIterator = $conditionList->getIterator();
         foreach ($conditionListIterator as $assertion) {
         }
     }
     // No flatten all the function definitions we got
     $functionDefinitionIterator = $this->functionDefinitions->getIterator();
     foreach ($functionDefinitionIterator as $functionDefinition) {
         $functionDefinition->flattenConditions();
     }
     return false;
 }
 /**
  * Will generate the code needed to enforce made invariant assertions
  *
  * @param \TechDivision\PBC\Entities\Lists\TypedListList $assertionLists List of assertion lists
  *
  * @return string
  */
 private function generateFunctionCode(TypedListList $assertionLists)
 {
     $code = 'protected function ' . PBC_CLASS_INVARIANT_NAME . '($callingMethod) {' . PBC_CONTRACT_CONTEXT . ' = \\TechDivision\\PBC\\ContractContext::open();if (' . PBC_CONTRACT_CONTEXT . ') {';
     $invariantIterator = $assertionLists->getIterator();
     for ($i = 0; $i < $invariantIterator->count(); $i++) {
         // Create the inner loop for the different assertions
         if ($invariantIterator->current()->count() !== 0) {
             $assertionIterator = $invariantIterator->current()->getIterator();
             $codeFragment = array();
             for ($j = 0; $j < $assertionIterator->count(); $j++) {
                 $codeFragment[] = $assertionIterator->current()->getString();
                 $assertionIterator->next();
             }
             $code .= 'if (!((' . implode(') && (', $codeFragment) . '))){' . PBC_FAILURE_VARIABLE . ' = \'(' . str_replace('\'', '"', implode(') && (', $codeFragment)) . ')\';' . PBC_PROCESSING_PLACEHOLDER . 'invariant' . PBC_PLACEHOLDER_CLOSE . '}';
         }
         // increment the outer loop
         $invariantIterator->next();
     }
     $code .= '}\\TechDivision\\PBC\\ContractContext::close();}';
     return $code;
 }
 /**
  * Will generate the code needed to enforce made precondition assertions
  *
  * @param \TechDivision\PBC\Entities\Lists\TypedListList $assertionLists List of assertion lists
  *
  * @return string
  */
 private function generateCode(TypedListList $assertionLists)
 {
     // We only use contracting if we're not inside another contract already
     $code = '/* BEGIN OF PRECONDITION ENFORCEMENT */
     if (' . PBC_CONTRACT_CONTEXT . ') {
         $passedOne = false;' . PBC_FAILURE_VARIABLE . ' = array();';
     // We need a counter to check how much conditions we got
     $conditionCounter = 0;
     $listIterator = $assertionLists->getIterator();
     for ($i = 0; $i < $listIterator->count(); $i++) {
         // Create the inner loop for the different assertions
         $assertionIterator = $listIterator->current()->getIterator();
         // Only act if we got actual entries
         if ($assertionIterator->count() === 0) {
             // increment the outer loop
             $listIterator->next();
             continue;
         }
         $codeFragment = array();
         for ($j = 0; $j < $assertionIterator->count(); $j++) {
             $codeFragment[] = $assertionIterator->current()->getString();
             $assertionIterator->next();
         }
         // Preconditions need or-ed conditions so we make sure only one conditionlist gets checked
         $conditionCounter++;
         // Code to catch failed assertions
         $code .= 'if ($passedOne === false && !((' . implode(') && (', $codeFragment) . '))){' . PBC_FAILURE_VARIABLE . '[] = \'(' . str_replace('\'', '"', implode(') && (', $codeFragment)) . ')\';
             } else {$passedOne = true;}';
         // increment the outer loop
         $listIterator->next();
     }
     // Preconditions need or-ed conditions so we make sure only one conditionlist gets checked
     $code .= 'if ($passedOne === false){' . PBC_FAILURE_VARIABLE . ' = implode(" and ", ' . PBC_FAILURE_VARIABLE . ');' . PBC_PROCESSING_PLACEHOLDER . 'precondition' . PBC_PLACEHOLDER_CLOSE . '
         }';
     // Closing bracket for contract depth check
     $code .= '}
         /* END OF PRECONDITION ENFORCEMENT */';
     // If there were no assertions we will just return a comment
     if ($conditionCounter === 0) {
         return '/* No preconditions for this function/method */';
     }
     return $code;
 }
 /**
  * Will generate the code needed to enforce made postcondition assertions
  *
  * @param \TechDivision\PBC\Entities\Lists\TypedListList $assertionLists List of assertion lists
  *
  * @return string
  */
 private function generateCode(TypedListList $assertionLists)
 {
     // We only use contracting if we're not inside another contract already
     $code = '/* BEGIN OF POSTCONDITION ENFORCEMENT */
     if (' . PBC_CONTRACT_CONTEXT . ') {';
     // We need a counter to check how much conditions we got
     $conditionCounter = 0;
     $listIterator = $assertionLists->getIterator();
     for ($i = 0; $i < $listIterator->count(); $i++) {
         // Create the inner loop for the different assertions
         $assertionIterator = $listIterator->current()->getIterator();
         // Only act if we got actual entries
         if ($assertionIterator->count() === 0) {
             // increment the outer loop
             $listIterator->next();
             continue;
         }
         $codeFragment = array();
         for ($j = 0; $j < $assertionIterator->count(); $j++) {
             $codeFragment[] = $assertionIterator->current()->getString();
             // Forward the iterator and tell them we got a condition
             $assertionIterator->next();
             $conditionCounter++;
         }
         // Lets insert the condition check (if there have been any)
         if (!empty($codeFragment)) {
             $code .= 'if (!((' . implode(') && (', $codeFragment) . '))){' . PBC_FAILURE_VARIABLE . ' = \'(' . str_replace('\'', '"', implode(') && (', $codeFragment)) . ')\';' . PBC_PROCESSING_PLACEHOLDER . 'postcondition' . PBC_PLACEHOLDER_CLOSE . '}';
         }
         // increment the outer loop
         $listIterator->next();
     }
     // Closing bracket for contract depth check
     $code .= '}' . '/* END OF POSTCONDITION ENFORCEMENT */';
     // Did we get anything at all? If not only give back a comment.
     if ($conditionCounter === 0) {
         $code = '/* No postconditions for this function/method */';
     }
     return $code;
 }
Пример #5
0
 /**
  * Retrieves class attributes from token array.
  *
  * This method will search for any attributes a class might have. Just pass the token array of the class.
  * Work is done using token definitions and common sense in regards to PHP syntax.
  * To retrieve the different properties of an attribute it relies on getAttributeProperties().
  * We need the list of invariants to mark attributes wo are under surveillance.
  *
  * @param array         $tokens     Array of tokens for this class
  * @param TypedListList $invariants List of invariants so we can compare the attributes to
  *
  * @return AttributeDefinitionList
  */
 protected function getAttributes(array $tokens, TypedListList $invariants = null)
 {
     // Check the tokens
     $attributes = new AttributeDefinitionList();
     for ($i = 0; $i < count($tokens); $i++) {
         // If we got a variable we will check if there is any function definition above it.
         // If not, we got an attribute, if so we will check if there is an even number of closing and opening
         // brackets above it, which would mean we are not in the function.
         if (is_array($tokens[$i]) && $tokens[$i][0] === T_VARIABLE) {
             for ($j = $i - 1; $j >= 0; $j--) {
                 if (is_array($tokens[$j]) && $tokens[$j][0] === T_FUNCTION) {
                     // Initialize our counter and also the check if we even started counting
                     $bracketCounter = 0;
                     $usedCounter = false;
                     // We got something, lets count the brackets between it and our variable's position
                     for ($k = $j + 1; $k < $i; $k++) {
                         if ($tokens[$k] === '{' || $tokens[$k][0] === T_CURLY_OPEN) {
                             $usedCounter = true;
                             $bracketCounter++;
                         } elseif ($tokens[$k] === '}') {
                             $usedCounter = true;
                             $bracketCounter--;
                         }
                     }
                     // If we got an even number of brackets (the counter is 0 and got used), we got an attribute
                     if ($bracketCounter === 0 && $usedCounter === true) {
                         $attributes->set($tokens[$i][1], $this->getAttributeProperties($tokens, $i));
                     }
                     break;
                 } elseif (is_array($tokens[$j]) && $tokens[$j][0] === T_CLASS) {
                     // If we reach the class definition without passing a function we definitely got an attribute
                     $attributes->set($tokens[$i][1], $this->getAttributeProperties($tokens, $i));
                     break;
                 }
             }
         }
     }
     // If we got invariants we will check if our attributes are used in invariants
     if ($invariants !== null) {
         // Lets iterate over all the attributes and check them against the invariants we got
         $listIterator = $invariants->getIterator();
         $listCount = $listIterator->count();
         $attributeIterator = $attributes->getIterator();
         $attributeCount = $attributeIterator->count();
         for ($i = 0; $i < $attributeCount; $i++) {
             // Do we have any of these attributes in our invariants?
             $listIterator = $invariants->getIterator();
             for ($j = 0; $j < $listCount; $j++) {
                 // Did we get anything useful?
                 if ($listIterator->current() === null) {
                     continue;
                 }
                 $invariantIterator = $listIterator->current()->getIterator();
                 $invariantCount = $invariantIterator->count();
                 for ($k = 0; $k < $invariantCount; $k++) {
                     $attributePosition = strpos($invariantIterator->current()->getString(), '$this->' . ltrim($attributeIterator->current()->name, '$'));
                     if ($attributePosition !== false) {
                         // Tell them we were mentioned and persist it
                         $attributeIterator->current()->inInvariant = true;
                     }
                     $invariantIterator->next();
                 }
                 $listIterator->next();
             }
             $attributeIterator->next();
         }
     }
     return $attributes;
 }