Builds a class definition from reflection.

@param \ReflectionClass $class

@return ClassDefinition
349543
public static function buildFromReflection(\ReflectionClass $class)
    {
        $classDefinition = new self($class->getNamespaceName(), $class->getName(), $class->getShortName());

        $methods = $class->getMethods();
        if (\count($methods) > 0) {
            foreach ($methods as $method) {
                $parameters = [];

                foreach ($method->getParameters() as $row) {
                    $params = [
                        'type' => 'parameter',
                        'name' => $row->getName(),
                        'const' => 0,
                        'data-type' => 'variable',
                        'mandatory' => !$row->isOptional(),
                    ];
                    if (!$params['mandatory']) {
                        try {
                            $params['default'] = $row->getDefaultValue();
                        } catch (\ReflectionException $e) {
                            // TODO: dummy default value
                            $params['default'] = true;
                        }
                    }
                    $parameters[] = $params;
                }

                $classMethod = new ClassMethod(
                    $classDefinition,
                    [],
                    $method->getName(),
                    new ClassMethodParameters($parameters)
                );
                $classMethod->setIsStatic($method->isStatic());
                $classMethod->setIsBundled(true);
                $classDefinition->addMethod($classMethod);
            }
        }

        $constants = $class->getConstants();
        if (\count($constants) > 0) {
            foreach ($constants as $constantName => $constantValue) {
                $type = self::_convertPhpConstantType(\gettype($constantValue));
                $classConstant = new ClassConstant($constantName, ['value' => $constantValue, 'type' => $type], null);
                $classDefinition->addConstant($classConstant);
            }
        }

        $properties = $class->getProperties();
        if (\count($properties) > 0) {
            foreach ($properties as $property) {
                $visibility = [];

                if ($property->isPublic()) {
                    $visibility[] = 'public';
                }

                if ($property->isPrivate()) {
                    $visibility[] = 'private';
                }

                if ($property->isProtected()) {
                    $visibility[] = 'protected';
                }

                if ($property->isStatic()) {
                    $visibility[] = 'static';
                }

                $classProperty = new ClassProperty(
                    $classDefinition,
                    $visibility,
                    $property->getName(),
                    null,
                    null,
                    null
                );
                $classDefinition->addProperty($classProperty);
            }
        }

        $classDefinition->setIsBundled(true);

        return $classDefinition;
    }
960897
public function getReflection($class)
    {
        $isObject = is_object($class);
        $identity = $isObject
            ? ObjectIdentity::createFromObject($class)
            : new ObjectIdentity(sprintf('%s@%s', \ReflectionClass::class, $class));
        
        if (!$this->hasShared($identity->getIdentifier())) {
            $reflection = $isObject ? new \ReflectionObject($class) : new \ReflectionClass($class);
            $this->setShared($identity->getIdentifier(), $reflection);
        }
        
        return $this->getShared($identity->getIdentifier());
    }
222551
public function generate(\ReflectionClass $originalClass, PhpClass $class)
    {
        $methods = ReflectionUtils::getOverrideableMethods($originalClass, true);

        // no public, non final methods
        if (empty($methods)) {
            return;
        }

        if (null !== $this->markerInterface) {
            $class->setImplementedInterfaces(array_merge(
                $class->getImplementedInterfaces(),
                array($this->markerInterface)
            ));
        }

        $initializer = new PhpProperty();
        $initializer->setName($this->prefix.'lazyInitializer');
        $initializer->setVisibility(PhpProperty::VISIBILITY_PRIVATE);
        $class->setProperty($initializer);

        $initialized = new PhpProperty();
        $initialized->setName($this->prefix.'initialized');
        $initialized->setDefaultValue(false);
        $initialized->setVisibility(PhpProperty::VISIBILITY_PRIVATE);
        $class->setProperty($initialized);

        $initializerSetter = new PhpMethod();
        $initializerSetter->setName($this->prefix.'setLazyInitializer');
        $initializerSetter->setBody('$this->'.$this->prefix.'lazyInitializer = $initializer;');

        $parameter = new PhpParameter();
        $parameter->setName('initializer');
        $parameter->setType('\CG\Proxy\LazyInitializerInterface');
        $initializerSetter->addParameter($parameter);
        $class->setMethod($initializerSetter);

        $this->addMethods($class, $methods);

        $initializingMethod = new PhpMethod();
        $initializingMethod->setName($this->prefix.'initialize');
        $initializingMethod->setVisibility(PhpMethod::VISIBILITY_PRIVATE);
        $initializingMethod->setBody(
            $this->writer
                ->reset()
                ->writeln('if (null === $this->'.$this->prefix.'lazyInitializer) {')
                    ->indent()
                    ->writeln('throw new \RuntimeException("'.$this->prefix.'setLazyInitializer() must be called prior to any other public method on this object.");')
                    ->outdent()
                ->write("}\n\n")
                ->writeln('$this->'.$this->prefix.'lazyInitializer->initializeObject($this);')
                ->writeln('$this->'.$this->prefix.'initialized = true;')
                ->getContent()
        );
        $class->setMethod($initializingMethod);
    }
