2012-03-27 4 views
11

Ich habe für so etwas wie das alles vorbei gesucht, aber ich glaube, das Wort„Verwendung“ist vielleicht zu häufig für irgendwelche hilfreiche Ergebnisse:Der einfachste Weg, zu erkennen/entfernen Sie nicht verwendete `use` Aussagen von PHP-Codebasis

Was ist der einfachste Weg, alle nicht verwendeten use Anweisungen aus Klassendateien in einer PHP Codebase zu entfernen?

Bearbeiten: Der Einfachheit halber können wir die Erkennung von use Anweisungen ignorieren, die für Anmerkungen verwendet werden.

+0

Wie würde dieses Tool wissen, wenn ein Namespace nicht verwendet wird? –

+1

Nun, Sie müssen jede Verwendung-Anweisung sammeln, Ihre Dateien mit Tokenizer möglicherweise analysieren und schauen, ob es instanziiert oder statisch aufgerufen wird. Aber es würde ein bisschen Arbeit erfordern. –

+0

Ich habe den Code in meiner Antwort bearbeitet, du solltest es jetzt nochmal probieren :). Ich habe einige Fälle getestet und es hat funktioniert. Ich hoffe, es ist jetzt für Ihre Zufriedenheit. Es funktioniert jedoch nur für eine Datei; Bei größeren Projekten sollten Sie sie anpassen und einen größeren Index erstellen. –

Antwort

16

Überprüfen Sie den PHP-CS-Fixierer von Fabien Potencier https://github.com/fabpot/PHP-CS-Fixer

+1

Dieses Tool ist faboo. Vielen Dank! – yitznewton

+4

'./php-cs-fixer fix ordner/--fixers = unused_use' funktionierte für mich – mrwaim

+0

' ./php-cs-fixer fix src/Backend/--rules = no_unused_imports' hat den Trick für mich gemacht – Kitze

1

Es hängt wahrscheinlich davon ab, wie Ihr Code eingerichtet ist. Wenn Ihr Code Namespaces wie folgt verwendet:

namespace Foo 
{ 
    <one or more classes in namespace Foo> 
} 

dann sind Sie wahrscheinlich in Ordnung, wenn Sie nur jede Datei einzeln überprüfen. Das bedeutet immer noch, dass Sie den PHP-Code analysieren müssen, um die Use-Anweisungen zu finden und dann zu bestimmen, welche Anweisungen verwendet werden.

Der einfache Weg ist, ein Werkzeug zu verwenden, das bereits gebaut wurde. Ich habe vor kurzem begonnen, PhpStorm IDE (30 Tage frei, oder die early access program) zu verwenden und das kann Sie informieren, wenn Sie ungenutzte use Anweisungen in einer Datei haben (und Sie können sogar angeben, ob das als Warnungen oder Fehler angezeigt werden soll). Sie müssten jedoch trotzdem jede Datei öffnen. Sie können aber auch die Dateien überprüfen, die Sie gerade bearbeiten. Dann wird Ihr Code sauberer.

6

EDIT

ich es komplett neu geschrieben haben, so jetzt ist es viel mächtiger ist:

  • Traits und anonym/Lambda-Funktionen ignoriert werden
  • nun von Catch-Blöcke kümmert, Klasse Erweiterungen und Schnittstellen
  • Einrückung und Kommentare sind egal
  • Mehrere Deklarationen für Namespa ce Aliase arbeiten zu
  • Statische und Objektklasse Anrufe erkannt werden als „Nutzung“ (u- $> getUsages())
  • Voll- und Halb qualifizierte Verwendungen sind nicht
  • behandelt

Die Testdatei, Klasse .php:

<?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; 
} 

Und hier das Drehbuch:

<?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 
) 
*/ 
+0

Schön!Ich werde dies versuchen und Ihnen sagen, wie es geht. – leek

+1

Haben die 'uses' Direktiven innerhalb von Klassen (für Traits in PHP 5.4) und die vorhergehenden Closing Blöcke unterschiedliche Token Typen als der Namespace' use'? Wenn nicht, möchten Sie vielleicht sicherstellen, dass dieser Code diese ignoriert. – FtDRbwLXw6

+0

Guter Punkt, ich wusste, ich habe einige Fälle vergessen, ich werde bald etwas über den Code nacharbeiten. –

Verwandte Themen