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); } } }