/**
  * Will generate the code needed to for managing the attributes in regards to invariants related to them
  *
  * @param \AppserverIo\Doppelgaenger\Entities\Lists\AttributeDefinitionList $attributeDefinitions Defined attributes
  *
  * @return string
  */
 protected function generateAttributeCode(AttributeDefinitionList $attributeDefinitions)
 {
     // We should create attributes to store our attribute types
     $code = '
        /**
         * @var array
         */
         private $' . ReservedKeywords::ATTRIBUTE_STORAGE . ' = array(
             ';
     // After iterate over the attributes and build up our array
     $iterator = $attributeDefinitions->getIterator();
     for ($i = 0; $i < $iterator->count(); $i++) {
         // Get the current attribute for more easy access
         $attribute = $iterator->current();
         // Only enter the attribute if it is used in an invariant and it is not private
         if ($attribute->inInvariant() && $attribute->getVisibility() !== 'private') {
             $code .= '"' . substr($attribute->getName(), 1) . '"';
             $code .= ' => array(
                     "visibility" => "' . $attribute->getVisibility() . '",
                     "line" => "' . $attribute->getLine() . '",
                     ';
             // Now check if we need any keywords for the variable identity
             if ($attribute->isStatic()) {
                 $code .= '"static" => true';
             } else {
                 $code .= '"static" => false';
             }
             $code .= '
                 ),
                 ';
         }
         // Move the iterator
         $iterator->next();
     }
     $code .= ');
     ';
     return $code;
 }
 /**
  * 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
  */
 public 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] === $this->getToken()) {
                     // 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;
                 }
                 /** @var \AppserverIo\Doppelgaenger\Interfaces\TypedListInterface|\Iterator $invariantIterator */
                 $invariantIterator = $listIterator->current()->getIterator();
                 $invariantCount = $invariantIterator->count();
                 for ($k = 0; $k < $invariantCount; $k++) {
                     $attributePosition = strpos($invariantIterator->current()->getString(), '$this->' . ltrim($attributeIterator->current()->getName(), '$'));
                     if ($attributePosition !== false) {
                         // Tell them we were mentioned and persist it
                         $attributeIterator->current()->setInInvariant(true);
                     }
                     $invariantIterator->next();
                 }
                 $listIterator->next();
             }
             $attributeIterator->next();
         }
     }
     return $attributes;
 }