/** * 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; }