Safely get class reflection, class loading errors will be blocked and reflection will be
excluded from analysis.

@param string $class

@return \ReflectionClass
185771
protected function classReflection(string $class): \ReflectionClass
    {
        $loader = function ($class) {
            if ($class == LocatorException::class) {
                return;
            }

            throw new LocatorException("Class '{$class}' can not be loaded");
        };

        //To suspend class dependency exception
        spl_autoload_register($loader);

        try {
            //In some cases reflection can thrown an exception if class invalid or can not be loaded,
            //we are going to handle such exception and convert it soft exception
            return new \ReflectionClass($class);
        } catch (\Throwable $e) {
            if ($e instanceof LocatorException && $e->getPrevious() != null) {
                $e = $e->getPrevious();
            }

            $this->getLogger()->error(
                sprintf(
                    "%s: %s in %s:%s",
                    $class,
                    $e->getMessage(),
                    $e->getFile(),
                    $e->getLine()
                ),
                ['error' => $e]
            );

            throw new LocatorException($e->getMessage(), $e->getCode(), $e);
        } finally {
            spl_autoload_unregister($loader);
        }
    }
505906
protected function getSingleton($class) {
		if (isset($this->singletons[$class])) {
			return $this->singletons[$class];
		}

		$instance = $this->getNewInstance($class);
		$this->singletons[$class] = $instance;
		return $instance;
	}
934705
public static function createProxyInstance(string $class)
    {
        if (!isset(self::$proxyCache[$class])) {
            $reflection = new \ReflectionClass($class);

            if (!$reflection->isAbstract()) {
                return $reflection->newInstanceWithoutConstructor();
            }

            $proxyNamespace = '__Proxies';
            $proxyName      = str_replace('\\', '_', $reflection->getName()) . self::$count++;
            $baseClass      = $class;
            $methods        = [];

            foreach ($reflection->getMethods(\ReflectionMethod::IS_ABSTRACT) as $method) {
                $methods[] = self::buildMethod($method);
            }

            $methods = implode(PHP_EOL, $methods);

            $classString = <<<PHP
namespace {$proxyNamespace};

class {$proxyName} extends \\{$baseClass} {
    {$methods}
}
PHP;
            eval($classString);
            self::$proxyCache[$class] = (new \ReflectionClass($proxyNamespace . '\\' . $proxyName))->newInstanceWithoutConstructor();
        }

        return clone self::$proxyCache[$class];
    }
730040
protected function findModuleForClass($class)
    {
        if (ClassInfo::exists($class)) {
            $module = ClassLoader::inst()
                ->getManifest()
                ->getOwnerModule($class);
            if ($module) {
                return $module->getName();
            }
        }

        // If we can't find a class, see if it needs to be fully qualified
        if (strpos($class, '\\') !== false) {
            return null;
        }

        // Find FQN that ends with $class
        $classes = preg_grep(
            '/' . preg_quote("\\{$class}", '\/') . '$/i',
            ClassLoader::inst()->getManifest()->getClassNames()
        );

        // Find all modules for candidate classes
        $modules = array_unique(array_map(function ($class) {
            $module = ClassLoader::inst()->getManifest()->getOwnerModule($class);
            return $module ? $module->getName() : null;
        }, $classes));

        if (count($modules) === 1) {
            return reset($modules);
        }

        // Couldn't find it! Exists in none, or multiple modules.
        return null;
    }
474023
private function getReflectionClass(): \ReflectionClass
    {
        if (null === $this->reflectionClass) {
            $this->reflectionClass = new \ReflectionClass(\get_class($this));
        }

        return $this->reflectionClass;
    }
579522
private function getFromCache(string $class): ?ClassMetadataInterface
    {
        if (null === $this->cache) {
            return null;
        }

        if ($this->cache instanceof Cache) {
            $cached = $this->cache->fetch($class) ?: null;
        } else {
            $class = preg_replace('#[\{\}\(\)/\\\\@:]#', '_', str_replace('_', '__', $class));
            $item = $this->cache->getItem($class);
            $cached = $item->isHit() ? $item->get() : null;
        }

        return $cached;
    }
141023
public function getNewInstance($class) {
		if (isset($this->aliases[$class])) {
			$class = $this->aliases[$class];
		}

		$args = $this->resolveArgs($class, '__construct', " when constructing $class");
		if ($args) {
			$instance = new $class(...$args);
		} else {
			$instance = new $class;
		}

		return $instance;
	}
184857
protected function getPropertyTypes($class)
    {
        $class = new \ReflectionClass($class);
        $properties = $class->getDefaultProperties();
        $propertyTypes = [];

        // This prevents any default string value, so it could be enhanced
        foreach ($properties as $propName => $property) {
            if (is_string($property) && (class_exists($property) || interface_exists($property))) {
                $propertyTypes[$propName] = $property;
            }
        }
        return $propertyTypes;
    }
1244260
public static function getClassAnnotations($class)
    {
        $annotationBag = Bridge\Loader::getInstance()->getClassAnnotations($class);
        $annotationBag = self::explodeNamespaces($annotationBag);

        return new ConfigObject($annotationBag);
    }
150250
private static function reflect($class): \ReflectionClass
    {
        if (is_string($class) && (class_exists($class) || interface_exists($class) || trait_exists($class))) {
            return new \ReflectionClass($class);
        } elseif (is_object($class)) {
            return new \ReflectionObject($class);
        }

        throw new \InvalidArgumentException(
                'Given class must either be an existing class, interface or'
                . ' trait name or class instance, ' . \gettype($class)
                . ' with value "' . $class . '" given'
        );
    }
