From ce7d8993ffc9ec32458db57883790eb69c03d524 Mon Sep 17 00:00:00 2001 From: Matthew Gharrity Date: Thu, 13 Aug 2020 13:33:53 -0700 Subject: [PATCH 1/2] Add integration test for .srcjar support --- .../integration/smoke/srcjar/Bar.java | 5 +++ .../testData/integration/smoke/srcjar/Foo.kt | 3 ++ .../testData/integration/smoke/srcjar/Main.kt | 4 ++ .../smoke/srcjar/normal.compile.expected | 1 + .../smoke/srcjar/srcjar.compile.expected | 1 + .../kotlin/integration/CompilerSrcjarTest.kt | 42 +++++++++++++++++++ 6 files changed, 56 insertions(+) create mode 100644 compiler/testData/integration/smoke/srcjar/Bar.java create mode 100644 compiler/testData/integration/smoke/srcjar/Foo.kt create mode 100644 compiler/testData/integration/smoke/srcjar/Main.kt create mode 100644 compiler/testData/integration/smoke/srcjar/normal.compile.expected create mode 100644 compiler/testData/integration/smoke/srcjar/srcjar.compile.expected create mode 100644 compiler/tests/org/jetbrains/kotlin/integration/CompilerSrcjarTest.kt diff --git a/compiler/testData/integration/smoke/srcjar/Bar.java b/compiler/testData/integration/smoke/srcjar/Bar.java new file mode 100644 index 0000000000000..8c59bedb95c4b --- /dev/null +++ b/compiler/testData/integration/smoke/srcjar/Bar.java @@ -0,0 +1,5 @@ +public class Bar { + public static void bar() { + System.out.println("bar"); + } +} diff --git a/compiler/testData/integration/smoke/srcjar/Foo.kt b/compiler/testData/integration/smoke/srcjar/Foo.kt new file mode 100644 index 0000000000000..c2afd03b697ce --- /dev/null +++ b/compiler/testData/integration/smoke/srcjar/Foo.kt @@ -0,0 +1,3 @@ +fun foo() { + println("foo") +} diff --git a/compiler/testData/integration/smoke/srcjar/Main.kt b/compiler/testData/integration/smoke/srcjar/Main.kt new file mode 100644 index 0000000000000..9806e62fd89ce --- /dev/null +++ b/compiler/testData/integration/smoke/srcjar/Main.kt @@ -0,0 +1,4 @@ +fun main() { + foo() + Bar.bar() +} diff --git a/compiler/testData/integration/smoke/srcjar/normal.compile.expected b/compiler/testData/integration/smoke/srcjar/normal.compile.expected new file mode 100644 index 0000000000000..a14ac74940f15 --- /dev/null +++ b/compiler/testData/integration/smoke/srcjar/normal.compile.expected @@ -0,0 +1 @@ +Return code: 0 diff --git a/compiler/testData/integration/smoke/srcjar/srcjar.compile.expected b/compiler/testData/integration/smoke/srcjar/srcjar.compile.expected new file mode 100644 index 0000000000000..a14ac74940f15 --- /dev/null +++ b/compiler/testData/integration/smoke/srcjar/srcjar.compile.expected @@ -0,0 +1 @@ +Return code: 0 diff --git a/compiler/tests/org/jetbrains/kotlin/integration/CompilerSrcjarTest.kt b/compiler/tests/org/jetbrains/kotlin/integration/CompilerSrcjarTest.kt new file mode 100644 index 0000000000000..22d5014da109b --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/integration/CompilerSrcjarTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.integration + +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream + +/** + * Tests the ability to compile sources contained in .srcjar files. + * This is useful in build systems like Bazel, where .srcjar files are used to hold generated sources. + */ +class CompilerSrcjarTest : CompilerSmokeTestBase() { + fun testSrcjar() { + val tmp = KotlinTestUtils.tmpDir("CompilerSrcjarTest.testSrcjar.tmp") + val src = File(testDataDir) + + val main = File(src, "Main.kt") + val foo = File(src, "Foo.kt") + val bar = File(src, "Bar.java") + + runCompiler("normal.compile", main.absolutePath, foo.absolutePath, bar.absolutePath, "-d", tmp.absolutePath) + + val foobar = File(tmp, "FooBar.srcjar") + ZipOutputStream(foobar.outputStream().buffered()).use { srcjar -> + srcjar.addZipEntry(foo.name, foo.readBytes()) + srcjar.addZipEntry(bar.name, bar.readBytes()) + } + + runCompiler("srcjar.compile", main.absolutePath, foobar.absolutePath, "-d", tmp.absolutePath) + } + + private fun ZipOutputStream.addZipEntry(name: String, content: ByteArray) { + putNextEntry(ZipEntry(name)) + write(content) + closeEntry() + } +} From 744cd4839728fa8c8ecdee71b2f431393662198f Mon Sep 17 00:00:00 2001 From: Matthew Gharrity Date: Mon, 13 Jul 2020 20:15:53 -0700 Subject: [PATCH 2/2] Support .srcjar files as source roots --- .../jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt | 2 +- .../cli/jvm/compiler/KotlinCoreEnvironment.kt | 3 +- .../cli/jvm/compiler/coreEnvironmentUtils.kt | 29 +++++++++++++------ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt index 81a080beefd17..d6d108aa4440d 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -190,7 +190,7 @@ class K2JVMCompiler : CLICompiler() { addCommonSourceFiles(arg) } - if (File(arg).isDirectory) { + if (arg.endsWith(".srcjar") || File(arg).isDirectory) { addJavaSourceRoot(JavaRootPath(arg, args.javaPackagePrefix)) } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 2d491bb5b1f41..d780a73441cc3 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -364,7 +364,8 @@ class KotlinCoreEnvironment private constructor( is JvmModulePathRoot -> if (root.file.isFile) findJarRoot(root.file) else findExistingRoot(root, "Java module root") is JavaSourceRoot -> - findExistingRoot(root, "Java source root") + if (root.file.isFile && root.file.path.endsWith(".srcjar")) findJarRoot(root.file) + else findExistingRoot(root, "Java source root") else -> throw IllegalStateException("Unexpected root: $root") } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt index f2fbb0be7619e..681786b8898d8 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/coreEnvironmentUtils.kt @@ -8,9 +8,11 @@ package org.jetbrains.kotlin.cli.jvm.compiler import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiManager +import com.intellij.util.io.URLUtil.JAR_SEPARATOR import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation @@ -21,7 +23,6 @@ import org.jetbrains.kotlin.extensions.PreprocessedFileCreator import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource -import java.io.File fun CompilerConfiguration.report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation? = null) { get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)?.report(severity, message, location) @@ -33,8 +34,9 @@ fun createSourceFilesFromSourceRoots( sourceRoots: List, reportLocation: CompilerMessageLocation? = null ): MutableList { - val localFileSystem = VirtualFileManager.getInstance() - .getFileSystem(StandardFileSystems.FILE_PROTOCOL) + val fileManager = VirtualFileManager.getInstance() + val localFileSystem = fileManager.getFileSystem(StandardFileSystems.FILE_PROTOCOL) + val jarFileSystem = fileManager.getFileSystem(StandardFileSystems.JAR_PROTOCOL) val psiManager = PsiManager.getInstance(project) val processedFiles = hashSetOf() @@ -43,7 +45,7 @@ fun createSourceFilesFromSourceRoots( val virtualFileCreator = PreprocessedFileCreator(project) for ((sourceRootPath, isCommon) in sourceRoots) { - val vFile = localFileSystem.findFileByPath(sourceRootPath) + var vFile = localFileSystem.findFileByPath(sourceRootPath) if (vFile == null) { val message = "Source file or directory not found: $sourceRootPath" @@ -57,16 +59,24 @@ fun createSourceFilesFromSourceRoots( continue } - if (!vFile.isDirectory && vFile.fileType != KotlinFileType.INSTANCE) { + + val isFile = !vFile.isDirectory + if (isFile && vFile.path.endsWith(".srcjar")) { + vFile = jarFileSystem.findFileByPath(vFile.path + JAR_SEPARATOR) + if (vFile == null) { + configuration.report(CompilerMessageSeverity.ERROR, "Source entry is not a valid srcjar: $sourceRootPath", reportLocation) + continue + } + } else if (isFile && vFile.fileType != KotlinFileType.INSTANCE) { configuration.report(CompilerMessageSeverity.ERROR, "Source entry is not a Kotlin file: $sourceRootPath", reportLocation) continue } - for (file in File(sourceRootPath).walkTopDown()) { - if (!file.isFile) continue + VfsUtilCore.processFilesRecursively(vFile) { child -> + if (child.isDirectory) return@processFilesRecursively true - val virtualFile = localFileSystem.findFileByPath(file.absolutePath)?.let(virtualFileCreator::create) - if (virtualFile != null && processedFiles.add(virtualFile)) { + val virtualFile = virtualFileCreator.create(child) + if (processedFiles.add(virtualFile)) { val psiFile = psiManager.findFile(virtualFile) if (psiFile is KtFile) { result.add(psiFile) @@ -75,6 +85,7 @@ fun createSourceFilesFromSourceRoots( } } } + return@processFilesRecursively true } }