public static fromType ( |
||
$type | The base type of this generic type referencing a generic class | |
$template_parameter_type_list | UnionType[] | A map from a template type identifier to a concrete union type |
Résultat |
/** * @param Type|null $parent_type * The type of the parent (extended) class of this class. * * @return void */ public function setParentType(Type $parent_type = null) { if ($this->getInternalScope()->hasAnyTemplateType()) { // Get a reference to the local list of templated // types. We'll use this to map templated types on the // parent to locally templated types. $template_type_map = $this->getInternalScope()->getTemplateTypeMap(); // Figure out if the given parent type contains any template // types. $contains_templated_type = false; foreach ($parent_type->getTemplateParameterTypeList() as $i => $union_type) { foreach ($union_type->getTypeSet() as $type) { if (isset($template_type_map[$type->getName()])) { $contains_templated_type = true; break 2; } } } // If necessary, map the template parameter type list through the // local list of templated types. if ($contains_templated_type) { $parent_type = Type::fromType($parent_type, array_map(function (UnionType $union_type) use($template_type_map) : UnionType { return new UnionType(array_map(function (Type $type) use($template_type_map) : Type { return $template_type_map[$type->getName()] ?? $type; }, $union_type->getTypeSet()->toArray())); }, $parent_type->getTemplateParameterTypeList())); } } $this->parent_type = $parent_type; // Add the parent to the union type of this // class $this->getUnionType()->addUnionType($parent_type->asUnionType()); }
/** * Visit a node with kind `\ast\AST_NEW` * * @param Node $node * A node of the type indicated by the method name that we'd * like to figure out the type that it produces. * * @return UnionType * The set of types that are possibly produced by the * given node */ public function visitNew(Node $node) : UnionType { $union_type = $this->visitClassNode($node->children['class']); // For any types that are templates, map them to concrete // types based on the parameters passed in. return new UnionType(array_map(function (Type $type) use($node) { // Get a fully qualified name for the type $fqsen = $type->asFQSEN(); // If this isn't a class, its fine as is if (!$fqsen instanceof FullyQualifiedClassName) { return $type; } // If we don't have the class, we'll catch that problem // elsewhere if (!$this->code_base->hasClassWithFQSEN($fqsen)) { return $type; } $class = $this->code_base->getClassByFQSEN($fqsen); // If this class doesn't have any generics on it, we're // fine as we are with this Type if (!$class->isGeneric()) { return $type; } // Now things are interesting. We need to map the // arguments to the generic types and return a special // kind of type. // Get the constructor so that we can figure out what // template types we're going to be mapping $constructor_method = $class->getMethodByName($this->code_base, '__construct'); // Map each argument to its type $arg_type_list = array_map(function ($arg_node) { return UnionType::fromNode($this->context, $this->code_base, $arg_node); }, $node->children['args']->children ?? []); // Map each template type o the argument's concrete type $template_type_list = []; foreach ($constructor_method->getParameterList() as $i => $parameter) { if (isset($arg_type_list[$i])) { $template_type_list[] = $arg_type_list[$i]; } } // Create a new type that assigns concrete // types to template type identifiers. return Type::fromType($type, $template_type_list); }, $union_type->getTypeSet()->toArray())); }