Checkstyle проверка на наличие дублирующих классов
У проекта, над которым я работаю, возникли ужасные проблемы с коллизиями классов в пути к классам, и разработчики повторно используют имена классов. Например, у нас есть 16, да 16 интерфейсов, называемых константами в этой кровавой штуке, и это вызывает всевозможные проблемы.
Я хочу реализовать проверку в стиле проверки, которая будет искать различные формы дублирования классов. вот класс
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 и ищет его по различным критериям. Этот конкретный является именем класса. Он может входить в исходные папки и, что наиболее важно, он может заходить в библиотеки, содержащиеся в пути к классам, и искать файлы *.class в банке с помощью ASM. Если он находит копии на основе представленных объектов критериев, он возвращает массив файлов. Это все еще требует некоторого массажа перед мейнстримом, но у меня ограниченный бюджет времени, такой быстрый и грязный.
Моя проблема заключается в понимании входных параметров для самой проверки. Я скопировал из примера, но похоже, что CheckStyles предоставляет мне базовый объект файла IO для самого исходного файла и содержимое исходного файла в виде строкового массива.
Нужно ли запускать этот массив через другой процессор, прежде чем я смогу получить полное имя класса?
1 ответ
Это труднее сделать правильно, чем можно подумать, в основном потому, что Java поддерживает все виды вложений, такие как статические классы, определенные в интерфейсе, анонимные внутренние классы и так далее. Кроме того, вы расширяете AbstractFileSetCheck
, который не является модулем TreeWalker, поэтому вы не получите AST. Если вы хотите AST, продлите Check
вместо.
Поскольку "быстрый и грязный" вариант для вас, вы можете просто вывести имя класса из имени файла: определить канонический путь, удалить общие каталоги в начале строки, заменить косые черты точками, отрезать расширение файла, и вы более или менее там. (Конечно, без поддержки внутренних классов и т. Д.)
Лучшим решением может быть продление
Check
и зарегистрируйтесь для PACKAGE_DEF, CLASS_DEF, ANNOTATION_DEF, ENUM_DEF и INTERFACE_DEF. При проверке вы поддерживаете стек идентификаторов, найденных в этих местах, что дает вам все полные имена классов в файле.java. (Если вы хотите анонимные классы, также зарегистрируйтесь на LITERAL_NEW. Я считаю, что в вашем случае вы не хотите их.)
Последнее решение не будет работать хорошо в среде IDE, такой как Eclipse, потому что жизненный цикл проверки слишком короткий, и вы продолжите терять список полностью определенных имен классов. Однако он будет работать в системе непрерывной интеграции или в другой форме внешнего запуска. Важно, чтобы статическая ссылка на поддерживаемый вами список классов сохранялась между проверочными прогонами. Если вам нужна поддержка Eclipse, вы должны добавить что-то в свой плагин Eclipse, который может сохранить список (а также список из предыдущих полных сборок, сохраненных где-то).