2013-08-23 101 views
2

我正在使用的項目存在類路徑中的類碰撞和開發人員重用類名的可怕問題。例如,在這個血腥的事情中,我們有16個,是16個稱爲常量的接口,它會引起各種問題。Checkstyle檢查重複類

我想執行checkstyle檢查,將檢索各種形式的類重複。這裏的類

import java.io.File; 
import java.util.List; 

import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; 
import com.wps.codetools.common.classpath.ClassScanner; 
import com.wps.codetools.common.classpath.criteria.ClassNameCriteria; 
import com.wps.codetools.common.classpath.locator.ClasspathClassLocator; 

/** 
* This codestyle check is designed to scan the project for duplicate class names 
* This is being done because it is common that if a class name matches a class 
* name that is in a library, the two can be confused. Its in my best practice that 
* the class names should be unique to the project. 
* 
* 
*/ 
public class DuplicateClassNames extends AbstractFileSetCheck { 
    private int fileCount; 

    @Override 
    public void beginProcessing(String aCharset) { 
     super.beginProcessing(aCharset); 

     // reset the file count 
     this.fileCount = 0; 
    } 

    @Override 
    public void processFiltered(File file, List<String> aLines) { 
     this.fileCount++; 

     System.out.println(file.getPath()); 

     ClassScanner scanner = new ClassScanner(); 
     scanner.addClassCriteria(new ClassNameCriteria(file.getPath())); 
     scanner.addClassLocater(new ClasspathClassLocator()); 
     List<Class<?>> classes = scanner.findClasses(); 

     if (classes.size() > 0) { 
      // log the message 
      log(0, "wps.duplicate.class.name", classes.size(), classes); 
      // you can call log() multiple times to flag multiple 
      // errors in the same file 
     } 
    } 
} 

好,所以ClassScanner打開當前JVM的類路徑中,並用不同的標準搜索它。這個特殊的是一個類名。它可以進入源文件夾,最重要的是它可以進入包含在類路徑中的庫中,並使用ASM在jar中搜索* .class文件。如果它根據呈現的條件對象找到副本,則會返回這些文件的數組。這仍然需要在主流之前進行一些按摩,但是時間預算在這裏如此快速和骯髒。

我的問題是瞭解檢查本身的輸入參數。我從示例中複製,但它看起來像CheckStyles給我一個源文件本身的基本IO文件對象,以及源文件在字符串數組中的內容。

我必須通過另一個處理器運行此數組,然後才能獲得完全限定的類名稱?

回答

1

這比正常人想象的要難得多,主要是因爲Java支持各種嵌套,如接口中定義的靜態類,匿名內部類等等。另外,你正在擴展AbstractFileSetCheck,這不是一個TreeWalker模塊,所以你不會得到一個AST。如果您想要AST,請改爲Check

  • 由於「快速和骯髒」是一個選擇,你可以簡單地從文件名推斷類名:確定正確的規範路徑,從字符串的開頭刪除常見的目錄,用點替換斜線,切斷文件擴展名,你或多或少就在那裏。 (當然不支持內部類等)

  • 更好的解決方案可能是擴展Check並註冊PACKAGE_DEF,CLASS_DEF,ANNOTATION_DEF,ENUM_DEF和INTERFACE_DEF。在您的支票中,您維護了在這些位置上找到的一堆IDENT,這會在.java文件中爲您提供所有完全限定的類名稱。 (如果 你想匿名類也一樣,還註冊LITERAL_NEW。我相信,在你的情況,你不希望這些。)

後者的解決方案將不會像Eclipse的IDE很好地工作,因爲檢查生命週期太短,並且您將繼續失去完全合格的類名稱列表。不過,它將在持續集成系統或其他形式的外部運行中工作。在檢查運行之間保留對您所維護的班級列表的靜態引用是很重要的。如果你需要Eclipse支持,你必須添加一些東西到你的Eclipse插件中,以保持列表(以及之前完整版本的列表,並保存在某個地方)。

+0

當你說支票生命週期很短時,你究竟是什麼意思?我想象一下,每當類觸發visitToken方法時,它會進行掃描,如果發現重複,請記錄它,然後繼續。我沒有想象這是爲了紀念任何東西而保留一份清單。或者我在這裏錯過了一些基礎知識。 – scphantm

+0

@scphantm那麼這將是非常低效的,所以它只能用於非常小的代碼庫。我一直在想,當有人在源代碼編輯器中按* Save *時,您最終甚至會運行檢查。但是如果你不關心這個問題,那麼你的問題就會減少到找到完全合格的類名。在這種情況下,請忽略我最後一段。 ;-) –

+0

是的,目前它有點失控。我的班級掃描儀很穩定,但效率卻很低,就像你說的。我工作了出來。你的評論讓我走上正軌。它開始一起墜落。謝謝 – scphantm