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 testPersist()
 {
     $this->packageVersion->addContainer($foo = new Clazz('Foo'));
     $foo->addImplementedInterface('Iterator');
     $foo->addMethod($fooMethod = new Method('foo'));
     $this->packageVersion->addFunction($count_foo = new GlobalFunction('count_foo'));
     CallSite::create($fooMethod, $count_foo);
     $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();
     assert($reloadedFoo instanceof Clazz);
     $this->assertEquals(array('Iterator'), $reloadedFoo->getImplementedInterfaces());
     $this->assertTrue($reloadedFoo->hasMethod('foo'));
     $reloadedCountFoo = $this->em->createQuery('SELECT f FROM Scrutinizer\\PhpAnalyzer\\Model\\GlobalFunction f WHERE f.name = :name')->setParameter('name', 'count_foo')->getSingleResult();
     $this->assertCount(1, $inSites = $reloadedCountFoo->getInCallSites());
     $this->assertSame($reloadedFoo->getMethod('foo')->getMethod(), $inSites[0]->getSource());
 }
 public function persist(CallSite $callSite)
 {
     // In this case, the call site has already been persisted.
     if (null !== $callSite->getId()) {
         return;
     }
     $sourceFunctionId = $targetFunctionId = $sourceMethodId = $targetMethodId = null;
     switch (true) {
         case $callSite instanceof FunctionToFunctionCallSite:
             $type = 'f2f';
             $sourceFunctionId = $sourceId = $callSite->getSource()->getId();
             $targetFunctionId = $targetId = $callSite->getTarget()->getId();
             break;
         case $callSite instanceof FunctionToMethodCallSite:
             $type = 'f2m';
             $sourceFunctionId = $sourceId = $callSite->getSource()->getId();
             $targetMethodId = $targetId = $callSite->getTarget()->getId();
             break;
         case $callSite instanceof MethodToFunctionCallSite:
             $type = 'm2f';
             $sourceMethodId = $sourceId = $callSite->getSource()->getId();
             $targetFunctionId = $targetId = $callSite->getTarget()->getId();
             break;
         case $callSite instanceof MethodToMethodCallSite:
             $type = 'm2m';
             $sourceMethodId = $sourceId = $callSite->getSource()->getId();
             $targetMethodId = $targetId = $callSite->getTarget()->getId();
             break;
         default:
             throw new \InvalidArgumentException('Unknown call site ' . get_class($callSite));
     }
     // If either target, or source have not yet been persisted, we
     // simply ignore this call as there will be a second call when
     // both are complete.
     if (null === $sourceId || null === $targetId) {
         return;
     }
     $this->insertStmt->bindValue(1, $type);
     $this->insertStmt->bindValue(2, $sourceFunctionId, $sourceFunctionId ? \PDO::PARAM_INT : \PDO::PARAM_NULL);
     $this->insertStmt->bindValue(3, $targetFunctionId, $targetFunctionId ? \PDO::PARAM_INT : \PDO::PARAM_NULL);
     $this->insertStmt->bindValue(4, $targetMethodId, $targetMethodId ? \PDO::PARAM_INT : \PDO::PARAM_NULL);
     $this->insertStmt->bindValue(5, $sourceMethodId, $sourceMethodId ? \PDO::PARAM_INT : \PDO::PARAM_NULL);
     $this->insertStmt->execute();
     $callSiteId = $this->con->lastInsertId();
     $this->idRef->setValue($callSite, $callSiteId);
     if ("0" == $callSiteId) {
         throw new \LogicException(sprintf('Could not retrieve id of call-site: ' . json_encode(array('type' => $type, 'source_function_id' => $sourceFunctionId, 'target_function_id' => $targetFunctionId, 'target_method_id' => $targetMethodId, 'source_method_id' => $sourceMethodId))));
     }
     foreach ($callSite->getArgs() as $arg) {
         $this->argPersister->persist($arg, $callSiteId);
     }
 }
 private function copyInCallSites(AbstractFunction $function, AbstractFunction $nonCachedFunction)
 {
     foreach ($function->getInCallSites() as $site) {
         $source = $site->getSource();
         $args = $site->getArgs()->getValues();
         $args = array_map(function ($arg) {
             return clone $arg;
         }, $args);
         $source->removeCallSite($site);
         CallSite::create($source, $nonCachedFunction, $args);
     }
 }
 public function removeCallSite(CallSite $site)
 {
     if ($site->getSource() === $this) {
         $target = $site->getTarget();
         if ($target instanceof Method) {
             return $this->getOutMethodCallSites()->removeElement($site);
         } else {
             if ($target instanceof GlobalFunction) {
                 return $this->getOutFunctionCallSites()->removeElement($site);
             }
         }
         throw new \LogicException('Previous ifs were exhaustive.');
     } else {
         if ($site->getTarget() === $this) {
             $source = $site->getSource();
             if ($source instanceof Method) {
                 return $this->getInMethodCallSites()->removeElement($site);
             } else {
                 if ($source instanceof GlobalFunction) {
                     return $this->getInFunctionCallSites()->removeElement($site);
                 }
             }
             throw new \LogicException('Previous ifs were exhaustive.');
         }
     }
     throw new \InvalidArgumentException('$site is neither originating, nor targeting this function.');
 }