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;
 }
Пример #2
0
 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');
 }