2

我正在进行的项目在类路径中存在类冲突和开发人员重用类名的可怕问题。例如,在这个该死的东西中,我们有 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 的类路径并使用各种条件搜索它。这个特定的是一个类名。它可以进入源文件夹,最重要的是它可以进入类路径中包含的库,并使用 ASM 搜索 jar 中的 *.class 文件。如果它根据显示的条件对象找到副本,它会返回一个文件数组。这仍然需要在主流之前进行一些按摩,但我在这里的时间预算如此之快和肮脏。

我的问题是了解检查本身的输入参数。我从示例中复制,但看起来 CheckStyles 为我提供了源文件本身的基本 IO 文件对象,以及字符串数组中源文件的内容。

在获得完全限定的类名之前,我是否必须通过另一个处理器运行这个数组?

4

1 回答 1

1

这比人们想象的更难做到,主要是因为 Java 支持各种嵌套,比如定义在接口中的静态类、匿名内部类等等。此外,您正在扩展AbstractFileSetCheck,这不是 TreeWalker 模块,因此您不会获得 AST。如果您想要 AST,请Check改为扩展。

  • 由于“快速而肮脏”是您的一个选项,您可以简单地从文件名中推断出类名:确定规范路径,从字符串的开头删除公共目录,用点替换斜杠,切断文件扩展名,你或多或少在那里。(当然不支持内部类等。)

  • 更好的解决方案可能是扩展Check和注册 PACKAGE_DEF、CLASS_DEF、ANNOTATION_DEF、ENUM_DEF 和 INTERFACE_DEF。在您的检查中,您维护了在这些位置找到的一组 IDENT,它为您提供了 .java 文件中的所有完全限定的类名。(如果您也想要匿名课程,也请注册 LITERAL_NEW。我相信在您的情况下您不想要这些。)

后一种解决方案在 Eclipse 之类的 IDE 中效果不佳,因为 Check 生命周期太短,并且您会不断丢失完全限定的类名列表。不过,它将在持续集成系统或其他形式的外部运行中工作。在检查运行之间保留对您正在维护的类列表的静态引用非常重要。如果您需要 Eclipse 支持,则必须在 Eclipse 插件中添加一些可以保留列表的内容(以及之前完整构建的列表,保留在某处)。

于 2013-08-23T08:26:13.843 回答