从PHP代码库中检测/删除未使用的“use”语句的最简单方法
我到处都在寻找类似的东西,但我相信“使用”这个词对于任何有用的结果来说可能太常见了: 从PHP代码库的类文件中删除所有未使用的从PHP代码库中检测/删除未使用的“use”语句的最简单方法,php,Php,我到处都在寻找类似的东西,但我相信“使用”这个词对于任何有用的结果来说可能太常见了: 从PHP代码库的类文件中删除所有未使用的use语句的最简单方法是什么 编辑:为了简单起见,我们可以忽略用于注释的使用语句。这可能取决于代码的设置方式。如果您的代码使用这样的名称空间: namespace Foo { <one or more classes in namespace Foo> } 名称空间Foo { } 如果您只是单独检查每个文件,您可能就没事了。这仍然意味着您必须解析PH
use
语句的最简单方法是什么
编辑:为了简单起见,我们可以忽略用于注释的
使用语句。这可能取决于代码的设置方式。如果您的代码使用这样的名称空间:
namespace Foo
{
<one or more classes in namespace Foo>
}
名称空间Foo
{
}
如果您只是单独检查每个文件,您可能就没事了。这仍然意味着您必须解析PHP代码以找到use语句,然后确定使用了哪些语句
简单的方法是使用已经构建的工具。我最近开始使用(30天免费试用,或the),它可以在文件中有未使用的use
语句时通知您(您甚至可以指定该语句是作为警告还是错误出现)。但仍然需要打开每个文件。但是你也可以检查你正在编辑的文件,这样最终你的代码会更干净。编辑
我已经完全重写了它,所以现在它更强大了:
- 忽略Traits和匿名/lambda函数
- 现在处理catch块、类扩展和接口
- 缩进和注释无关紧要
- 命名空间别名的多个声明也起作用
- 静态和对象类调用被识别为“用法”($u->getUsages())
- 未处理完全合格和半合格使用
测试文件class.php:
检查FriendsOfPHP的PHP-CS-Fixer该工具如何知道名称空间何时未被使用?您需要收集每个use语句,使用标记器解析您的文件,并查看它是实例化的还是静态调用的。但这需要一些工作。我已经在回答中编辑了代码,您现在应该再试一次:)。我测试了一些案例,结果成功了。我希望这是为了让你现在满意。但它只适用于一个文件;对于更大的项目,你应该调整它,并建立一个更大的索引。php风暴:alt+control+o(这是一个不需要动脑筋的问题)@ling you忘了第#1步,你每年支付89美元!我将试一试并让您知道它是如何运行的。类内的使用
指令(用于PHP5.4中的traits)和前面的闭包块是否都具有与命名空间使用
不同的令牌类型?如果没有,您可能希望确保此代码忽略这些。好的一点,我知道,我已经忘记了一些情况,我将很快对代码进行一些修改。我接受您的答案,因为它可以完成工作。我只需要一个快速脚本来告诉我哪里有未使用的use
语句,这很好(除了一些小错误)。谢谢您的代码缺少两个用例:$foo foo instanceof FooInterface
和对象类型提示foo(ClassOne$one,ClassTwo$too)
。否则它似乎工作得很好。这个工具是faboo。谢谢大家!/php-cs-fixer-fix-folder/--fixers=unused\u use
对我有效/php-cs-fixer-fix-src/Backend/--rules=no\u unused\u imports
对我有效
<?php
use My\Full\Classname as Another, My\Full\NSname, Some\Other\Space;
/* some insane commentary */ use My\Full\NSname1; use ArrayObject;
$obj = new namespaced\Another;
$obj = new Another;
$a = new ArrayObject(array(1));
Space::call();
$a = function($a, $b, $c = 'test') use ($obj) {
/* use */
};
class MyHelloWorld extends Base {
use traits, hello, world;
}
<?php
class UseStatementSanitzier
{
protected $content;
public function __construct($file)
{
$this->content = token_get_all(file_get_contents($file));
// we don't need and want them while parsing
$this->removeTokens(T_COMMENT);
$this->removeTokens(T_WHITESPACE);
}
public function getUnused()
{
$uses = $this->getUseStatements();
$usages = $this->getUsages();
$unused = array();
foreach($uses as $use) {
if (!in_array($use, $usages)) {
$unused[] = $use;
}
}
return $unused;
}
public function getUsages()
{
$usages = array();
foreach($this->content as $key => $token) {
if (!is_string($token)) {
$t = $this->content;
// for static calls
if ($token[0] == T_DOUBLE_COLON) {
// only if it is NOT full or half qualified namespace
if ($t[$key-2][0] != T_NAMESPACE) {
$usages[] = $t[$key-1][1];
}
}
// for object instanciations
if ($token[0] == T_NEW) {
if ($t[$key+2][0] != T_NAMESPACE) {
$usages[] = $t[$key+1][1];
}
}
// for class extensions
if ($token[0] == T_EXTENDS || $token[0] == T_IMPLEMENTS) {
if ($t[$key+2][0] != T_NAMESPACE) {
$usages[] = $t[$key+1][1];
}
}
// for catch blocks
if ($token[0] == T_CATCH) {
if ($t[$key+3][0] != T_NAMESPACE) {
$usages[] = $t[$key+2][1];
}
}
}
}
return array_values(array_unique($usages));
}
public function getUseStatements()
{
$tokenUses = array();
$level = 0;
foreach($this->content as $key => $token) {
// for traits, only first level uses should be captured
if (is_string($token)) {
if ($token == '{') {
$level++;
}
if ($token == '}') {
$level--;
}
}
// capture all use statements besides trait-uses in class
if (!is_string($token) && $token[0] == T_USE && $level == 0) {
$tokenUses[] = $key;
}
}
$useStatements = array();
// get rid of uses in lambda functions
foreach($tokenUses as $key => $tokenKey) {
$i = $tokenKey;
$char = '';
$useStatements[$key] = '';
while($char != ';') {
++$i;
$char = is_string($this->content[$i]) ? $this->content[$i] : $this->content[$i][1];
if (!is_string($this->content[$i]) && $this->content[$i][0] == T_AS) {
$useStatements[$key] .= ' AS ';
} else {
$useStatements[$key] .= $char;
}
if ($char == '(') {
unset($useStatements[$key]);
break;
}
}
}
$allUses = array();
// get all use statements
foreach($useStatements as $fullStmt) {
$fullStmt = rtrim($fullStmt, ';');
$fullStmt = preg_replace('/^.+ AS /', '', $fullStmt);
$fullStmt = explode(',', $fullStmt);
foreach($fullStmt as $singleStmt) {
// $singleStmt only for full qualified use
$fqUses[] = $singleStmt;
$singleStmt = explode('\\', $singleStmt);
$allUses[] = array_pop($singleStmt);
}
}
return $allUses;
}
public function removeTokens($tokenId)
{
foreach($this->content as $key => $token) {
if (isset($token[0]) && $token[0] == $tokenId) {
unset($this->content[$key]);
}
}
// reindex
$this->content = array_values($this->content);
}
}
$unused = new UseStatementSanitzier('class.php');
print_r($unused->getUnused());
/*
Returns:
Array
(
[0] => NSname
[1] => NSname1
)
*/