899646
public function getClassReflector($class)
    {
        if (is_object($class)) {
            $class = get_class($class);
        }
        if (!isset($this->reflectors[ $class ])) {
            $this->reflectors[ $class ] = new \ReflectionClass($class);
        }

        return $this->reflectors[ $class ];
    }
1153892
public function createInstance(string $class)
    {
        $refClass = new \ReflectionClass($class);
        $args = [];
        if ($refClass->getConstructor()) {
            foreach ($refClass->getConstructor()->getParameters() as $parameter) {
                $name = Inflector::tableize(str_replace('_', '.', $parameter->getName()));
                $dependency = null;
                if ($parameter->getClass()) {
                    if ($this->container->has($parameter->getClass()->getName())) {
                        $dependency = $this->container->get($parameter->getClass()->getName());
                    } elseif ($this->container->has($name)) {
                        $dependency = $this->container->get($name);
                    }
                } elseif ($this->container->hasParameter($name)) {
                    $dependency = $this->container->getParameter($name);
                }
                $args[] = $dependency;
            }
        }

        return $refClass->newInstanceArgs($args);
    }
11661
private function make(string $class)
    {
        if (! array_key_exists($class, $this->instances)) {

            try {

                return $this->instances[$class] = ($this->factory)($class)->value($this);

            }

            catch (ResolvingExceptionInterface $e) {

                throw new ReflectionContainerException($class, $e);

            }

        }

        return $this->instances[$class];
    }
480229
protected function define(ClassDefinition $class)
    {
        $class->property($this->name)->asString();

        $class->property($this->file)->asObject(File::class);
    }
1118012
static public function from($class)
        {
            if (is_object($class)) {
                $class = get_class($class);
            }

            if (empty(self::$prototypes[$class])) {
                self::$prototypes[$class] = new static($class);
            }

            return self::$prototypes[$class];
        }
147595
protected function instance($class)
    {
        $reflection = new \ReflectionClass($class);

        $arguments = array();

        $constructor = $reflection->getConstructor();

        if ($this->container->has($class))
        {
            return $this->container->get($class);
        }

        if ($constructor !== null)
        {
            $arguments = $this->arguments($constructor);
        }

        return $reflection->newInstanceArgs($arguments);
    }
1352187
public static function fromReflection($class, $method = '__construct')
  {
    // $serviceDefinition = new static($class);
    $serviceDefinitionParameters = array();

    /* @var $reflection \ReflectionClass */
    $reflection = new \ReflectionClass($class);
    if (!$reflection->isInstantiable())
    {
      throw new \InvalidArgumentException("Class $class is not instantiable");
    }

    try {
      $constructor = $reflection->getMethod($method);

      if ($method != '__construct' && !$constructor->isStatic())
      {
        throw new \InvalidArgumentException("$class::$method is not static");
      }

      foreach ($constructor->getParameters() as $param)
      {
        /* @var $param \ReflectionParameter */

        $parameterDefinition = new ArrayParameterDefinition($param->getName());
        if ($param->isDefaultValueAvailable())
        {
          $parameterDefinition->setDefaultValue($param->getDefaultValue());
        }

        $serviceDefinitionParameters[$param->getName()] = $parameterDefinition;
      }
    }
    catch (\ReflectionException $e)
    {
      if ($method !== '__construct') // not ok
      {
        throw $e;
      }
      // ok
      $serviceDefinitionParameters = array();
    }

    return new static($class, $serviceDefinitionParameters, $method);
  }
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);
        }
    }
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);
    }
1029599
protected function defineEntity(ClassDefinition $class)
    {
        $class->property($this->article)->asObject(BlogArticle::class);

        $class->property($this->authorName)->asString();

        $class->property($this->authorEmail)->asObject(EmailAddress::class);

        $class->property($this->content)->asString();

        $class->property($this->postedAt)->asObject(DateTime::class);

        $this->defineMetadata($class);
    }
98969
protected function define(ClassDefinition $class)
    {
        $class->property($this->address)->asString();
        $class->property($this->latLng)->asObject(LatLng::class);
    }
560992
protected function defineEntity(ClassDefinition $class)
    {
        $class->property($this->name)->asString();

        $class->property($this->slug)->asString();

        $class->property($this->role)->asString();

        $class->property($this->bio)->asObject(Html::class);

        $class->property($this->articles)->asType(BlogArticle::collectionType());

        $this->defineMetadata($class);
    }
80880
private static function methodsOf(\ReflectionClass $class): \Iterator
    {
        return new \CallbackFilterIterator(
                new \ArrayIterator($class->getMethods()),
                function(\ReflectionMethod $method)
                {
                    return !$method->isPrivate()
                            && !$method->isFinal()
                            && !$method->isStatic()
                            && !$method->isConstructor()
                            && !$method->isDestructor();
                }
        );
    }
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;
    }