private function ensurePropertyDefined($left, $resultType)
 {
     if ($resultType->isUnknownType()) {
         return;
     }
     $property = $this->typeRegistry->getFetchedPropertyByNode($left);
     if (null !== $property) {
         assert($property instanceof ClassProperty);
         // Specifically ignore anything that is being set in a tearDown() method.
         // TODO: We should think about introducing a general concept for this which takes
         //       inter procedural control flow into account.
         $scopeRoot = $this->syntacticScope->getRootNode();
         if (!$scopeRoot instanceof BlockNode && !$scopeRoot instanceof \PHPParser_Node_Expr_Closure) {
             $testCase = $this->typeRegistry->getClassOrCreate('PHPUnit_Framework_TestCase');
             $method = $this->typeRegistry->getFunctionByNode($scopeRoot);
             if ($property->getDeclaringClassType()->isSubtypeOf($testCase) && null !== ($thisType = $this->syntacticScope->getTypeOfThis()) && $thisType->isSubtypeOf($testCase) && null !== $method && strtolower($method->getName()) === 'teardown') {
                 return;
             }
         }
         if (null !== ($type = $property->getPhpType())) {
             $newType = $this->typeRegistry->createUnionType(array($type, $resultType));
         } else {
             $newType = $resultType;
         }
         $property->setPhpType($newType);
         if ($astNode = $property->getAstNode()) {
             $astNode->setAttribute('type', $newType);
         }
     }
 }
 private function getThisType(\PHPParser_Node $node, Scope $parentScope = null)
 {
     $parent = $node;
     while (null !== $parent) {
         // As of PHP 5.4, closures inherit the this type of their parent scope. Since there is currently no way to
         // configure the PHP version that we build against, we will simply always infer the ThisType. Other passes,
         // can then perform checks whether ``$this`` may be accessed, allowing us to produce better error messages.
         if ($parent instanceof \PHPParser_Node_Expr_Closure) {
             if (null === $parentScope) {
                 return null;
             }
             return $parentScope->getTypeOfThis();
         }
         if (NodeUtil::isMethodContainer($parent)) {
             $name = implode("\\", $parent->namespacedName->parts);
             return $this->typeRegistry->getClassOrCreate($name);
         }
         $parent = $parent->getAttribute('parent');
     }
     return null;
 }
 private function attachLiteralTypes(\PHPParser_Node $node, \PHPParser_Node $parent = null)
 {
     switch (true) {
         case $node instanceof \PHPParser_Node_Name_FullyQualified:
             $node->setAttribute('type', $this->typeRegistry->getClassOrCreate(implode("\\", $node->parts)));
             break;
         case $node instanceof \PHPParser_Node_Name:
             if ($parent instanceof \PHPParser_Node_Expr_New || $parent instanceof \PHPParser_Node_Expr_StaticPropertyFetch || $parent instanceof \PHPParser_Node_Expr_StaticCall || $parent instanceof \PHPParser_Node_Expr_Instanceof || $parent instanceof \PHPParser_Node_Stmt_Catch) {
                 $name = implode("\\", $node->parts);
                 $lowerName = strtolower($name);
                 if ('static' === $name) {
                     $node->setAttribute('type', $this->typeRegistry->getThisType($this->scope->getTypeOfThis()));
                 } else {
                     if ('self' === $name) {
                         $node->setAttribute('type', $this->scope->getTypeOfThis());
                     } else {
                         if ('parent' === $name) {
                             $thisType = $this->scope->getTypeOfThis()->toMaybeObjectType();
                             if (null === $thisType || !$thisType->isClass() || null === $thisType->getSuperClassType()) {
                                 $node->setAttribute('type', $this->typeRegistry->getNativeType('unknown'));
                             } else {
                                 $node->setAttribute('type', $thisType->getSuperClassType());
                             }
                         } else {
                             $node->setAttribute('type', $this->typeRegistry->getClassOrCreate($name));
                         }
                     }
                 }
             }
             break;
         case $node instanceof \PHPParser_Node_Expr_Array:
         case $node instanceof \PHPParser_Node_Expr_Cast_Array:
             // We only do attach the generic array type on the first build.
             // For subsequent builds, other passes likely have already made
             // the array type more specific.
             if (null === $node->getAttribute('type')) {
                 $node->setAttribute('type', $this->typeRegistry->getNativeType('array'));
             }
             break;
         case $node instanceof \PHPParser_Node_Expr_UnaryMinus:
         case $node instanceof \PHPParser_Node_Expr_UnaryPlus:
         case $node instanceof \PHPParser_Node_Scalar_LNumber:
         case $node instanceof \PHPParser_Node_Scalar_LineConst:
             $node->setAttribute('type', $this->typeRegistry->getNativeType('integer'));
             break;
         case $node instanceof \PHPParser_Node_Scalar_DNumber:
             $node->setAttribute('type', $this->typeRegistry->getNativeType('double'));
             break;
         case $node instanceof \PHPParser_Node_Scalar_String:
         case $node instanceof \PHPParser_Node_Scalar_FileConst:
         case $node instanceof \PHPParser_Node_Scalar_DirConst:
             $node->setAttribute('type', $this->typeRegistry->getNativeType('string'));
             break;
         case $node instanceof \PHPParser_Node_Expr_ClassConstFetch:
             if ($node->class instanceof \PHPParser_Node_Name && in_array($node->class->parts[0], array('self', 'static')) && null !== ($thisType = $this->scope->getTypeOfThis()) && null !== ($objType = $thisType->toMaybeObjectType()) && ($objType->isClass() || $objType->isInterface()) && $objType->hasConstant($node->name)) {
                 $node->setAttribute('type', $objType->getConstant($node->name)->getPhpType());
             }
             break;
         case $node instanceof \PHPParser_Node_Expr_ConstFetch:
             $nameParts = $node->name->parts;
             if (1 === count($nameParts)) {
                 $name = strtolower($nameParts[0]);
                 if ('true' === $name) {
                     $node->setAttribute('type', $this->typeRegistry->getNativeType('boolean'));
                 } else {
                     if ('false' === $name) {
                         $node->setAttribute('type', $this->typeRegistry->getNativeType('false'));
                     } else {
                         if ('null' === $name) {
                             $node->setAttribute('type', $this->typeRegistry->getNativeType('null'));
                         }
                     }
                 }
             }
             break;
     }
 }