当前位置: 首页 > 知识库问答 >
问题:

木星测试期间未找到科特林test注释处理器生成的类

昝光临
2023-03-14

我正在为静态编程语言开发一个KSP注释处理器。代码在编译期间正确生成,我可以在输出目录中看到生成的类。现在我想通过JUnit和“com.github.tschuchortdev.KotlinCompilation”测试我的注释处理器。如果我调用编译方法,代码将被生成,我可以在Temp-Directory中看到生成的类,但如果我尝试加载类,那么我会得到一个“java.lang.ClassNotFoundException:test.pack.TestClassDslBuilder”异常。我希望代码是不言自明的。我的问题是:为什么类没有编译并且不可加载?也许komPiler的配置丢失了。

    @BeforeEach
    fun setup() {
        val kotlinSource = SourceFile.kotlin(
            "TestClass.kt", """
                package test.pack

                import yy.xxx.dsl.builder.annotation.DslBuilder
                @DslBuilder        
                class TestClass {

                }
            """
        )

        val compilation = KotlinCompilation().apply {
            sources = listOf(kotlinSource)
            symbolProcessorProviders = listOf(DslBuilderProcessorProvider())
            //workingDir =
            inheritClassPath = true
            verbose = false
            //messageOutputStream = System.out
            kspIncremental = true
        }
        compilationResult = compilation.compile()
        assertEquals(KotlinCompilation.ExitCode.OK, compilationResult.exitCode)

        // The next line leads to java.lang.ClassNotFoundException 
        compilationResult.classLoader.loadClass("test.pack.TestClassDslBuilder")
    }

共有2个答案

宰鸿博
2023-03-14

此库尚未与 KSP 完全兼容。有一个技巧可以使其与双重编译一起使用:https://github.com/tschuchortdev/kotlin-compile-testing/issues/72#issuecomment-744475289

fun compile(tempDir: File, compilation: KotlinCompilation): KotlinCompilation.Result {
    val pass1 = compilation.compile()
    require(pass1.exitCode == KotlinCompilation.ExitCode.OK) {
        "Cannot do the 1st pass \n ${pass1.messages}"
    }
    val pass2 = KotlinCompilation().apply {
        sources = compilation.kspGeneratedSourceFiles(tempDir) + compilation.sources
        inheritClassPath = true
    }.compile()
    require(pass2.exitCode == KotlinCompilation.ExitCode.OK) {
        "Cannot do the 2nd pass \n ${pass2.messages}"
    }
    return pass2
}

private fun KotlinCompilation.kspGeneratedSourceFiles(tempDir: File): List<SourceFile> =
    kspGeneratedSources(tempDir)
        .filter { it.isFile }
        .map { SourceFile.fromPath(it.absoluteFile) }
        .toList()
}

private fun kspGeneratedSources(tempDir: File): List<File> {
    val kspWorkingDir = tempDir.resolve("ksp")
    val kspGeneratedDir = kspWorkingDir.resolve("sources")
    val kotlinGeneratedDir = kspGeneratedDir.resolve("kotlin")
    val javaGeneratedDir = kspGeneratedDir.resolve("java")
    return kotlinGeneratedDir.walkTopDown().toList() +
            javaGeneratedDir.walkTopDown()
}

我可以确认它有效。这只是一个例子。当然,根据您的输出目录,您可能希望对文件路径进行一些修改。如果它仍然不起作用,请确保第二个 KotlinCompilation() 适合您的情况。

毕衡
2023-03-14

我有同样的问题。并没有修复它,但在我看来,这个问题是在生成文件的路径中(您像字符串一样编写),就像在google编译测试中一样,使用标准位置很重要。SOURCE_OUTPUT,当您尝试查找generatedFile()时。但在我的情况下,它不会生成任何东西-我是说生成的文件。在KotlinCompilation.Result中,size()==0

 类似资料:
  • 我已经编写了一个简单的注释处理器(只是为了好玩),它将生成一些我在以前的项目中编写的样板代码。它实际上通过收集活动类上的注释来生成如下所示的模块 但是,当我用dagger运行时,dagger似乎找不到我的注释处理器生成的类。虽然,类是生成的,并且存在于生成的目录中,我可以在源代码中使用它,但在编译时,dagger会产生以下异常。有什么专家建议吗? 这是主要的应用程序组件。 如果有人想做实验,这里有

  • 我试图让非空注释在NetBeans中工作,这是一个又一个令人头痛的问题。 我遵循了https://checkerframework.org/manual/#netbeans的说明,可以确认是作为编译库和处理器库添加的。我启用了注释处理,并添加了作为注释处理器。 在源代码中,我可以导入import和have注释编译。然而,在构建过程中,我发现: 我需要做什么来解决此错误?

  • 我正在尝试创建一个自定义注释,例如,确保字段或方法既是又是,如果字段或方法既不是又不是,则会生成编译时错误,如以下示例所示: 到目前为止,我已经完成了两个自定义注释接口: 和: 正如所暗示的,我不知道如何生成编译时错误。Processor的文档清楚地表明我不应该抛出异常, 如果处理器抛出未捕获的异常,该工具可能会停止其他活动注释处理器。 它接着描述了当提出错误条件时会发生什么,现在是如何提出错误条

  • 问题内容: 我正在尝试创建一个自定义批注,例如,以确保字段或方法为and ,并且如果该字段或​​方法不为and ,则将生成编译时错误,如以下示例所示: 到目前为止,我已经完成了两个自定义注释接口: 和: 如所示,我不知道如何生成编译时错误。Processor 的文档清楚地表明,我不应该抛出异常, 如果处理器抛出未捕获的异常,则该工具可能会停止其他活动的注释处理器。 它继续描述了引发错误条件时会发生

  • 我在编译使用我的注释处理器的代码时收到以下错误: 关于如何调试这个有什么提示吗?错误输出根本没有用处。有没有办法得到更详细的错误?

  • 想象一下,我尝试构建简单的依赖注入库。它的类,当在特定类上调用时,应该注入所有用注释注释的属性。 例如,给定此客户机: 调用应该会导致设置和(但不是)。让我们假设知道如何构造这些对象。 我的问题是如何编写代码来解析类的属性,检查它们的注释并在Kotlin中设置它们? 由于我使用的是Android系统,因此我尝试通过Java反射: 问题是< code>fieldAnnotations为空。将< co