2012-03-27 11 views
11

मैं कुछ इस तरह के लिए सब कुछ खत्म हो खोज की है निकालने, लेकिन मेरा मानना ​​है कि शब्द" का उपयोग करें "शायद भी किसी भी उपयोगी परिणाम के लिए आम है:पता लगाने के लिए सबसे आसान तरीका है/पीएचपी codebase से अप्रयुक्त `use` बयान

क्या है एक PHP कोडबेस में कक्षा फ़ाइलों से सभी un-used use कथन को हटाने का सबसे आसान तरीका?

संपादित करें: सादगी के लिए, हम एनोटेशन के लिए उपयोग किए जाने वाले use कथन का पता लगाने को अनदेखा कर सकते हैं।

+0

इस उपकरण को कैसे पता चल जाएगा जब नामस्थान का उपयोग नहीं किया जा रहा है? –

+1

वैसे आपको हर उपयोग-कथन एकत्र करने की आवश्यकता है, अपनी फाइलों को टोकननाइज़र के साथ पार्स कर सकते हैं और देखें कि यह स्थिर है या स्थिर रूप से कहा जाता है या नहीं। लेकिन इसके लिए थोड़ा सा काम करना होगा। –

+0

मैंने अपने उत्तर में कोड संपादित किया है, आपको इसे फिर से आजमाएं :)। मैंने कुछ मामलों का परीक्षण किया, और यह काम किया। मुझे उम्मीद है कि यह अब आपकी संतुष्टि के लिए है। यह केवल एक फ़ाइल के लिए काम करता है; बड़ी परियोजनाओं के लिए आपको इसे समायोजित करना चाहिए, और एक बड़ी अनुक्रमणिका बनाना चाहिए। –

उत्तर

16

चेक फैबियन पोटेनेंसर के PHP-CS-Fixer https://github.com/fabpot/PHP-CS-Fixer

+1

यह उपकरण faboo है। धन्यवाद! – yitznewton

+4

'./php-cs-fixer fix फ़ोल्डर/--fixers = unused_use' ने मेरे लिए काम किया – mrwaim

+0

'। /php-cs-fixer fix src/backend/--rules = no_unused_imports' ने मेरे लिए चाल की है – Kitze

1

यह संभवतः आपके कोड की स्थापना के तरीके पर निर्भर करेगा। यदि आपका कोड नामस्थानों का उपयोग करता है जैसे:

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

तो आप शायद ठीक हैं अगर आप प्रत्येक फ़ाइल को अलग-अलग जांचते हैं। इसका अभी भी मतलब है कि आपको उपयोग कथन खोजने के लिए PHP कोड को पार्स करना होगा, और फिर यह निर्धारित करने के लिए कि कौन से कथन का उपयोग किया जाता है।

एक उपकरण का उपयोग करना आसान तरीका है जो पहले से ही बनाया जा चुका है। मैंने हाल ही में PhpStorm IDE (30 दिन का नि: शुल्क निशान, या early access program) का उपयोग शुरू किया है और यह आपको सूचित कर सकता है जब आपने फ़ाइल में use कथन का उपयोग नहीं किया है (और आप यह भी निर्दिष्ट कर सकते हैं कि यह चेतावनियों या त्रुटियों के रूप में आना चाहिए)। हालांकि आपको अभी भी प्रत्येक फाइल को खोलने की आवश्यकता होगी। लेकिन आप उन फ़ाइलों को भी देख सकते हैं जिन्हें आप संपादित कर रहे हैं, फिर अंततः आपका कोड क्लीनर होगा।

6

संपादित

मैं पूरी तरह से इसे फिर से लिखा है, इसलिए अब यह कहीं अधिक शक्तिशाली है:

  • लक्षण और अनाम/लैम्ब्डा कार्यों पकड़ ब्लॉक के
  • देखभाल अब ले रही है अनदेखी कर रहे हैं, वर्ग एक्सटेंशन और इंटरफेस
  • इंडेंटेशन और टिप्पणियां
  • नामपा के लिए एकाधिक घोषणाएं ce उपनाम काम भी
  • स्टेटिक और वस्तु वर्ग कॉल "उपयोग" ($ यू> getUsages())
  • पूर्ण और आधा योग्य उपयोगों

परीक्षण फ़ाइल का इलाज नहीं कर रहे हैं, वर्ग के रूप में पहचाने जाते हैं .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; 
} 

और यहाँ स्क्रिप्ट:

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

अच्छा!मैं इसे एक शॉट दूंगा और आपको बता दूंगा कि यह कैसा चल रहा है। – leek

+1

कक्षाओं के अंदर 'उपयोग' निर्देश (PHP 5.4 में लक्षणों के लिए) और बंद करने वाले ब्लॉक से पहले नामस्थान 'उपयोग' की तुलना में अलग टोकन प्रकार हैं? यदि नहीं, तो आप यह सुनिश्चित करना चाहते हैं कि यह कोड उनको अनदेखा कर देगा। – FtDRbwLXw6

+0

अच्छा बिंदु, मुझे पता था, मैं कुछ मामलों को भूल गया हूं, मैं जल्द ही कोड पर थोड़ा सा काम करूंगा। –

संबंधित मुद्दे