拼图:找不到 Kotlin 符号。

4

我有一个Java/Kotlin项目,其中包含多个子项目(模块)。这是基础模块的module-info.java

module ir.openuniverse {
    requires java.desktop;
    requires kotlin.stdlib;
    requires transitive org.apache.logging.log4j;
    requires org.apache.logging.log4j.core;

    exports ir.openuniverse;  // Base module has exported here.
}

对于消费者模块,我有:

module ir.openuniverse.watchservice {
    requires kotlin.stdlib;
    requires gson;
    requires ir.openuniverse; // Base module has imported here

    exports ir.openuniverse.watchservice;
}

现在我在消费者模块中插入了一个测试文件:
package ir.openuniverse.watchservice;

import ir.openuniverse.UtilKt;
import ir.openuniverse.JUtil;
import ir.openuniverse.Entry; 

public class Test {}

然后尝试进行编译:

> Task :watch-service:compileJava FAILED
[...]\watch-service\src\main\ir\openuniverse\watchservice\Test.java:3: error: cannot find symbol
import ir.openuniverse.UtilKt;
                      ^
  symbol:   class UtilKt
  location: package ir.openuniverse
[...]\watch-service\src\main\ir\openuniverse\watchservice\Test.java:5: error: cannot find symbol
import ir.openuniverse.Entry;
                      ^
  symbol:   class Entry
  location: package ir.openuniverse
2 errors

FAILURE: Build failed with an exception.

所有三个类(UtilKt,JUtil和Entry)都在基础模块中。但是JUtil位于Java(JUtil.java)中,另外两个类则位于Kotlin(Util.kt和Entry.kt)中。
正如您所看到的,导入JUtil没有问题,但是它们源自Kotlin的类无法解析。(如果没有导入这两个Kotlin类,我可以成功编译模块)。
此外,如果完全不使用Java 9模块系统,则也没有问题。
我使用Gradle,并测试了这两个插件:
gradle.plugin.org.gradle.java:experimental-jigsaw:0.1.1

xor:

gradle.plugin.rgoldberg:experimental-jigsaw:0.4.1-SNAPSHOT

更新1:

根据@nullpointer的评论,我试图检查classpath。这是执行任务时带有--debug选项的一部分,显示-classpath为空,而--module-path具有正确的值(特别是请注意这两个值:D:\Devel\IdeaProjects\Tinifier\base\build\classes\java\main;D:\Devel\IdeaProjects\Tinifier\base\build\classes\kotlin\main;):

05:40:29.575 [DEBUG] [org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler] Compiler arguments: -source 11 -target 11 -d D:\Devel\IdeaProjects\Tinifier\watch-service\build\classes\java\main -g -sourcepath  -proc:none -XDuseUnsharedTable=true -classpath  --module-path D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk8\1.3.10\71d0fa967493eb76648b575edf1762cb2d0c7f10\kotlin-stdlib-jdk8-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\com.google.code.gson\gson\2.8.5\f645ed69d595b24d4cf8b3fbb64cc505bede8829\gson-2.8.5.jar;D:\Devel\IdeaProjects\Tinifier\base\build\classes\java\main;D:\Devel\IdeaProjects\Tinifier\base\build\classes\kotlin\main;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-jdk7\1.3.10\4d147bf43060dc43d61b096e24da1e67dfe0c032\kotlin-stdlib-jdk7-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib\1.3.10\b178c1501609c6e4ee8be635513cb023a466457d\kotlin-stdlib-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.11.1\268f0fe4df3eefe052b57c87ec48517d64fb2a10\log4j-api-2.11.1.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlin\kotlin-stdlib-common\1.3.10\1b19d99229dcedad7caf50534dce38fe82845269\kotlin-stdlib-common-1.3.10.jar;D:\Devel\.gradle\caches\modules-2\files-2.1\org.jetbrains\annotations\13.0\919f0dfe192fb4e063e7dacadee7f8bb9a2672a9\annotations-13.0.jar;D:\Devel\IdeaProjects\Tinifier\watch-service\build\classes\kotlin\main D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\ir\openuniverse\watchservice\T.java D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\module-info.java
05:40:29.576 [INFO] [org.gradle.api.internal.tasks.compile.JdkJavaCompiler] Compiling with JDK Java compiler API.
05:40:30.138 [ERROR] [system.err] D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\ir\openuniverse\watchservice\T.java:3: error: cannot find symbol
05:40:30.139 [ERROR] [system.err] import ir.openuniverse.UtilKt;
05:40:30.139 [ERROR] [system.err]                       ^
05:40:30.139 [ERROR] [system.err]   symbol:   class UtilKt
05:40:30.139 [ERROR] [system.err]   location: package ir.openuniverse
05:40:30.142 [ERROR] [system.err] D:\Devel\IdeaProjects\Tinifier\watch-service\src\main\ir\openuniverse\watchservice\T.java:5: error: cannot find symbol
05:40:30.142 [ERROR] [system.err] import ir.openuniverse.Entry;
05:40:30.143 [ERROR] [system.err]                       ^
05:40:30.143 [ERROR] [system.err]   symbol:   class Entry
05:40:30.143 [ERROR] [system.err]   location: package ir.openuniverse
05:40:30.164 [ERROR] [system.err] 2 errors

