/** * Extract class from position * * @param $n * @param TokenCollection $tokens * @return ReflectedClass */ public function extract(&$n, TokenCollection $tokens) { // is abstract ? $prev = $this->searcher->getPrevious($n, $tokens); $isAbstract = $prev && T_ABSTRACT === $prev->getType(); $classname = $this->searcher->getFollowingName($n, $tokens); $class = new ReflectedClass($this->namespace, trim($classname)); $class->setAbstract($isAbstract); return $class; }
/** * Extract class from position * * @param $n * @param TokenCollection $tokens * @return ReflectedClass */ public function extract(&$n, TokenCollection $tokens) { // is PHP7 ? $previous = $tokens->get($n - 2); if ($previous && T_NEW === $previous->getType()) { // anonymous class $class = new ReflectedAnonymousClass($this->namespace, 'class@anonymous'); return $class; } // is abstract ? $prev = $this->searcher->getPrevious($n, $tokens); $isAbstract = $prev && T_ABSTRACT === $prev->getType(); $classname = $this->searcher->getFollowingName($n, $tokens); $class = new ReflectedClass($this->namespace, trim($classname)); $class->setAbstract($isAbstract); return $class; }
/** * Calculates Card And Agresti metric * * Fan-out = Structural fan-out = Number of other procedures this procedure calls * v = number of input/output variables for a procedure * * (SC) Structural complexity = fan-out^2 * (DC) Data complexity = v / (fan-out + 1) * * @param ReflectedClass $class * @return Result */ public function calculate(ReflectedClass $class) { $result = new Result(); $sy = $dc = $sc = array(); // in system foreach ($class->getMethods() as $method) { $fanout = sizeof($method->getDependencies(), COUNT_NORMAL); $v = sizeof($method->getArguments(), COUNT_NORMAL) + sizeof($method->getReturns(), COUNT_NORMAL); $ldc = $v / ($fanout + 1); $lsc = pow($fanout, 2); $sy[] = $ldc + $lsc; $dc[] = $ldc; $sc[] = $lsc; } $result->setRelativeStructuralComplexity(empty($sc) ? 0 : round(array_sum($sc) / sizeof($sc, COUNT_NORMAL), 2))->setRelativeDataComplexity(empty($dc) ? 0 : round(array_sum($dc) / sizeof($dc, COUNT_NORMAL), 2))->setRelativeSystemComplexity(empty($sy) ? 0 : round(array_sum($sy) / sizeof($sy, COUNT_NORMAL), 2))->setTotalStructuralComplexity(round(array_sum($sc), 2))->setTotalDataComplexity(round(array_sum($dc), 2))->setTotalSystemComplexity(round(array_sum($dc) + array_sum($sc), 2)); return $result; }
/** * Extract dependency from call * * @param $n * @param TokenCollection $tokens * @return string * @throws \LogicException */ public function extract(&$n, TokenCollection $tokens) { $token = $tokens[$n]; $call = null; switch ($token->getType()) { case T_PAAMAYIM_NEKUDOTAYIM: $prev = $n - 1; $value = $this->searcher->getUnder(array('::'), $prev, $tokens); switch (true) { case $value == 'parent' && $this->currentClass: return $this->currentClass->getParent(); case $value == 'parent': // we try to get the name of the parent class $extendPosition = $this->searcher->getExtendPosition($tokens, $n); return $this->searcher->getFollowingName($extendPosition, $tokens); case ($value == 'static' || $value === 'self') && $this->currentClass: return $this->currentClass->getFullname(); case $value == 'static' || $value === 'self': $extendPosition = $this->searcher->getClassNamePosition($tokens); return $this->searcher->getFollowingName($extendPosition, $tokens); default: return $value; } case T_NEW: $call = $this->searcher->getFollowingName($n, $tokens); if (preg_match('!^(\\w+)!', $call, $matches)) { // fixes PHP 5.4: (new MyClass)->foo() $call = $matches[1]; } break; } if (null === $call) { throw new \LogicException('Classname of call not found'); } return $call; }
/** * @param ReflectedClass|ReflectedInterface|ReflectedTrait $class * @return array */ protected function processClassData($class, $includeFile = false) { $data = []; // $data['namespace'] = $class->getNamespace(); $data['namespace'] = ltrim($class->getNamespace(), '\\'); $data['name'] = $class->getName(); $data['extends'] = $class->getParent(); $data['dependencies'] = $class->getDependencies(); $data['methods'] = $this->processMethods($class); try { if ($includeFile) { include_once $includeFile; } $reflection = new \ReflectionClass($class->getFullname()); //$data['constants'] = $this->processConstants($reflection); $data['constants'] = $this->processConstants($reflection); $data['properties'] = $this->processProperties($reflection); } catch (\Exception $e) { } return $data; }
/** * Search methods whose share attribute * * @param ReflectedClass $class * @param ReflectedMethod $method * @return array */ private function searchDirectLinkedMethodsByMember(ReflectedClass $class, ReflectedMethod $method) { $linked = array(); $members = array(); if (preg_match_all('!\\$this\\->([\\w\\(]+)!im', $method->getContent(), $matches)) { list(, $members) = $matches; } // search in other methods if they share attribute foreach ($class->getMethods() as $otherMethod) { $otherMembers = array(); if (preg_match_all('!\\$this\\->([\\w\\(]+)!im', $otherMethod->getContent(), $matches)) { list(, $otherMembers) = $matches; } $intersect = array_intersect($members, $otherMembers); // remove calls (members and calls are mixed : regex is too complex to be read) foreach ($intersect as $k => $name) { if (preg_match('!\\($!', $name)) { unset($intersect[$k]); } } if (sizeof($intersect, COUNT_NORMAL) > 0) { array_push($linked, $otherMethod->getName()); } } return $linked; }