Parse class property annotations

@param $class
@param string $method
@param string $key
@return array
14165
public static function ofMethod($class, $method, $key = null)
	{
		$reflector = is_object($class) ? new \ReflectionObject($class) : new \ReflectionClass($class);

		if(!static::cache()->hasMethod($reflector->getName(), $method)) {
			$annotations = static::parser()->parse($reflector->getMethod($method)->getDocComment());
			static::cache()->storeMethod($reflector->getName(), $method, $annotations);
		}
		else {
			$annotations = static::cache()->getMethod($reflector->getName(), $method);
		}

		if($key) {
			return isset($annotations[$key]) ? $annotations[$key] : null;
		}

		return $annotations;
	}
473611
public static function classHasMethod($method, $class) {
        $methods = self::classMethods($class);

        if (!in_array($method, $methods)) {
          return false;
        }

        return true;
    }
623586
public function getParameters(string $class, string $method = null){
        if(!class_exists($class)){
            throw new \InvalidArgumentException();
        }

        if($method !== null && !method_exists($class, $method)){
            throw new \InvalidArgumentException();
        }

        if(!array_key_exists($class, $this->params)){
            $this->params[$class]   = [];
        }

        $method = $method === null ? "__construct" : $method;

        if(!array_key_exists($method, $this->params[$class])){
            if($method === "__construct" && !method_exists($class, $method)){
                $reflection = null;
            }else{
                $reflection = $this->getClass($class)->getMethod($method);
            }

            $this->params[$class][$method]  = $reflection === null
                ? []
                : $reflection->getParameters()
            ;
        }

        return $this->params[$class][$method];
    }
155695
protected function parseMethodDoc($method)
    {
        // Reflect the method
        $reflectionMethod = new \ReflectionMethod($this, $method);
        // Get method documentation
        $doc = $reflectionMethod->getDocComment();

        // Prepare output
        $output = [];

        $longKey = null;

        // Loop through all lines
        foreach (preg_split("/((\r?\n)|(\r\n?))/", $doc) as $line) {

            // Reset value
            $value = '';
            // Reset key
            $key = '';

            // Remove some unwanted chars from the line
            $line = trim(str_replace('*', '', trim($line)));

            // check if line starts with @api
            if (substr($line, 0, 4) == '@api') {
                // find the annotation and use it as a key/identifier, example: @apiDescription
                preg_match('/^@api[a-zA-Z]*/i', $line, $matches);
                $longKey = $matches[0];

                // remove @api from the key/identifier
                $key = lcfirst(str_replace('@api', '', $longKey));

                // remove whitespace from the line
                $value = trim($line);

                // check if line doesn't have a annotation
            } elseif (!in_array(substr($line, 0, 1), ['@', '/']) && !empty($line)) {
                // check if we have the key/identifier from last loop
                if (!empty($longKey)) {
                    // remove whitespace
                    $value .= trim($line);
                    // create key/identifier by removing @api and making first letter lowercase
                    $key = lcfirst(str_replace('@api', '', $longKey));
                }
            } else {
                // don't include this line in the doc
                $longKey = null;
                continue;
            }

            $output = $this->prepareOutput($output, $key, $value, $longKey);
        }

        return $output;
    }
1360591
public static function readMethod( $method , $annotation = null ) {

		$ref = $method instanceof ReflectionMethod ? $method : new ReflectionMethod( $method[0] , $method[1] );

		return $annotation ? static::reader()->getMethodAnnotation( $ref , $annotation ) : static::reader()->getMethodAnnotations( $ref );

	}
