5

我正在尝试使用标记器扫描文件以查找所有定义的类、它们扩展的任何内容、任何创建的实例以及它们被静态调用的任何时间。

<?php

$tokens = token_get_all(file_get_contents($file));

$used_classes = array();
$defined_classes = array();
$variable_classes = array();

foreach($tokens as $i => $token) {

    if(is_array($token)) {

        if(isset($tokens[$i - 2][0], $tokens[$i - 1][0])) {

            // new [class]
            if ($tokens[$i - 2][0] == T_NEW AND $tokens[$i - 1][0] == T_WHITESPACE) {

                if($tokens[$i][0] == T_STRING) {
                    $used_classes[$token[1]] = TRUE;

                // new $variable()
                } elseif($tokens[$i][0] == T_VARIABLE) {    

                    // @todo, this is really broken. However, do best to look for the assignment
                    if(preg_match('~\$var\s*=\s*([\'"])((?:(?!\1).)*)\1~', $text, $match)) {
                        if(empty($extension_classes[$match[2]])) {
                            $used_classes[$match[2]] = TRUE;
                        }
                    } elseif($token[1] !== '$this') {
                        $variable_classes[$token[1]] = TRUE;
                    }
                }

            }

            // class [class]
            if ($tokens[$i - 2][0] == T_CLASS AND $tokens[$i - 1][0] == T_WHITESPACE) {

                if($tokens[$i][0] == T_STRING) {
                    $defined_classes[$token[1]] = TRUE;
                }
            }


            // @todo: find more classes \/

            // class [classname] extends [class] ???
            // [class]::method()???
        }
    }
}

如何扩展此代码以查找上述 PHP 类的任何其他实例?

4

4 回答 4

2

解析然后解释 PHP 代码不是使用正则表达式可以很好地解决的问题。你需要一个更聪明的东西,比如状态机,它可以真正理解范围、类名、继承等内容,以便能够做你想做的事情。

碰巧的是,我碰巧写了一个基于状态机的PHP 到 Javascript转换器,它几乎可以完成你想做的大部分事情:

所有定义的类

是的,所有类都创建了一个 ClassScope,其中列出了所有变量,并且它们的方法被创建为 FunctionScope,因此您可以知道一个类具有哪些方法。

他们扩展的任何东西

是的,每个类都有它的父类在 ClassScope->$parentClasses 中列出

任何创建的实例

不,但是添加额外的代码来记录这些并不难。

任何时候它们被静态调用。

不——但这实际上可以用正则表达式来完成。

虽然它并不能完全解决您的问题,但目前的项目可以让您完成您想做的事情的 95%,这将节省几周的工作。

于 2013-02-20T13:41:57.957 回答
0

我认为您不能仅通过分析令牌来做到这一点。

您需要知道,对于任何类名,它所代表的实际定义是什么,包括任何继承关系,以及它是否已在您的代码中用于实现接口。类/接口定义可能在另一个文件中;在某些情况下可能会包含该文件。您可能在不同的文件中以不同的方式定义相同的类名。因此,通常您需要一次处理构成系统的所有文件。

作为基础,您需要一个解析 PHP 并构建真实符号表的工具。您也许可以从中计算出您的结果。(这样的工具分析令牌作为起点,但它比琐碎的令牌扫描工作要多得多)。

于 2013-02-15T22:09:14.173 回答
0

包含可能值得在这里研究,尽管我认为它不会为您提供超出哪些文件/类以及包含多少次的任何数据。

于 2013-02-13T15:42:40.730 回答
0

看起来如果您只是加载代码,然后可以使用内置的反射 API(ReflectionClass::_construct()等)来检查每个类。

要获取类本身,请使用内置的get_declared_classes()

(注:这个我没试过,所以YMMV。)

于 2013-02-19T23:07:02.153 回答