1329908
public function create($class) {
        $reflectionClass = new ReflectionClass($class);
        $reflectionMethod = $reflectionClass->getConstructor();
        if (!$reflectionMethod) {
            return new $class;
        }
        $params = &$this->fetchDepsFromSignature($reflectionMethod);
        return $reflectionClass->newInstanceArgs($params);
    }
1018825
public static function getInstance($class = null)
    {
        $reflector = null;

        if (class_exists($class)) {
            throw new \Exception(sprintf('Class %s not found', $class));
        }

        $reflector = new ReflectionClass('\\'.$class);

        return new $reflector->name();
    }
777376
public function getConstructor($class)
    {
        $cacheKey = self::CACHE_KEY_CTORS . strtolower($class);

        $reflectedConstructor = $this->cache->fetch($cacheKey);

        if ($reflectedConstructor === false) {
            $reflectionClass      = $this->getClass($class);
            $reflectedConstructor = $reflectionClass->getConstructor();
            $this->cache->store($cacheKey, $reflectedConstructor);
        }

        return $reflectedConstructor;
    }
310856
public function find($class)
    {
        $reflectionClass = new \ReflectionClass($class);

        do {
            $classNamespace = $reflectionClass->getNamespaceName();
            foreach ($this->bundles as $bundleName => $bundleClass) {
                $bundleNamespace = \substr($bundleClass, 0, \strrpos($bundleClass, '\\'));
                if (0 === \strpos($classNamespace, $bundleNamespace)) {
                    return $bundleName;
                }
            }
            $reflectionClass = $reflectionClass->getParentClass();
        } while ($reflectionClass);

        return null;
    }
476990
private function parseClassMetadata($class)
    {
        $metadata = new ClassMetadata($class);

        //Load up parent and interfaces
        $this->loadParentMetadata($metadata);
        $this->loadInterfaceMetadata($metadata);

        //Load Annotations from Reader
        $this->loader->loadClassMetadata($metadata);

        //Store internally
        $this->setParsedClass($class, $metadata);

        if ($this->cache !== null) {
            $this->cache->save($class, $metadata);
        }

        return $metadata;
    }
1044048
public function loadMetadataForClass(\ReflectionClass $class)
    {
        $classMetadata = new ClassMetadata($class->getName());

        // should class be exposed?
        $annotation = $this->reader->getClassAnnotation(
            $class,
            Entity\Expose::class
        );

        $classMetadata->setExposed($annotation !== null);

        // not exposed so just return here
        if (!$classMetadata->isExposed()) {
            return $classMetadata;
        }

        if ($annotation->name) {
            $classMetadata->setExposedName($annotation->name);
        }

        $this->parseProperties($class, $classMetadata);

        while ($class = $class->getParentClass()) {
            $this->parseProperties($class, $classMetadata);
        }

        return $classMetadata;
    }
253839
public static function getClass($class) {
        $cache = null;

        if (is_object($class)) {
            $cache = new Cache('gcs_cache_annotation_' . strtolower(str_replace('\\', '-', get_class($class))), 0);
        }
        else {
            $cache = new Cache('gcs_cache_annotation_' . strtolower(str_replace('\\', '-', $class)), 0);
        }

        if ($cache->isExist() && Config::config()['user']['debug']['environment'] != 'development') {
            return $cache->getCache();
        }

        $data = ['class' => [], 'methods' => [], 'properties' => []];

        $reflectionClass = new \ReflectionClass($class);

        //Class annotations
        $parser = new Parser($reflectionClass->getDocComment());
        $dataClasses = $parser->parse();

        foreach ($dataClasses as $key => $dataClass) {
            $processorClass = new Processor($dataClass);
            array_push($data['class'], [0 => ['annotation' => $dataClass['type'], 'instance' => $processorClass->process()]]);
        }

        //Method annotations
        $methodsName = $reflectionClass->getMethods();

        foreach ($methodsName as $methodName) {
            $method = new \ReflectionMethod($class, $methodName->getName());

            $parser = new Parser($method->getDocComment());
            $dataMethods = $parser->parse();

            if (count($dataMethods) > 0) {
                $data['methods'][$methodName->getName()] = [];

                foreach ($dataMethods as $key => $dataMethod) {
                    $processorMethods = new Processor($dataMethod);
                    array_push($data['methods'][$methodName->getName()], ['annotation' => $dataMethod['type'], 'instance' => $processorMethods->process()]);
                }
            }
        }

        //Properties annotations
        $propertiesNames = $reflectionClass->getProperties();

        foreach ($propertiesNames as $propertyName) {
            $property = new \ReflectionProperty($class, $propertyName->getName());

            $parser = new Parser($property->getDocComment());
            $dataProperties = $parser->parse();

            if (count($dataProperties) > 0) {
                $data['properties'][$propertyName->getName()] = [];

                foreach ($dataProperties as $key => $dataProperty) {
                    $processorProperties = new Processor($dataProperty);
                    array_push($data['properties'][$propertyName->getName()], ['annotation' => $dataProperty['type'], 'instance' => $processorProperties->process()]);
                }
            }
        }

        $cache->setContent($data);
        $cache->setCache();

        return $data;
    }