1091463
public function parse(RefClass $class)
    {
        $result = [];

        $annotations = $this->parseComment($class->docComment);
        foreach ($annotations as $annotation) {
            $annotation->originClass = $class->name;
            $result[]                = $annotation;
        }

        foreach ($class->constants as $constant) {
            foreach ($this->parseComment($constant->docComment) as $annotation) {
                $annotation->originClass    = $class->name;
                $annotation->originConstant = $constant->name;
                $result[]                   = $annotation;
            }
        }

        foreach ($class->properties as $property) {
            foreach ($this->parseComment($property->docComment) as $annotation) {
                $annotation->originClass    = $class->name;
                $annotation->originProperty = $property->name;
                $result[]                   = $annotation;
            }
        }

        foreach ($class->methods as $method) {
            foreach ($this->parseComment($method->docComment) as $annotation) {
                $annotation->originClass  = $class->name;
                $annotation->originMethod = $method->name;
                $result[]                 = $annotation;
            }
        }

        return $result;
    }
892330
protected function parseMethods(SimpleXMLElement $class)
    {
        $methods = [];

        $className = (string)$class->full_name;
        $className = ltrim($className, '\\');

        foreach ($class->method as $method) {
            $methodName = (string)$method->name;

            $return = $method->xpath('docblock/tag[@name="return"]');

            if (count($return)) {
                $return = (string)$return[0]['type'];
            } else {
                $return = 'mixed';
            }

            $arguments = [];

            foreach ($method->argument as $argument) {
                $nArgument = [
                    'type' => (string)$argument->type,
                    'name' => (string)$argument->name
                ];

                $tags = $method->xpath(
                    sprintf('docblock/tag[@name="param" and @variable="%s"]', $nArgument['name'])
                );

                if (count($tags)) {
                    $tag = $tags[0];

                    if ((string)$tag['type']) {
                        $nArgument['type'] = (string)$tag['type'];
                    }

                    if ((string)$tag['description']) {
                        $nArgument['description'] = (string)$tag['description'];
                    }

                    if ((string)$tag['variable']) {
                        $nArgument['name'] = (string)$tag['variable'];
                    }
                }

                $arguments[] = $nArgument;
            }

            $argumentStr = implode(', ', array_map(function($argument) {
                $return = $argument['name'];

                if ($argument['type']) {
                    $return = $argument['type'] . ' ' . $return;
                }

                return $return;
            }, $arguments));

            $signature = sprintf('%s %s::%s(%s)', $return, $className, $methodName, $argumentStr);

            $methods[$methodName] = [
                'name'        => $methodName,
                'description' => (string)$method->docblock->description . "\n\n" . (string)$method->docblock->{'long-description'},
                'visibility'  => (string)$method['visibility'],
                'abstract'    => ((string)$method['abstract']) == "true",
                'static'      => ((string)$method['static']) == "true",
                'deprecated'  => count($class->xpath('docblock/tag[@name="deprecated"]')) > 0,
                'signature'   => $signature,
                'arguments'   => $arguments,
                'definedBy'   => $className,
            ];
        }

        return $methods;
    }
1114046
public static function ofClass($class, $key = null)
	{
		$reflector = is_object($class) ? new \ReflectionObject($class) : new \ReflectionClass($class);

		if(!static::cache()->hasClass($reflector->getName())) {
			$annotations = static::parser()->parse($reflector->getDocComment());
			static::cache()->storeClass($reflector->getName(), $annotations);
		}
		else {
			$annotations = static::cache()->getClass($reflector->getName());
		}

		if($key) {
			return isset($annotations[$key]) ? $annotations[$key] : null;
		}

		return $annotations;
	}
35278
public static function getPropertyAnnotations($class, $property)
    {
        $annotationBag = Bridge\Loader::getInstance()->getPropertyAnnotations($class, str_replace('$', '', $property));
        $annotationBag = self::explodeNamespaces($annotationBag);

        return new ConfigObject($annotationBag);
    }
989846
public function parseProp(\ReflectionClass $ref, \ReflectionProperty $prop)
    {
        $annotations = $this->reader->getPropertyAnnotations($prop);
        if($this->checkAnnotations($annotations))
        {
            $this->data[$ref->getName()]['prop'][$prop->getName()] = $this->fileMap[$ref->getFileName()][$ref->getName()]['prop'][$prop->getName()] = &$annotations;
        }
    }