很不幸,尽管我从上面的日志中知道了编译器参数,但我不知道如何手动编译源代码。简单地运行javac <编译器参数>是不起作用的。


更新2:

将Kotlin .class文件复制到Java .class文件的路径中解决了这个问题。请查看我的答案以获取一个简单的Gradle配置来执行此操作。但我知道这不是一个根本性的解决方案。


更新3:

我发现了一个更根本的问题!如果我从一个模块中删除所有的Java源代码(即使它不依赖于另一个模块;像我的基础模块一样),只保留Kotlin源代码,那么编译该模块时会在包含仅Kotlin源代码的包(在module-info.java中导出)处抛出异常,并说该包为空

> Task :base:compileJava FAILED
D:\Devel\IdeaProjects\Tinifier\base\src\main\module-info.java:9: error: package is empty or does not exist: ir.openuniverse
    exports ir.openuniverse;
              ^
1 error

FAILURE: Build failed with an exception.

我之前没有使用过Kotlin,但是那些Kotlin文件是否构建在与Jutil.class相同的目标(输出)文件夹下呢? - Naman
@nullpointer。是的,但不完全一样。*JUtil.classbase/build/classes/java/main/ir/openuniverse/JUtil.class中,而UtilKt.class* 在 base/build/classes/kotlin/main/ir/openuniverse/UtilKt.class中。 但在生成的jar文件(base/build/libs/base-<version>.jar)中,所有的.class文件都在同一个地方:ir/openuniverse/*.class - Mir-Ismaili
1
在这种情况下不确定,Kotlin 文件是否被处理得不同。只是猜测可能唯一的不同处理方式可能是它们的输出位置。 - Naman
1个回答

1
将 Kotlin 的 .class 文件复制到 Java 的 .class 文件路径下可解决此问题。但我知道这不是根本解决方案(请参见问题的 UPDATE 3)。您可以更改 Kotlin 编译的目标路径。在 Gradle 中:
sourceSets {
    main {
        // Optional: Removing `java` directory from output path that usually is `build/classes/java/main/`:  
        java.outputDir = file(java.outputDir.toString().replaceAll("\\${File.separatorChar}java", ""))

        // Mandatory:
        kotlin.outputDir = java.outputDir 
    }
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"

    // Unfortunately setting `main.kotlin.outputDir` isn't enough. See: https://dev59.com/1Krka4cB1Zd3GeqPb1OS#GAAloYgBc1ULPQZFZNNd and https://youtrack.jetbrains.com/issue/KT-23807
    destinationDir = sourceSets.main.kotlin.outputDir
}

compileTestKotlin {
    // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接