示例#1
0
 public function testClassesThatDoesNotExtendOtherClassesShouldNotHaveAParentClass()
 {
     $file = __DIR__ . '/../../../resources/oop/f1.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($file);
     $this->assertCount(1, $result->getClasses());
     $class = current($result->getClasses());
     $this->assertNull($class->getParent());
 }
示例#2
0
 /**
  * @dataProvider providesFilesForLcom
  */
 public function testICanCalculateLackOfCohesionOfClass($file, $expected)
 {
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($file);
     $classes = $result->getClasses();
     $class = $classes[0];
     $lcom = new LackOfCohesionOfMethods();
     $result = $lcom->calculate($class);
     $this->assertEquals($expected, $result->getLCOM());
 }
 public function testAnonymousClassIsFound()
 {
     $filename = __DIR__ . '/../../../resources/oop/php7-scalarhint1.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $this->assertEquals(1, sizeof($classes));
     $main = $classes[0];
     $this->assertEquals(0, sizeof($main->getDependencies()));
 }
 public function testProxyIsDetected()
 {
     $filename = __DIR__ . '/../../../../resources/patterns/proxy.php';
     $extractor = new Extractor(new Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $class = $classes[2];
     $resolved = new ResolvedClass($class);
     $resolver = new ProxyResolver($classes);
     $resolver->resolve($resolved);
     $this->assertEquals(1, sizeof($resolved->getPatterns()));
 }
示例#5
0
 public function testCallsAreFoundAsDependencies()
 {
     $file = __DIR__ . '/../../../resources/oop/f5.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($file);
     $classes = $result->getClasses();
     $this->assertCount(1, $classes, 'all classes are found');
     $class = $classes[0];
     $dependencies = $class->getDependencies();
     $expected = array('\\Example\\IAmCalled', '\\IAmCalled');
     $this->assertEquals($expected, $dependencies, 'Direct dependencies (calls) are found');
 }
示例#6
0
 public function testCouplingTakesCareOfReturnedValues()
 {
     $filename = __DIR__ . '/../../../../../resources/coupling/f1.php';
     $extractor = new Extractor(new Tokenizer());
     $classmap = new ClassMap();
     $classmap->push($filename, $extractor->extract($filename));
     $coupling = new Coupling();
     $this->result = $coupling->calculate($classmap);
     $this->assertEquals(0, $this->result->get('\\ClassWhoUseAnother')->getAfferentCoupling());
     $this->assertEquals(1, $this->result->get('\\ClassWhoUseAnother')->getEfferentCoupling());
     $this->assertEquals(1, $this->result->get('\\ClassWhoIsUsed')->getAfferentCoupling());
     $this->assertEquals(0, $this->result->get('\\ClassWhoIsUsed')->getEfferentCoupling());
 }
 /**
  * @dataProvider provideAbstractClasses
  */
 public function testAbstractClassesAreFound($filename, $expected)
 {
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($filename);
     $found = 0;
     foreach ($result->getClasses() as $class) {
         if ($class->isAbstract()) {
             $found++;
             $this->assertContains($class->getFullname(), $expected);
         }
     }
     $this->assertEquals(sizeof($expected, COUNT_NORMAL), $found);
 }
 /**
  * @inheritdoc
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output->writeln('Design pattern detector by Jean-François Lépine <https://twitter.com/Halleck45>');
     $output->writeln('');
     $finder = new Finder($input->getOption('extensions'), $input->getOption('excluded-dirs'));
     $files = $finder->find($input->getArgument('path'));
     if (0 == sizeof($files, COUNT_NORMAL)) {
         throw new \LogicException('No file found');
     }
     //
     // 1. Extracting classes
     $output->writeln('<info>Extracting classes</info>');
     $progress = new ProgressBar($output);
     $progress->start(sizeof($files, COUNT_NORMAL));
     $collection = array();
     $tokenizer = new Tokenizer(new CacheMemory());
     $extractor = new Extractor($tokenizer);
     $nbClasses = 0;
     foreach ($files as $k => $filename) {
         $progress->advance();
         $collection[] = $classes = $extractor->extract($filename);
         $nbClasses += sizeof($classes->getClasses());
     }
     $progress->clear();
     $progress->finish();
     // inform user
     $output->writeln('');
     $output->writeln('');
     $output->writeln(sprintf("<info>Found %d classes</info>", $nbClasses));
     //
     // 2. Extracting patterns
     $output->writeln('<info>Extracting design patterns</info>');
     $patterns = array();
     foreach ($collection as $oop) {
         $classes = $oop->getClasses();
         $resolver = new PatternResolver($classes);
         foreach ($classes as $class) {
             $resolvedClass = new ResolvedClass($class);
             $resolver->resolve($resolvedClass);
             if ($resolvedClass->getPatterns()) {
                 $patterns = array_merge($patterns, $resolvedClass->getPatterns());
             }
         }
     }
     // inform user
     $output->writeln(sprintf("<info>Found %d design patterns</info>", sizeof($patterns)));
     $output->writeln();
     foreach ($patterns as $pattern) {
         $output->writeln(sprintf("\t<info>[%s]</info> %s", $pattern->getName(), $pattern->describe()));
     }
 }
 /**
  * @dataProvider providesClasses
  */
 public function testICanCalculateSystemComplexityOfClass($totalDataComplexity, $totalStructureComplexity, $totalSystemComplexity, $code)
 {
     $filename = tempnam(sys_get_temp_dir(), 'unit-phpmetrics-syc');
     file_put_contents($filename, $code);
     $extractor = new Extractor(new Tokenizer());
     $classes = $extractor->extract($filename)->getClasses();
     $class = $classes[0];
     $metric = new SystemComplexity();
     $result = $metric->calculate($class);
     $this->assertEquals($totalDataComplexity, $result->getTotalDataComplexity(), 'total data complexity');
     $this->assertEquals($totalStructureComplexity, $result->getTotalStructuralComplexity(), 'total structure complexity');
     $this->assertEquals($totalSystemComplexity, $result->getTotalSystemComplexity(), 'total system complexity');
     unlink($filename);
 }
 public function testReturnedTypeIsFoundEvenOnAbstractMethod()
 {
     $filename = __DIR__ . '/../../../resources/oop/php7-return3.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $this->assertEquals(1, sizeof($classes));
     $methods = $classes[0]->getMethods();
     $this->assertEquals(2, sizeof($methods));
     $method = $methods['createSchema'];
     $expected = new ReflectedReturn();
     $expected->setMode(ReflectedReturn::STRICT_TYPE_HINT)->setType('\\Schema');
     $this->assertEquals(array($expected), $method->getReturns());
 }
 public function testUsageOfConstantInParameterDoesNotBreakEngine()
 {
     $filename = __DIR__ . '/../../../resources/oop/php7-return-bugfix1.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $this->assertEquals(1, sizeof($classes));
     $methods = $classes[0]->getMethods();
     $this->assertEquals(1, sizeof($methods));
     $method = $methods['register'];
     $expected = new ReflectedReturn();
     $expected->setMode(ReflectedReturn::ESTIMATED_TYPE_HINT)->setType(TypeResolver::TYPE_UNKNWON)->setValue('stream_filter_register($name, $class)');
     $this->assertEquals(array($expected), $method->getReturns());
 }
 public function testGodObjectIsDetected()
 {
     $filename = __DIR__ . '/../../../../resources/patterns/godobject.php';
     $extractor = new Extractor(new Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $resolver = new GodObjectResolver($classes);
     $resolved = new ResolvedClass($classes[0]);
     $resolver->resolve($resolved);
     $this->assertEquals(1, sizeof($resolved->getPatterns()));
     $resolved = new ResolvedClass($classes[1]);
     $resolver->resolve($resolved);
     $this->assertEquals(0, sizeof($resolved->getPatterns()));
 }
示例#13
0
 /**
  * Run analyze
  *
  * @param $filename
  * @return \Hal\Component\Result\ResultSet
  */
 public function execute($filename)
 {
     $rHalstead = $this->halstead->calculate($filename);
     $rLoc = $this->loc->calculate($filename);
     $rMcCabe = $this->mcCabe->calculate($filename);
     $rMyer = $this->myer->calculate($filename);
     $rMaintenability = $this->maintenabilityIndex->calculate($rHalstead, $rLoc, $rMcCabe);
     $resultSet = new \Hal\Component\Result\ResultSet($filename);
     $resultSet->setLoc($rLoc)->setMcCabe($rMcCabe)->setMyer($rMyer)->setHalstead($rHalstead)->setMaintenabilityIndex($rMaintenability);
     if ($this->withOOP) {
         $rOOP = $this->extractor->extract($filename);
         $this->classMap->push($filename, $rOOP);
         $resultSet->setOOP($rOOP);
     }
     return $resultSet;
 }
示例#14
0
 /**
  * @group php7
  */
 public function testInterfacesAreFound()
 {
     // only one contract
     $filename = __DIR__ . '/../../../resources/oop/interface1.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $this->assertCount(2, $classes);
     $class = $classes[1];
     $this->assertEquals(array('\\Contract1'), $class->getInterfaces(), 'interface of class is found');
     // multiple contracts
     $filename = __DIR__ . '/../../../resources/oop/interface2.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $this->assertCount(3, $classes);
     $class = $classes[2];
     $this->assertEquals(array('\\My\\Contract1', '\\My\\Contract2'), $class->getInterfaces(), 'multiple interfaces of class are found');
 }
    public function testContentOfMethodIsFound()
    {
        $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
        $result = $extractor->extract(__DIR__ . '/../../../resources/oop/f6.php');
        $classes = $result->getClasses();
        $class = $classes[0];
        $methods = $class->getMethods();
        $method = $methods['foo'];
        $expected = <<<EOT
\$a = strtoupper((string)\$a);
return \$a;
EOT;
        $this->assertEquals($expected, $method->getContent());
        $methods = $class->getMethods();
        $method = end($methods);
        $expected = <<<EOT
\$x = 1 * 2;
die();
EOT;
        $this->assertEquals($expected, $method->getContent());
    }
 public function testReservedWordClassDoesNotCount()
 {
     $filename = __DIR__ . '/../../../resources/oop/reserved-word-class.php';
     $tokens = (new \Hal\Component\Token\Tokenizer())->tokenize($filename);
     $extractor = new Extractor();
     $result = $extractor->extract($tokens);
     $classes = $result->getClasses();
     $this->assertEquals(1, sizeof($classes));
     $class = $classes[0];
     $this->assertEquals('\\My\\Test', $class->getFullname());
 }
示例#17
0
 public function testReturningNewStaticIsWellParsed()
 {
     $filename = __DIR__ . '/../../../resources/oop/php7-static-as-dep1.php';
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract($filename);
     $classes = $result->getClasses();
     $this->assertEquals(1, sizeof($classes));
     $class = $classes[0];
     $this->assertEquals(array('\\My\\MyClass'), $class->getDependencies());
 }
示例#18
0
 public function testSetterAreFound()
 {
     $extractor = new Extractor(new \Hal\Component\Token\Tokenizer());
     $result = $extractor->extract(__DIR__ . '/../../../resources/oop/f8.php');
     $classes = $result->getClasses();
     $class = $classes[0];
     $methods = $class->getMethods();
     $this->assertFalse($methods['getA']->isSetter());
     $this->assertFalse($methods['foo']->isSetter());
     $this->assertTrue($methods['setA']->isSetter());
     $this->assertTrue($methods['setB']->isSetter());
 }
 public function testMultipleClassesWithSameMethodName()
 {
     $filename = __DIR__ . '/../../../resources/oop/php7-6.php';
     $tokens = (new \Hal\Component\Token\Tokenizer())->tokenize($filename);
     $extractor = new Extractor();
     $result = $extractor->extract($tokens);
     $classes = $result->getClasses();
     $this->assertEquals(7, sizeof($classes));
     $mother = $classes[0];
     $class1 = $classes[2];
     $class2 = $classes[4];
     $this->assertEquals('\\My\\B', $class1->getFullname());
     $this->assertEquals('\\My\\C', $class2->getFullname());
     $this->assertEquals(array('\\My\\D', '\\My\\A', '\\My\\Mother'), $class1->getDependencies());
 }