976570
private function getMutatorMethod(string $class, string $property): ?array
    {
        $ucProperty = ucfirst($property);
        $ucSingulars = (array) Inflector::singularize($ucProperty);

        foreach ($this->mutatorPrefixes as $prefix) {
            $names = [$ucProperty];
            if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
                $names = array_merge($names, $ucSingulars);
            }

            foreach ($names as $name) {
                try {
                    $reflectionMethod = new \ReflectionMethod($class, $prefix.$name);
                    if ($reflectionMethod->isStatic()) {
                        continue;
                    }

                    // Parameter can be optional to allow things like: method(array $foo = null)
                    if ($reflectionMethod->getNumberOfParameters() >= 1) {
                        return [$reflectionMethod, $prefix];
                    }
                } catch (\ReflectionException $e) {
                    // Try the next prefix if the method doesn't exist
                }
            }
        }

        return null;
    }
744079
private static function getProperties($class): array
    {
        $reflect = new \ReflectionClass($class);
        $prop = $reflect->getProperties(
            \ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_PRIVATE
        );
        $properties = [];
        foreach ($prop as $property) {
            $properties[] = $property->name;
        }
        $parent = \get_parent_class($class);
        if ($parent) {
            $properties = \array_merge(self::getProperties($parent), $properties);
        }
        return $properties;
    }
914167
public function parser(string $className, $objectAnnotation = null, string $propertyName = "", string $methodName = "", $propertyValue = null)
    {
        $scope    = Scope::PROTOTYPE;
        $name     = $objectAnnotation->getName();
        $beanName = empty($name) ? $className : $name;

        ProcessCollector::collect($className, $objectAnnotation, $propertyName, $methodName, $propertyValue);

        return [$beanName, $scope, ""];
    }
537437
static function getAnnotation($name, $class, $method = NULL, $nullable = TRUE)
	{
		try {
			NULL === $method or $annotation = self::getMethodAnnotation($method, $name, $class);
			isset($annotation) or $annotation = self::getClassAnnotation($class, $name);
		} catch (ReflectionException $e) {
			$annotation = NULL;
		}

		return !$nullable && NULL === $annotation
			? self::annotationClass($name)
			: $annotation;
	}
1023282
public static function getClassMethodArgs($class, string $method)
    {
        static $cache = null;

        if (null !== $cache && isset($cache[$class][$method])) {
            return $cache[$class][$method];
        }

        $reflector = new \ReflectionMethod($class, $method);
        $params = $reflector->getParameters();
        if (empty($params)) {
            $cache[$class][$method] = [];
            return [];
        }
        $args = [];
        foreach ($params as $param) {
            $args[$param->name] = [
                'optional' => $param->isOptional(),
                'variadic' => $param->isVariadic(),
            ];
            if ($param->isOptional() && $param->isDefaultValueAvailable()) {
                $args[$param->name]['default'] = $param->getDefaultValue();
            }
            if ($param->hasType()) {
                $args[$param->name]['type'] = (string)$param->getType();
            }
        }
        $cache[$class][$method] = $args;
        return $args;
    }
568447
public function parse($class, array $meta = [])
    {
        $methods = get_class_methods($class);
        foreach($methods as $method) {
            $query = Annotation::ofMethod($class, $method, 'uri');
            if($query) {
                $this->add($query, [$class, $method], $meta);
            }
        }

        return $this;
    }
33095
public static function fromProperty(
        string $class,
        string $property
    ): array
    {
        try {

            $property = new \ReflectionProperty($class, $property);
        }
        catch (\ReflectionException $e) {

            throw new Exception(
                "Property '{$class}::{$property}' not found.",
                Exception::PROPERTY_NOT_FOUND
            );
        }

        $docComment = $property->getDocComment();

        unset($property);

        if ($docComment === false) {

            return [];
        }

        return Parser::parseDocComment($docComment);
    }