SebastianBergmann\PHPLOC\Analyser::countFile PHP Method

countFile() public method

Processes a single file.
public countFile ( string $filename, boolean $countTests )
$filename string
$countTests boolean
    public function countFile($filename, $countTests)
    {
        if ($countTests) {
            $this->preProcessFile($filename);
        }
        $buffer = file_get_contents($filename);
        $this->collector->incrementLines(substr_count($buffer, "\n"));
        $tokens = token_get_all($buffer);
        $numTokens = count($tokens);
        unset($buffer);
        $this->collector->addFile($filename);
        $blocks = [];
        $currentBlock = false;
        $namespace = false;
        $className = null;
        $functionName = null;
        $testClass = false;
        $this->collector->currentClassReset();
        $isInMethod = false;
        for ($i = 0; $i < $numTokens; $i++) {
            if (is_string($tokens[$i])) {
                $token = trim($tokens[$i]);
                if ($token == ';') {
                    if ($className !== null && !$testClass) {
                        $this->collector->currentClassIncrementLines();
                        if ($functionName !== null) {
                            $this->collector->currentMethodIncrementLines();
                        }
                    } elseif ($functionName !== null) {
                        $this->collector->incrementFunctionLines();
                    }
                    $this->collector->incrementLogicalLines();
                } elseif ($token == '?' && !$testClass) {
                    if ($className !== null) {
                        $this->collector->currentClassIncrementComplexity();
                        $this->collector->currentMethodIncrementComplexity();
                    }
                    $this->collector->incrementComplexity();
                } elseif ($token == '{') {
                    if ($currentBlock == T_CLASS) {
                        $block = $className;
                    } elseif ($currentBlock == T_FUNCTION) {
                        $block = $functionName;
                    } else {
                        $block = false;
                    }
                    array_push($blocks, $block);
                    $currentBlock = false;
                } elseif ($token == '}') {
                    $block = array_pop($blocks);
                    if ($block !== false && $block !== null) {
                        if ($block == $functionName) {
                            $functionName = null;
                            if ($isInMethod) {
                                $this->collector->currentMethodStop();
                                $isInMethod = false;
                            }
                        } elseif ($block == $className) {
                            $className = null;
                            $testClass = false;
                            $this->collector->currentClassReset();
                        }
                    }
                }
                continue;
            }
            list($token, $value) = $tokens[$i];
            switch ($token) {
                case T_NAMESPACE:
                    $namespace = $this->getNamespaceName($tokens, $i);
                    $this->collector->addNamespace($namespace);
                    break;
                case T_CLASS:
                case T_INTERFACE:
                case T_TRAIT:
                    if (!$this->isClassDeclaration($tokens, $i)) {
                        continue;
                    }
                    $this->collector->currentClassReset();
                    $this->collector->currentClassIncrementComplexity();
                    $className = $this->getClassName($namespace, $tokens, $i);
                    $currentBlock = T_CLASS;
                    if ($token == T_TRAIT) {
                        $this->collector->incrementTraits();
                    } elseif ($token == T_INTERFACE) {
                        $this->collector->incrementInterfaces();
                    } else {
                        if ($countTests && $this->isTestClass($className)) {
                            $testClass = true;
                            $this->collector->incrementTestClasses();
                        } else {
                            if (isset($tokens[$i - 2]) && is_array($tokens[$i - 2]) && $tokens[$i - 2][0] == T_ABSTRACT) {
                                $this->collector->incrementAbstractClasses();
                            } else {
                                $this->collector->incrementConcreteClasses();
                            }
                        }
                    }
                    break;
                case T_FUNCTION:
                    $prev = $this->getPreviousNonWhitespaceTokenPos($tokens, $i);
                    if ($tokens[$prev][0] === T_USE) {
                        continue;
                    }
                    $currentBlock = T_FUNCTION;
                    $next = $this->getNextNonWhitespaceTokenPos($tokens, $i);
                    if (!is_array($tokens[$next]) && $tokens[$next] == '&') {
                        $next = $this->getNextNonWhitespaceTokenPos($tokens, $next);
                    }
                    if (is_array($tokens[$next]) && $tokens[$next][0] == T_STRING) {
                        $functionName = $tokens[$next][1];
                    } else {
                        $currentBlock = 'anonymous function';
                        $functionName = 'anonymous function';
                        $this->collector->incrementAnonymousFunctions();
                    }
                    if ($currentBlock == T_FUNCTION) {
                        if ($className === null && $functionName != 'anonymous function') {
                            $this->collector->incrementNamedFunctions();
                        } else {
                            $static = false;
                            $visibility = T_PUBLIC;
                            for ($j = $i; $j > 0; $j--) {
                                if (is_string($tokens[$j])) {
                                    if ($tokens[$j] == '{' || $tokens[$j] == '}' || $tokens[$j] == ';') {
                                        break;
                                    }
                                    continue;
                                }
                                if (isset($tokens[$j][0])) {
                                    switch ($tokens[$j][0]) {
                                        case T_PRIVATE:
                                            $visibility = T_PRIVATE;
                                            break;
                                        case T_PROTECTED:
                                            $visibility = T_PROTECTED;
                                            break;
                                        case T_STATIC:
                                            $static = true;
                                            break;
                                    }
                                }
                            }
                            if ($testClass && $this->isTestMethod($functionName, $visibility, $static, $tokens, $i)) {
                                $this->collector->incrementTestMethods();
                            } elseif (!$testClass) {
                                $isInMethod = true;
                                $this->collector->currentMethodStart();
                                if (!$static) {
                                    $this->collector->incrementNonStaticMethods();
                                } else {
                                    $this->collector->incrementStaticMethods();
                                }
                                if ($visibility == T_PUBLIC) {
                                    $this->collector->incrementPublicMethods();
                                } else {
                                    $this->collector->incrementNonPublicMethods();
                                }
                            }
                        }
                    }
                    break;
                case T_CURLY_OPEN:
                    $currentBlock = T_CURLY_OPEN;
                    array_push($blocks, $currentBlock);
                    break;
                case T_DOLLAR_OPEN_CURLY_BRACES:
                    $currentBlock = T_DOLLAR_OPEN_CURLY_BRACES;
                    array_push($blocks, $currentBlock);
                    break;
                case T_IF:
                case T_ELSEIF:
                case T_FOR:
                case T_FOREACH:
                case T_WHILE:
                case T_CASE:
                case T_CATCH:
                case T_BOOLEAN_AND:
                case T_LOGICAL_AND:
                case T_BOOLEAN_OR:
                case T_LOGICAL_OR:
                    if (!$testClass) {
                        if ($isInMethod) {
                            $this->collector->currentClassIncrementComplexity();
                            $this->collector->currentMethodIncrementComplexity();
                        }
                        $this->collector->incrementComplexity();
                    }
                    break;
                case T_COMMENT:
                case T_DOC_COMMENT:
                    // We want to count all intermediate lines before the token ends
                    // But sometimes a new token starts after a newline, we don't want to count that.
                    // That happend with /* */ and /**  */, but not with // since it'll end at the end
                    $this->collector->incrementCommentLines(substr_count(rtrim($value, "\n"), "\n") + 1);
                    break;
                case T_CONST:
                    $this->collector->incrementClassConstants();
                    break;
                case T_STRING:
                    if ($value == 'define') {
                        $this->collector->incrementGlobalConstants();
                        $j = $i + 1;
                        while (isset($tokens[$j]) && $tokens[$j] != ';') {
                            if (is_array($tokens[$j]) && $tokens[$j][0] == T_CONSTANT_ENCAPSED_STRING) {
                                $this->collector->addConstant(str_replace('\'', '', $tokens[$j][1]));
                                break;
                            }
                            $j++;
                        }
                    } else {
                        $this->collector->addPossibleConstantAccesses($value);
                    }
                    break;
                case T_DOUBLE_COLON:
                case T_OBJECT_OPERATOR:
                    $n = $this->getNextNonWhitespaceTokenPos($tokens, $i);
                    $nn = $this->getNextNonWhitespaceTokenPos($tokens, $n);
                    if ($n && $nn && isset($tokens[$n][0]) && ($tokens[$n][0] == T_STRING || $tokens[$n][0] == T_VARIABLE) && $tokens[$nn] == '(') {
                        if ($token == T_DOUBLE_COLON) {
                            $this->collector->incrementStaticMethodCalls();
                        } else {
                            $this->collector->incrementNonStaticMethodCalls();
                        }
                    } else {
                        if ($token == T_DOUBLE_COLON && $tokens[$n][0] == T_VARIABLE) {
                            $this->collector->incrementStaticAttributeAccesses();
                        } elseif ($token == T_OBJECT_OPERATOR) {
                            $this->collector->incrementNonStaticAttributeAccesses();
                        }
                    }
                    break;
                case T_GLOBAL:
                    $this->collector->incrementGlobalVariableAccesses();
                    break;
                case T_VARIABLE:
                    if ($value == '$GLOBALS') {
                        $this->collector->incrementGlobalVariableAccesses();
                    } elseif (isset($this->superGlobals[$value])) {
                        $this->collector->incrementSuperGlobalVariableAccesses();
                    }
                    break;
            }
        }
    }