diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt index 7fc0487d9e1..dfd060fc498 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt @@ -244,7 +244,11 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xdisable-standard-script", description = "Disable standard kotlin script support") var disableStandardScript: Boolean by FreezableVar(false) - // Paths to output directories for friend modules. + @Argument( + value = "-Xfriend-paths", + valueDescription = "", + description = "Paths to output directories for friend modules (whose internals should be visible)" + ) var friendPaths: Array? by FreezableVar(null) override fun configureAnalysisFlags(collector: MessageCollector): MutableMap, Any> { diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 572b02be815..756c169fd1e 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -18,6 +18,7 @@ where advanced options include: -Xdisable-default-scripting-plugin Do not enable scripting plugin by default -Xdisable-standard-script Disable standard kotlin script support + -Xfriend-paths= Paths to output directories for friend modules (whose internals should be visible) -Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade -Xmodule-path= Paths where to find Java 9+ modules -Xjavac-arguments= Java compiler arguments diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/library/a.kt new file mode 100644 index 00000000000..a7fd975a6be --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/library/a.kt @@ -0,0 +1,15 @@ +package a + +internal interface InternalInterface + +public class PublicClass { + internal fun internalMemberFun() {} + + internal companion object {} +} + +internal val internalVal = "" + +internal fun internalFun(s: String): String = s + +internal typealias InternalTypealias = InternalInterface diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/output.txt new file mode 100644 index 00000000000..f90b62b7f62 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/output.txt @@ -0,0 +1,19 @@ +compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt:3:21: error: cannot access 'InternalInterface': it is internal in 'a' +private fun test(i: InternalInterface): InternalTypealias { + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt:3:41: error: cannot access 'InternalTypealias': it is internal in 'a' +private fun test(i: InternalInterface): InternalTypealias { + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt:4:19: error: cannot access 'internalMemberFun': it is internal in 'PublicClass' + PublicClass().internalMemberFun() + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt:5:17: error: cannot access 'Companion': it is internal in 'PublicClass' + PublicClass.Companion + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt:7:5: error: cannot access 'internalFun': it is internal in 'a' + internalFun(internalVal) + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt:7:17: error: cannot access 'internalVal': it is internal in 'a' + internalFun(internalVal) + ^ +COMPILATION_ERROR diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt new file mode 100644 index 00000000000..5e872880a78 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromForeignModule/source.kt @@ -0,0 +1,10 @@ +import a.* + +private fun test(i: InternalInterface): InternalTypealias { + PublicClass().internalMemberFun() + PublicClass.Companion + + internalFun(internalVal) + + return i +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/library/a.kt new file mode 100644 index 00000000000..a7fd975a6be --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/library/a.kt @@ -0,0 +1,15 @@ +package a + +internal interface InternalInterface + +public class PublicClass { + internal fun internalMemberFun() {} + + internal companion object {} +} + +internal val internalVal = "" + +internal fun internalFun(s: String): String = s + +internal typealias InternalTypealias = InternalInterface diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/output.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/output.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/source.kt new file mode 100644 index 00000000000..5e872880a78 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/internalFromFriendModule/source.kt @@ -0,0 +1,10 @@ +import a.* + +private fun test(i: InternalInterface): InternalTypealias { + PublicClass().internalMemberFun() + PublicClass.Companion + + internalFun(internalVal) + + return i +} diff --git a/compiler/tests/org/jetbrains/kotlin/cli/FriendPathsTest.kt b/compiler/tests/org/jetbrains/kotlin/cli/FriendPathsTest.kt index 8724cb9b028..62e4512db59 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/FriendPathsTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/cli/FriendPathsTest.kt @@ -16,22 +16,11 @@ package org.jetbrains.kotlin.cli -import org.jetbrains.kotlin.cli.common.ExitCode -import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler -import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.test.CompilerTestUtil import org.jetbrains.kotlin.test.TestCaseWithTmpdir -import org.junit.Assert import java.io.File -/** - * This test checks that [org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments.friendPaths] works by invoking the compiler's - * "exec" method directly. Once there's a CLI argument for friend paths, it can be simplified to use that CLI argument instead. - */ class FriendPathsTest : TestCaseWithTmpdir() { private fun getTestDataDirectory(): File = File("compiler/testData/friendPaths/") @@ -40,7 +29,13 @@ class FriendPathsTest : TestCaseWithTmpdir() { val libDest = File(tmpdir, "lib.jar") CompilerTestUtil.executeCompilerAssertSuccessful(K2JVMCompiler(), listOf("-d", libDest.path, libSrc.path)) - Assert.assertEquals(ExitCode.OK, invokeCompiler(libDest.path)) + CompilerTestUtil.executeCompilerAssertSuccessful( + K2JVMCompiler(), + listOf( + "-d", tmpdir.path, "-cp", libDest.path, File(getTestDataDirectory(), "usage.kt").path, + "-Xfriend-paths=${libDest.path}" + ) + ) } fun testDirectory() { @@ -48,28 +43,12 @@ class FriendPathsTest : TestCaseWithTmpdir() { val libDest = File(tmpdir, "lib") CompilerTestUtil.executeCompilerAssertSuccessful(K2JVMCompiler(), listOf("-d", libDest.path, libSrc.path)) - Assert.assertEquals(ExitCode.OK, invokeCompiler(libDest.path)) - } - - private fun invokeCompiler(libraryPath: String): ExitCode { - return K2JVMCompiler().exec(ThrowingMessageCollector(), Services.EMPTY, K2JVMCompilerArguments().apply { - destination = tmpdir.path - classpath = libraryPath - freeArgs = arrayListOf(File(getTestDataDirectory(), "usage.kt").path) - - friendPaths = arrayOf(libraryPath) - }) - } - - private class ThrowingMessageCollector : MessageCollector { - override fun clear() {} - - override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) { - if (severity.isError) { - Assert.fail("${severity.presentableName}: $message at $location") - } - } - - override fun hasErrors(): Boolean = false + CompilerTestUtil.executeCompilerAssertSuccessful( + K2JVMCompiler(), + listOf( + "-d", tmpdir.path, "-cp", libDest.path, File(getTestDataDirectory(), "usage.kt").path, + "-Xfriend-paths=${libDest.path}" + ) + ) } } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index d022840a475..abc35b6ef6e 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -471,6 +471,15 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration ) } + fun testInternalFromForeignModule() { + compileKotlin("source.kt", tmpdir, listOf(compileLibrary("library"))) + } + + fun testInternalFromFriendModule() { + val library = compileLibrary("library") + compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xfriend-paths=${library.path}")) + } + companion object { // compiler before 1.1.4 version did not include suspension marks into bytecode. private fun stripSuspensionMarksToImitateLegacyCompiler(bytes: ByteArray): Pair {