public function getEqualsTests() { $registry = new TypeRegistry(); $tests = array(); $tests[] = array($registry->createUnionType(array('integer', 'string')), $registry->createUnionType(array('string', 'integer')), true); $tests[] = array($registry->createUnionType(array('number', 'string')), $registry->createUnionType(array('string', 'number')), true); return $tests; }
private function getStringRepr(PhpType $type) { switch (true) { case $type instanceof AllType: return TypeRegistry::NATIVE_ALL; // This handles the generic array type specially. // This handles the generic array type specially. case $type === self::$typeRegistry->getNativeType('array'): return 'array'; case $type instanceof ArrayType: $itemTypes = $type->getItemTypes(); if (empty($itemTypes)) { return TypeRegistry::NATIVE_ARRAY . '<' . $this->getStringRepr($type->getKeyType()) . ',' . $this->getStringRepr($type->getElementType()) . '>'; } return sprintf('array<%s,%s,%s>', $this->getStringRepr($type->getKeyType()), $this->getStringRepr($type->getElementType()), $this->dumpJsonLike($itemTypes, true)); case $type instanceof FalseType: return TypeRegistry::NATIVE_BOOLEAN_FALSE; case $type instanceof BooleanType: return TypeRegistry::NATIVE_BOOLEAN; case $type instanceof CallableType: return TypeRegistry::NATIVE_CALLABLE; case $type instanceof ResourceType: return TypeRegistry::NATIVE_RESOURCE; case $type instanceof DoubleType: return TypeRegistry::NATIVE_DOUBLE; case $type instanceof IntegerType: return TypeRegistry::NATIVE_INTEGER; case $type instanceof ThisType: return 'this<' . $type->getReferenceName() . '>'; case $type instanceof NamedType: // If this type has been resolved, we can get the representation // of the resolved type instead of using the reference name. if (!$type->isNoResolvedType()) { return $this->getStringRepr($type->getReferencedType()); } return 'object<' . $type->getReferenceName() . '>'; case $type instanceof NoObjectType: return TypeRegistry::NATIVE_OBJECT; case $type instanceof NoType: return TypeRegistry::NATIVE_NONE; case $type instanceof NullType: return TypeRegistry::NATIVE_NULL; case $type instanceof ObjectType: return 'object<' . $type->getName() . '>'; case $type instanceof StringType: return TypeRegistry::NATIVE_STRING; case $type instanceof UnionType: $alt = array(); foreach ($type->getAlternates() as $t) { $alt[] = $this->getStringRepr($t); } return implode('|', $alt); case $type instanceof UnknownType: return $type->isChecked() ? TypeRegistry::NATIVE_UNKNOWN_CHECKED : TypeRegistry::NATIVE_UNKNOWN; } throw new \InvalidArgumentException(sprintf('The SWITCH statement is exhaustive, but got "%s".', get_class($type))); }
private function assertTypeEquals($expectedType, PhpType $restrictedType = null) { if (null === $expectedType) { $this->assertNull($restrictedType); } else { $resolvedExpectedType = $this->registry->resolveType($expectedType); $this->assertNotNull($restrictedType); $this->assertTrue($resolvedExpectedType->equals($restrictedType), sprintf('Failed to assert that expected type "%s" equals the actual type "%s".', $resolvedExpectedType, $restrictedType)); } }
private function setUpClass($class, array $extends) { $class = new Clazz($class); if (isset($extends[$class->getName()])) { $parentClass = $this->setUpClass($extends[$class->getName()], $extends); $class->setSuperClasses(array_merge(array($parentClass->getName()), $parentClass->getSuperClasses())); $class->setSuperClass($parentClass->getName()); } $class->setNormalized(true); $this->registry->registerClass($class); return $class; }
public function testLoadConstant() { $this->versionA->addConstant($fooA = new GlobalConstant('FOO')); $fooA->setPhpType($this->typeRegistry->getNativeType('string')); $this->versionB->addConstant($fooB = new GlobalConstant('FOO')); $fooB->setPhpType($this->typeRegistry->getNativeType('string')); $this->em->persist($this->package); $this->em->flush(); $loadedConst = $this->provider->loadConstant('FOO'); $this->assertSame($fooA, $loadedConst, 'loadConstant() takes the first constant if no package versions are set.'); $loadedConst = $this->provider->loadConstant('foo'); $this->assertNull($loadedConst, 'loadConstant() treats the name **not** as case-insensitive.'); $this->provider->setPackageVersions(array($this->versionB)); $loadedConst = $this->provider->loadConstant('FOO'); $this->assertSame($fooB, $loadedConst, 'loadConstant() takes the constant from one of the set packages.'); $this->provider->setPackageVersions(array($this->versionC)); $this->assertNull($this->provider->loadConstant('FOO'), 'loadConstant() returns null if constant is not found in set packages.'); $this->assertNull($this->provider->loadConstant('BAR'), 'loadConstant() returns null if constant does not exist.'); }
private function getPropertyType(PhpType $objType = null, $propName, \PHPParser_Node $n, LinkedFlowScope $scope) { // Check whether the scope contains inferred type information about the property, // or fallback to the wider property type if not available. Scopes could // contain information about properties if we have reverse interpreted // the property previously. $qualifiedName = self::getQualifiedName($n); $var = $scope->getSlot($qualifiedName); if (null !== $var && null !== ($varType = $var->getType())) { if ($varType->equals($this->typeRegistry->getNativeType('unknown')) && $var !== $this->syntacticScope->getSlot($qualifiedName)) { // If the type of this qualified name has been checked in this scope, // then use CHECKED_UNKNOWN_TYPE instead to indicate that. // TODO: The checked unknown type has not really proved useful in // practice. Consider removing it entirely. return $this->typeRegistry->getNativeType('unknown_checked'); } return $varType; } $propertyType = null; if (null !== $objType && null !== ($objType = $objType->toMaybeObjectType()) && $objType instanceof Clazz && $objType->hasProperty($propName)) { $propertyType = $objType->getProperty($propName)->getPhpType(); } return $propertyType ?: $this->typeRegistry->getNativeType('unknown'); }
public static function getNativeTypeForGettypeResultHelper(TypeRegistry $registry, $resultName) { switch ($resultName) { case 'integer': case 'double': case 'array': case 'object': case 'boolean': case 'string': return $registry->getNativeType($resultName); case 'NULL': return $registry->getNativeType('null'); default: return null; } }
private function parseTypeName() { $type = null; if ('\\' === $this->token[0][0]) { $type = $this->typeRegistry->getClassOrCreate(substr($this->token[0], 1)); } else { // First, we check whether the name is a class that we have already scanned $parts = explode("\\", $this->token[0]); if (isset($this->importedNamespaces[$parts[0]])) { $className = $this->importedNamespaces[$parts[0]]; if (count($parts) > 1) { $className .= '\\' . implode("\\", array_slice($parts, 1)); } $type = $this->typeRegistry->getClassOrCreate($className); } else { switch (strtolower($this->token[0])) { case '(': $type = $this->parseGroup(); break; case 'false': $type = $this->typeRegistry->getNativeType('false'); break; case 'bool': case 'boolean': $type = $this->typeRegistry->getNativeType('boolean'); break; case 'int': case 'integer': $type = $this->typeRegistry->getNativeType('integer'); break; case 'float': case 'double': $type = $this->typeRegistry->getNativeType('double'); break; case 'scalar': $type = $this->typeRegistry->getNativeType('scalar'); break; case 'string': $type = $this->typeRegistry->getNativeType('string'); break; case 'array': if ($this->isNextToken('<')) { $this->match('<'); $this->moveNext(); $firstType = $this->parse(); if ($this->isNextToken(',')) { $this->match(','); $this->moveNext(); $arrayType = $this->typeRegistry->getArrayType($this->parse(), $firstType); $this->match('>'); return $arrayType; } $this->match('>'); return $this->typeRegistry->getArrayType($firstType, $this->typeRegistry->getNativeType('integer')); } $type = $this->typeRegistry->getNativeType('array'); break; case 'resource': $type = $this->typeRegistry->getNativeType('resource'); break; case '*': case 'mixed': $type = $this->typeRegistry->getNativeType('all'); break; case 'number': $type = $this->typeRegistry->getNativeType('number'); break; case 'object': $type = $this->typeRegistry->getNativeType('object'); break; case 'void': case 'null': $type = $this->typeRegistry->getNativeType('null'); break; case 'callable': case 'callback': $type = $this->typeRegistry->getNativeType('callable'); break; default: if ($this->isThisReference($this->token[0])) { if (null === $this->currentClassName) { throw new \RuntimeException(sprintf('"%s" is only available from within classes.', $this->token[0])); } $type = $this->typeRegistry->getClassOrCreate($this->currentClassName); } else { if (preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*(?:\\\\[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)*$/', $this->token[0])) { $className = !empty($this->importedNamespaces['']) ? $this->importedNamespaces[''] . '\\' : ''; $className .= $this->token[0]; $type = $this->typeRegistry->getClassOrCreate($className); } else { throw new \RuntimeException(sprintf('Unknown type name "%s" at position %d.', $this->token[0], $this->token[1])); } } } } } if (!$type) { throw new \RuntimeException(sprintf('Internal error for token "%s" at position %d.', $this->token[0], $this->token[1])); } if ($this->isNextToken('[')) { $this->moveNext(); // In the php stubs, there often is an [optional] appended to types. // We just ignore this suffix. if ($this->isNextToken('optional')) { $this->moveNext(); $this->match(']'); } else { $this->match(']'); return $this->typeRegistry->getArrayType($type, $this->typeRegistry->getNativeType('integer')); } } return $type; }
public function visitNoType() { return $this->registry->getNativeType('none'); }