2013-08-23 4 views
2

Проект, на котором я нахожусь, вызывает ужасные проблемы с столкновением классов в пути к классам и разработчиками, повторно использующими имена классов. Например, у нас есть 16, да 16 интерфейсов, называемых Константами в этой кровавой вещи и вызывающих всевозможные проблемы.Checkstyle check for duplicate classes

Я хочу реализовать проверку 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 
     } 
    } 
} 

Ok, так что ClassScanner открывает путь к классам текущей виртуальной машины Java и ищет его с различными критериями. Это конкретное имя класса. Он может войти в исходные папки, и, самое главное, он может попасть в библиотеки, содержащиеся в пути к классам, и искать файлы * .class в банке, используя ASM. Если он находит копии на основе объектов критериев, которые представлены, он возвращает массив файлов. Это все еще требует некоторого массажа перед основным течением, но im на бюджете времени здесь так быстро и грязно.

Моя проблема заключается в понимании входных параметров для самой проверки. Я скопировал из примера, но похоже, что CheckStyles предоставляет мне базовый объект IO-файла для самого исходного файла и содержимое исходного файла в массиве строк.

Должен ли я запускать этот массив через другой процессор, прежде чем я смогу получить полное имя класса?

ответ

1

Это сложнее сделать, чем можно было бы подумать, главным образом потому, что Java поддерживает все виды вложенности, такие как статические классы, определенные в интерфейсе, анонимные внутренние классы и т. Д. Кроме того, вы распространяете AbstractFileSetCheck, который не является модулем TreeWalker, поэтому вы не получаете AST. Если вы хотите получить АСТ, вместо этого добавьте Check.

  • С «быстрой и грязной» вариантом для вас, вы можете просто вывести имя класса из имени файла: Определите канонический путь, удалить общие каталоги с начала строки, заменить косую черту с точками , отключите расширение файла, и вы более или менее там. (Не поддерживая внутренние классы и т.д., конечно.)

  • Лучшее решение могло бы быть, чтобы расширить Check и зарегистрировать PACKAGE_DEF, CLASS_DEF, ANNOTATION_DEF, ENUM_DEF и INTERFACE_DEF. В вашем чеке вы сохраняете стек IDENT, найденный в этих местах, что дает вам все полные имена классов в файле .java. (Если вы хотите   анонимные классы, тоже, также зарегистрироваться для LITERAL_NEW. Я считаю, что в вашем случае, если вы не хотите их.)

Последнее решение не будет хорошо работать в IDE как Eclipse, так как Проверьте жизненный цикл слишком короткий, и вы потеряете список полностью квалифицированных имен классов. Однако он будет работать в системе непрерывной интеграции или в другой форме внешнего запуска. Важно, чтобы статическая ссылка на список классов, который вы поддерживаете, сохраняется между прогонами проверки. Если вам нужна поддержка Eclipse, вам нужно будет добавить что-то в свой плагин Eclipse, который может сохранить список (а также список из предыдущих полных сборников, где-то сохранился).

+0

, когда вы говорите, что жизненный цикл проверки короток, что именно вы имеете в виду? Im изображая это, где каждый раз, когда класс запускает метод visitToken, он выполняет сканирование, если он находит дубликат, регистрирует его, а затем перебирает. Я не представляю, что это хранит список в память о чем угодно. Или я пропустил некоторые основы здесь. – scphantm

+0

@scphantm Ну, это было бы довольно неэффективно, поэтому оно будет работать только с очень маленькими кодовыми базами. Я думал, что вы в конечном итоге даже запускаете чек, когда кто-то нажимает * Сохранить * в редакторе исходного кода.Но если вас это не волнует, ваша проблема сводится к поиску полного имени класса. В этом случае проигнорируйте мой последний абзац. ;-) –

+0

Да, сейчас он немного выйдет из-под контроля. Мой классный сканер прочен, но очень неэффективен, как вы сказали. Я работаю над этим. Ваши комментарии поставили меня на правильный путь. Его начало падать вместе. благодаря – scphantm