public function testFullyQualifiedClassConstantName() { $this->assertFQSENEqual(FullyQualifiedClassConstantName::make(FullyQualifiedClassName::make('\\Name\\Space', 'a'), 'c'), '\\Name\\Space\\a::c'); $this->assertFQSENEqual(FullyQualifiedClassConstantName::fromFullyQualifiedString('\\Name\\a::c'), '\\Name\\a::c'); $this->assertFQSENEqual(FullyQualifiedClassConstantName::fromFullyQualifiedString('Name\\a::c'), '\\Name\\a::c'); $this->assertFQSENEqual(FullyQualifiedClassConstantName::fromFullyQualifiedString('\\Name\\Space\\a::c,2'), '\\Name\\Space\\a::c,2'); $this->assertFQSENEqual(FullyQualifiedClassConstantName::fromFullyQualifiedString('\\Name\\Space\\a,1::c,2'), '\\Name\\Space\\a,1::c,2'); $this->assertFQSENEqual(FullyQualifiedClassConstantName::fromStringInContext('a::methodName', $this->context), '\\a::methodName'); }
public static function createSchema() : Schema { $schema = new Schema('File', [new Column('file_path', Column::TYPE_STRING, true), new Column('modification_time', Column::TYPE_INT)]); $schema->addAssociation(new ListAssociation('FileClassFQSEN', Column::TYPE_STRING, function (File $file, array $class_fqsen_string_list) { $file->getFile()->setClassFQSENList(array_map(function (string $fqsen_string) { return FullyQualifiedClassName::fromFullyQualifiedString($fqsen_string); }, $class_fqsen_string_list)); }, function (File $file) { return array_map(function (FullyQualifiedClassName $fqsen) { return (string) $fqsen; }, $file->getFile()->getClassFQSENList()); })); $schema->addAssociation(new ListAssociation('FileMethodFQSEN', Column::TYPE_STRING, function (File $file, array $method_fqsen_string_list) { $file->getFile()->setMethodFQSENList(array_map(function (string $fqsen_string) { if (false !== strpos($fqsen_string, '::')) { return FullyQualifiedMethodName::fromFullyQualifiedString($fqsen_string); } else { return FullyQualifiedFunctionName::fromFullyQualifiedString($fqsen_string); } }, $method_fqsen_string_list)); }, function (File $file) { return array_map(function (FQSEN $fqsen) { return (string) $fqsen; }, $file->getFile()->getMethodFQSENList()); })); $schema->addAssociation(new ListAssociation('FilePropertyFQSEN', Column::TYPE_STRING, function (File $file, array $fqsen_string_list) { $file->getFile()->setPropertyFQSENList(array_map(function (string $fqsen_string) { if (false !== strpos($fqsen_string, '::')) { return FullyQualifiedPropertyName::fromFullyQualifiedString($fqsen_string); } else { return FullyQualifiedFunctionName::fromFullyQualifiedString($fqsen_string); } }, $fqsen_string_list)); }, function (File $file) { return array_map(function (FQSEN $fqsen) { return (string) $fqsen; }, $file->getFile()->getPropertyFQSENList()); })); $schema->addAssociation(new ListAssociation('FileConstantFQSEN', Column::TYPE_STRING, function (File $file, array $fqsen_string_list) { $file->getFile()->setConstantFQSENList(array_map(function (string $fqsen_string) { if (false !== strpos($fqsen_string, '::')) { return FullyQualifiedClassConstantName::fromFullyQualifiedString($fqsen_string); } else { return FullyQualifiedGlobalConstantName::fromFullyQualifiedString($fqsen_string); } }, $fqsen_string_list)); }, function (File $file) { return array_map(function (FQSEN $fqsen) { return (string) $fqsen; }, $file->getFile()->getConstantFQSENList()); })); return $schema; }
/** * Visit a node with kind `\ast\AST_CLASS_CONST_DECL` * * @param Node $node * A node to parse * * @return Context * A new or an unchanged context resulting from * parsing the node */ public function visitClassConstDecl(Node $node) : Context { $clazz = $this->getContextClass(); foreach ($node->children ?? [] as $child_node) { $name = $child_node->children['name']; $fqsen = FullyQualifiedClassConstantName::fromStringInContext($name, $this->context); $constant = new ClassConstant($this->context->withLineNumberStart($child_node->lineno ?? 0)->withLineNumberEnd($child_node->endLineno ?? 0), $name, new UnionType(), $child_node->flags ?? 0); $constant->setFQSEN($fqsen); $constant->setFutureUnionType(new FutureUnionType($this->code_base, $this->context, $child_node->children['value'])); $clazz->addConstant($this->code_base, $constant); } return $this->context; }
/** * @return FullyQualifiedConstantName * A fully-qualified constant name */ public function withConstantName(string $constant_name) : FullyQualifiedClassConstantName { return FullyQualifiedClassConstantName::make($this, $constant_name); }
/** * This method must be called before analysis * begins. * * @return void */ protected function hydrateOnce(CodeBase $code_base) { foreach ($this->getAncestorFQSENList($code_base) as $fqsen) { if ($code_base->hasClassWithFQSEN($fqsen)) { $code_base->getClassByFQSEN($fqsen)->hydrate($code_base); } } // Create the 'class' constant $this->addConstant($code_base, new ClassConstant($this->getContext(), 'class', StringType::instance()->asUnionType(), 0, FullyQualifiedClassConstantName::make($this->getFQSEN(), 'class'))); // Add variable '$this' to the scope $this->getInternalScope()->addVariable(new Variable($this->getContext(), 'this', $this->getUnionType(), 0)); // Load parent methods, properties, constants $this->importAncestorClasses($code_base); }
/** * @param CodeBase $code_base * A reference to the entire code base in which this * context exists * * @param ReflectionClass $class * A reflection class representing a builtin class. * * @return Clazz * A Class structural element representing the given named * builtin. */ public static function fromReflectionClass(CodeBase $code_base, \ReflectionClass $class) : Clazz { // Build a set of flags based on the constitution // of the built-in class $flags = 0; if ($class->isFinal()) { $flags = \ast\flags\CLASS_FINAL; } elseif ($class->isInterface()) { $flags = \ast\flags\CLASS_INTERFACE; } elseif ($class->isTrait()) { $flags = \ast\flags\CLASS_TRAIT; } if ($class->isAbstract()) { $flags |= \ast\flags\CLASS_ABSTRACT; } $context = new Context(); // Build a base class element $clazz = new Clazz($context, $class->getName(), UnionType::fromStringInContext($class->getName(), $context), $flags); $clazz->setFQSEN(FullyQualifiedClassName::fromStringInContext($class->getName(), $context)); // If this class has a parent class, add it to the // class info if ($parent_class = $class->getParentClass()) { $parent_class_fqsen = FullyQualifiedClassName::fromFullyQualifiedString('\\' . $parent_class->getName()); $clazz->setParentClassFQSEN($parent_class_fqsen); } foreach ($class->getDefaultProperties() as $name => $value) { // TODO: whats going on here? $reflection_property = new \ReflectionProperty($class->getName(), $name); $property_context = $context->withClassFQSEN($clazz->getFQSEN()); $property = new Property($property_context, $name, Type::fromObject($value)->asUnionType(), 0); $property->setFQSEN(FullyQualifiedPropertyName::make($clazz->getFQSEN(), $name)); $clazz->addProperty($code_base, $property); } foreach ($class->getInterfaceNames() as $name) { $clazz->addInterfaceClassFQSEN(FullyQualifiedClassName::fromFullyQualifiedString('\\' . $name)); } foreach ($class->getTraitNames() as $name) { $clazz->addTraitFQSEN(FullyQualifiedClassName::fromFullyQualifiedString('\\' . $name)); } foreach ($class->getConstants() as $name => $value) { $constant = new ClassConstant($context, $name, Type::fromObject($value)->asUnionType(), 0); $constant->setFQSEN(FullyQualifiedClassConstantName::make($clazz->getFQSEN(), $name)); $clazz->addConstant($code_base, $constant); } foreach ($class->getMethods() as $reflection_method) { $method_list = FunctionFactory::methodListFromReflectionClassAndMethod($context->withClassFQSEN($clazz->getFQSEN()), $code_base, $class, $reflection_method); foreach ($method_list as $method) { $clazz->addMethod($code_base, $method); } } return $clazz; }
/** * @param array * A map from column name to value * * @return Constant * An instance of the model derived from row data */ public static function fromRow(array $row) : Constant { list($scope, $name) = explode('|', $row['scope_name']); $constant = new Constant(new ConstantElement(unserialize(base64_decode($row['context'])), $row['name'], UnionType::fromFullyQualifiedString($row['type']), (int) $row['flags']), $scope, $name); if (false !== strpos($row['fqsen'], '::')) { $fqsen = FullyQualifiedClassConstantName::fromFullyQualifiedString($row['fqsen']); } else { $fqsen = FullyQualifiedGlobalConstantName::fromFullyQualifiedString($row['fqsen']); } $constant->getConstant()->setFQSEN($fqsen); return $constant; }
/** * @return ClassConstant * The class constant with the given name. */ public function getConstantWithName(CodeBase $code_base, string $name) : ClassConstant { return $code_base->getClassConstantByFQSEN(FullyQualifiedClassConstantName::make($this->getFQSEN(), $name)); }
/** * This method must be called before analysis * begins. * * @return void */ protected function hydrateOnce(CodeBase $code_base) { $constant_fqsen = FullyQualifiedClassConstantName::make($this->getFQSEN(), 'class'); // Create the 'class' constant $constant = new ClassConstant($this->getContext(), 'class', StringType::instance()->asUnionType(), 0, $constant_fqsen); $this->addConstant($code_base, $constant); // Add variable '$this' to the scope $this->getInternalScope()->addVariable(new Variable($this->getContext(), 'this', $this->getUnionType(), 0)); // Load parent methods, properties, constants $this->importAncestorClasses($code_base); }