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, который может сохранить список (а также список из предыдущих полных сборок, сохраненных где-то).

Другие вопросы по тегам