public function testCachedCallSitesAreRemoved()
 {
     $cachedFooFunc = new GlobalFunction('foo');
     $cachedBarFunc = new GlobalFunction('bar');
     $cachedBarClass = new Clazz('Bar');
     $cachedBarClass->addMethod($cachedBarMethod = new Method('bar'));
     $cachedFooClass = new Clazz('Foo');
     $cachedFooClass->addMethod($cachedFooMethod = new Method('foo'));
     CallSite::create($cachedFooFunc, $cachedBarFunc);
     CallSite::create($cachedFooMethod, $cachedBarFunc);
     CallSite::create($cachedFooMethod, $cachedBarMethod);
     CallSite::create($cachedBarFunc, $cachedFooFunc);
     CallSite::create($cachedBarMethod, $cachedFooFunc);
     $this->provider->addFunction($cachedFooFunc);
     $this->provider->addFunction($cachedBarFunc);
     $this->provider->addClass($cachedBarClass);
     $this->provider->addClass($cachedFooClass);
     $this->analyzeAst('CallGraph/cache.php');
     $fooFunc = $this->registry->getFunction('foo');
     $fooMethod = $this->registry->getClass('Foo')->getMethod('foo')->getMethod();
     $this->assertInCallSites($fooFunc, array($cachedBarMethod), array($cachedBarFunc));
     $this->assertOutCallSites($fooFunc, array(), array());
     $this->assertInCallSites($fooMethod, array(), array());
     $this->assertOutCallSites($fooMethod, array($cachedBarMethod), array($cachedBarFunc));
     $this->assertInCallSites($cachedBarMethod, array($fooMethod), array());
     $this->assertOutCallSites($cachedBarMethod, array(), array($fooFunc));
     $this->assertInCallSites($cachedBarFunc, array($fooMethod), array());
     $this->assertOutCallSites($cachedBarFunc, array(), array($fooFunc));
     $this->assertInCallSites($cachedFooFunc, array($cachedBarMethod), array($cachedBarFunc));
     $this->assertOutCallSites($cachedFooFunc, array(), array($cachedBarFunc));
     $this->assertInCallSites($cachedFooMethod, array(), array());
     $this->assertOutCallSites($cachedFooMethod, array($cachedBarMethod), array($cachedBarFunc));
 }
 public function getIsSubtypeTests()
 {
     $tests = array();
     try {
         $registry = new TypeRegistry();
         $foo = new Clazz('Foo');
         $foo->setSuperClass('Bar');
         $foo->setSuperClasses(array('Bar'));
         $foo->setImplementedInterfaces(array('Baz', 'FooBar'));
         $foo->setNormalized(true);
         $tests[] = array($foo, new InterfaceC('FooBar'), true);
         $tests[] = array($foo, new InterfaceC('Foo'), false);
         $tests[] = array($foo, $foo, true);
         $tests[] = array($foo, new Clazz('Bar'), true);
         $tests[] = array($foo, new Clazz('FooBar'), false);
         $tests[] = array($foo, NamedType::createResolved($registry, new InterfaceC('Baz')), true);
         $tests[] = array($foo, NamedType::createResolved($registry, new InterfaceC('Moo')), false);
         $tests[] = array($foo, NamedType::createResolved($registry, new Clazz('Foo')), true);
         $tests[] = array($foo, NamedType::createResolved($registry, new Clazz('FoooFooo')), false);
         $tests[] = array($foo, new UnknownType($registry, false), true);
         $tests[] = array($foo, new NoObjectType($registry), true);
         $tests[] = array($foo, new BooleanType($registry), false);
         $tests[] = array($foo, new IntegerType($registry), false);
         $tests[] = array($foo, new DoubleType($registry), false);
         $tests[] = array($foo, new StringType($registry), false);
         $tests[] = array($foo, $registry->createUnionType(array('string', new InterfaceC('Baz'))), true);
         $tests[] = array($foo, $registry->createUnionType(array('string', 'boolean')), false);
     } catch (\Exception $ex) {
         echo sprintf("Could not get tests for isSubtypeTests(): %s\n", $ex->getMessage() . ' on line ' . $ex->getLine() . ' in file ' . $ex->getFile());
     }
     return $tests;
 }
 public function __construct(Clazz $class, Property $property, $declaringClass = null)
 {
     $this->class = $class;
     $this->property = $property;
     $this->name = $property->getName();
     if ($class->getName() === $declaringClass) {
         $declaringClass = null;
     }
     $this->declaringClass = $declaringClass;
 }
 public function testObjectTypes()
 {
     $class = new \Scrutinizer\PhpAnalyzer\Model\Clazz('Foo');
     $class->setNormalized(true);
     $this->registry->registerClass($class);
     $this->assertUnion('object<Foo>', new NamedType($this->registry, 'Foo'), $class);
     $named = new NamedType($this->registry, 'Foo');
     $named->setReferencedType($class);
     $this->assertUnion('object<Foo>', $named, $class);
 }
 public function __construct(Clazz $class, Method $method, $declaringClass = null)
 {
     $this->class = $class;
     $this->method = $method;
     $this->name = strtolower($method->getName());
     if ($class->getName() === $declaringClass) {
         $declaringClass = null;
     }
     $this->declaringClass = $declaringClass;
 }
 public function __construct(Clazz $class, Constant $constant, $declaringClass = null)
 {
     $this->class = $class;
     $this->constant = $constant;
     $this->name = $constant->getName();
     if ($class->getName() === $declaringClass) {
         $declaringClass = null;
     }
     $this->declaringClass = $declaringClass;
 }
 public function testDocTypesOfMethods()
 {
     $this->packageVersion->addContainer($foo = new Clazz('Foo'));
     $foo->addMethod($method = new Method('foo'));
     $method->setReturnDocType('self');
     $method->setParamDocType(0, 'string');
     $this->persister->persist($this->packageVersion);
     $reloadedFoo = $this->em->createQuery('SELECT c FROM Scrutinizer\\PhpAnalyzer\\Model\\Clazz c WHERE c.name = :name')->setParameter('name', 'Foo')->getSingleResult();
     $reloadedMethod = $reloadedFoo->getMethod('foo');
     $this->assertEquals(array('param_0' => 'string', 'return' => 'self'), $reloadedMethod->getDocTypes());
 }
 public function testNullableThisType()
 {
     $class = new Clazz('Foo');
     $class->setNormalized(true);
     $this->registry->registerClass($class);
     $builder = new UnionTypeBuilder($this->registry);
     $this->assertCount(0, $builder->getAlternates());
     $builder->addAlternate($this->registry->getNativeType('null'));
     $this->assertCount(1, $builder->getAlternates());
     $builder->addAlternate(new ThisType($this->registry, $class));
     $this->assertCount(2, $builder->getAlternates());
     $type = $builder->build();
     $this->assertInstanceOf('Scrutinizer\\PhpAnalyzer\\PhpParser\\Type\\UnionType', $type);
 }
 /**
  * @group packageDependencies
  */
 public function testDeletePackageVersionWhenInheritingBetweenPackages()
 {
     $this->packageVersion->addContainer($foo = new Clazz('Foo'));
     $foo->addProperty($fooProperty = new Property('foo'));
     $fooProperty->setPhpType($this->typeRegistry->getNativeType('string'));
     $this->em->persist($this->packageVersion);
     $this->otherPackageVersion->addDependency($this->packageVersion);
     $this->otherPackageVersion->addContainer($bar = new Clazz('bar'));
     $bar->addProperty($fooProperty, 'Foo');
     $this->em->persist($this->otherPackageVersion);
     $this->em->flush();
     $this->assertVersionsCount(2);
     $this->repo->deletePackageVersion($this->packageVersion);
     $this->em->clear();
     $this->assertVersionsCount(0);
 }
 private function findOverriddenMethodsForDocInheritance($methodName, Clazz $clazz)
 {
     $methods = array();
     foreach ($clazz->getImplementedInterfaces() as $interfaceName) {
         if (null !== ($interface = $this->registry->getClass($interfaceName))) {
             if ($interface->hasMethod($methodName)) {
                 $methods[] = $interface->getMethod($methodName);
             }
         }
     }
     $superClass = $clazz;
     while (null !== ($superClass = $superClass->getSuperClassType())) {
         if ($superClass->hasMethod($methodName) && ($parentMethod = $superClass->getMethod($methodName)) && $parentMethod->isAbstract()) {
             $methods[] = $parentMethod;
         }
     }
     return $methods;
 }
 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;
 }
 private function createClass($class)
 {
     $n = new \PHPParser_Node_Name_FullyQualified(explode("\\", $class));
     if (is_string($class)) {
         $class = new \Scrutinizer\PhpAnalyzer\Model\Clazz($class);
         $class->setNormalized(true);
         $this->registry->registerClass($class);
     }
     $n->setAttribute('type', $class);
     return $n;
 }
 public function parse(\PHPParser_Node $node)
 {
     if ($node instanceof \PHPParser_Node_Stmt_Class) {
         $class = new Clazz(implode("\\", $node->namespacedName->parts));
         // convert PHPParser modifier to our modifier
         $modifier = 0;
         if (\PHPParser_Node_Stmt_Class::MODIFIER_FINAL === ($node->type & \PHPParser_Node_Stmt_Class::MODIFIER_FINAL)) {
             $modifier |= Clazz::MODIFIER_FINAL;
         }
         if (\PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT === ($node->type & \PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT)) {
             $modifier |= Clazz::MODIFIER_ABSTRACT;
         }
         $class->setModifier($modifier);
         if (null !== $node->extends) {
             $class->setSuperClass(implode("\\", $node->extends->parts));
         }
         foreach ($node->implements as $iface) {
             $class->addImplementedInterface(implode("\\", $iface->parts));
         }
     } else {
         if ($node instanceof \PHPParser_Node_Stmt_Interface) {
             $class = new InterfaceC(implode("\\", $node->namespacedName->parts));
             foreach ($node->extends as $interface) {
                 $class->addExtendedInterface(implode("\\", $interface->parts));
             }
         } else {
             if ($node instanceof \PHPParser_Node_Stmt_Trait) {
                 $class = new TraitC(implode("\\", $node->namespacedName->parts));
             } else {
                 throw new \LogicException(sprintf('The other statements were exhaustive. The node "%s" is not supported.', get_class($node)));
             }
         }
     }
     $class->setImportedNamespaces($this->importedNamespaces);
     $class->setAstNode($node);
     // add methods, properties, and constants
     foreach ($node->stmts as $stmt) {
         if ($stmt instanceof \PHPParser_Node_Stmt_ClassMethod) {
             $this->scanMethod($stmt, $class);
         } else {
             if ($stmt instanceof \PHPParser_Node_Stmt_Property) {
                 $visibility = \PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC === ($stmt->type & \PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC) ? Property::VISIBILITY_PUBLIC : (\PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED === ($stmt->type & \PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED) ? Property::VISIBILITY_PROTECTED : Property::VISIBILITY_PRIVATE);
                 foreach ($stmt->props as $propNode) {
                     assert($propNode instanceof \PHPParser_Node_Stmt_PropertyProperty);
                     // This is a PHP error which we flag in a later pass. Here, we can just ignore the property definition.
                     if ($class->isInterface()) {
                         continue;
                     }
                     assert($class instanceof Clazz || $class instanceof TraitC);
                     $property = new Property($propNode->name);
                     $property->setAstNode($propNode);
                     $property->setVisibility($visibility);
                     $class->addProperty($property);
                 }
             } else {
                 if ($stmt instanceof \PHPParser_Node_Stmt_ClassConst) {
                     foreach ($stmt->consts as $constNode) {
                         assert($constNode instanceof \PHPParser_Node_Const);
                         $constant = new Constant($constNode->name);
                         $constant->setAstNode($constNode);
                         if (null !== ($type = $constNode->value->getAttribute('type'))) {
                             $constant->setPhpType($type);
                         }
                         $class->addConstant($constant);
                     }
                 }
             }
         }
     }
     // Add magic properties denoted by @property, @property-read, @property-write.
     if ($node instanceof \PHPParser_Node_Stmt_Class && preg_match_all('#@(?:property|property-read|property-write)\\s+[^\\s]+\\s+\\$?([^\\s]+)#', $node->getDocComment(), $matches)) {
         for ($i = 0, $c = count($matches[0]); $i < $c; $i++) {
             // If there is already an explicitly declared property of the same
             // name, it has precedence for us.
             if ($class->hasProperty($matches[1][$i])) {
                 $this->logger->warning(sprintf('The property "%s" is already defined in code; ignoring @property tag.', $matches[1][$i]));
                 continue;
             }
             $property = new Property($matches[1][$i]);
             $property->setAstNode($node);
             $class->addProperty($property);
         }
     }
     // Add magic methods denoted by @method.
     if ($node instanceof \PHPParser_Node_Stmt_Class && preg_match_all('#@method\\s+([^@]+)#s', $node->getDocComment(), $matches)) {
         foreach ($matches[1] as $methodDef) {
             if (null !== ($method = $this->parseCommentMethodDef($methodDef))) {
                 // An explicitly defined method has precedence.
                 if ($class->hasMethod($method->getName())) {
                     $this->logger->warning(sprintf('The method "%s" is already defined in code; ignoring @method tag.', $method->getName()));
                     continue;
                 }
                 $class->addMethod($method);
             }
         }
     }
     return $class;
 }
 /**
  * @group equals
  */
 public function testEqualsWithResolvedNamedAndResolvedType()
 {
     $a = new NamedType($this->registry, 'Foo');
     $b = new \Scrutinizer\PhpAnalyzer\Model\Clazz('Foo');
     $b->setNormalized(true);
     $a->setReferencedType($b);
     $this->assertTrue($a->equals($b));
     $this->assertTrue($b->equals($a));
     $a = new NamedType($this->registry, 'Foo');
     $c = new \Scrutinizer\PhpAnalyzer\Model\Clazz('Foo');
     $c->setNormalized(true);
     $a->setReferencedType($c);
     $this->assertTrue($c->equals($a));
     $this->assertTrue($a->equals($c));
 }