diff --git a/build.gradle.kts b/build.gradle.kts index a163526af3f..ae59a2ac8d4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -132,6 +132,7 @@ extra["versions.javaslang"] = "2.0.6" extra["versions.ant"] = "1.8.2" extra["versions.android"] = "2.3.1" extra["versions.kotlinx-coroutines-core"] = "0.20" +extra["versions.kotlinx-serialization-runtime"] = "0.4.2" extra["versions.kotlinx-coroutines-jdk8"] = "0.20" extra["versions.json"] = "20160807" extra["versions.native-platform"] = "0.14" diff --git a/build.gradle.kts.182 b/build.gradle.kts.182 index ca8678db2ac..b3a29ae6b14 100644 --- a/build.gradle.kts.182 +++ b/build.gradle.kts.182 @@ -132,6 +132,7 @@ extra["versions.javaslang"] = "2.0.6" extra["versions.ant"] = "1.8.2" extra["versions.android"] = "2.3.1" extra["versions.kotlinx-coroutines-core"] = "0.20" +extra["versions.kotlinx-serialization-runtime"] = "0.4.2" extra["versions.kotlinx-coroutines-jdk8"] = "0.20" extra["versions.json"] = "20160807" extra["versions.native-platform"] = "0.14" diff --git a/compiler/cli/build.gradle.kts b/compiler/cli/build.gradle.kts index 7726ad01a5e..6406ce00252 100644 --- a/compiler/cli/build.gradle.kts +++ b/compiler/cli/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { compile(project(":js:js.translator")) compile(project(":js:js.serializer")) compile(project(":js:js.dce")) + compile(commonDep("org.jetbrains.kotlinx", "kotlinx-serialization-runtime")) { isTransitive = false } compile(commonDep("org.fusesource.jansi", "jansi")) compile(commonDep("org.jline", "jline")) compile(files("${System.getProperty("java.home")}/../lib/tools.jar")) 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 94b241ebec6..d1e1774475a 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 @@ -225,6 +225,13 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { ) var noExceptionOnExplicitEqualsForBoxedNull by FreezableVar(false) + @Argument( + value = "-Xoutput-imports", + valueDescription = "", + description = "Output imports from all compiled files to the specified file in JSON format" + ) + var outputImports: String? by FreezableVar(null) + @Argument(value = "-Xenable-jvm-default", description = "Allow to use '@JvmDefault' for JVM default method support") var enableJvmDefault: Boolean by FreezableVar(false) 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 7cebbd97956..b1b2ed60c6b 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/K2JVMCompiler.kt @@ -23,10 +23,7 @@ import org.jetbrains.kotlin.cli.common.ExitCode.* import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.messages.* import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* -import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentUtil -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler +import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoot @@ -34,6 +31,7 @@ import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser import org.jetbrains.kotlin.cli.jvm.repl.ReplFromTerminal import org.jetbrains.kotlin.codegen.CompilationException +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker @@ -378,6 +376,11 @@ class K2JVMCompiler : CLICompiler() { configuration.put(JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES, arguments.addCompilerBuiltIns) configuration.put(JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES, arguments.loadBuiltInsFromDependencies) + if (arguments.outputImports != null) { + configuration.put(JVMConfigurationKeys.OUTPUT_IMPORTS, arguments.outputImports!!) + configuration.add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, ImportsProducerComponentRegistrar()) + } + arguments.declarationsOutputPath?.let { configuration.put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ImportsProducerExtension.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ImportsProducerExtension.kt new file mode 100644 index 00000000000..2028cf890e9 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/ImportsProducerExtension.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.cli.jvm.compiler + +import com.intellij.mock.MockProject +import com.intellij.openapi.project.Project +import kotlinx.serialization.internal.StringSerializer +import kotlinx.serialization.json.JSON +import kotlinx.serialization.list +import kotlinx.serialization.map +import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.container.ComponentProvider +import org.jetbrains.kotlin.context.ProjectContext +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension +import java.io.File + +class ImportsProducerComponentRegistrar : ComponentRegistrar { + override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { + val destinationPath = configuration[JVMConfigurationKeys.OUTPUT_IMPORTS] ?: return + AnalysisHandlerExtension.registerExtension(project, ImportsProducerExtension(destinationPath)) + } +} + +class ImportsProducerExtension(destinationPath: String) : AnalysisHandlerExtension { + private val destination: File = File(destinationPath) + + override fun doAnalysis( + project: Project, + module: ModuleDescriptor, + projectContext: ProjectContext, + files: Collection, + bindingTrace: BindingTrace, + componentProvider: ComponentProvider + ): AnalysisResult? { + val filePathToImports: MutableMap> = mutableMapOf() + + for (file in files) { + filePathToImports[file.virtualFilePath] = file.importDirectives.map { it.text } + } + + val serializer = (StringSerializer to StringSerializer.list).map + + val jsonStringWithImports = JSON.stringify(serializer, filePathToImports) + + destination.writeText(jsonStringWithImports) + + return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false) + } +} \ No newline at end of file diff --git a/compiler/compiler.pro b/compiler/compiler.pro index c1b25795690..500fc1503d6 100644 --- a/compiler/compiler.pro +++ b/compiler/compiler.pro @@ -216,4 +216,7 @@ messages/**) # remove when KT-18563 would be fixed -keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; } +# for imports dumper in compiler +-keep class kotlinx.serialization.** { *; } + -keep class net.jpountz.lz4.* { *; } diff --git a/compiler/compiler.pro.172 b/compiler/compiler.pro.172 index 50e652a529a..44fcae37bc1 100644 --- a/compiler/compiler.pro.172 +++ b/compiler/compiler.pro.172 @@ -215,3 +215,6 @@ messages/**) # remove when KT-18563 would be fixed -keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; } + +# for imports dumper in compiler +-keep class kotlinx.serialization.** { *; } diff --git a/compiler/compiler.pro.182 b/compiler/compiler.pro.182 index d66e0cfb328..07730a1de22 100644 --- a/compiler/compiler.pro.182 +++ b/compiler/compiler.pro.182 @@ -223,4 +223,7 @@ messages/**) # remove when KT-18563 would be fixed -keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; } +# for imports dumper in compiler +-keep class kotlinx.serialization.** { *; } + -keep class net.jpountz.lz4.* { *; } diff --git a/compiler/compiler.pro.as32 b/compiler/compiler.pro.as32 index cecfab73b98..e7b7fbd7098 100644 --- a/compiler/compiler.pro.as32 +++ b/compiler/compiler.pro.as32 @@ -219,3 +219,6 @@ messages/**) # remove when KT-18563 would be fixed -keep class org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt { *; } + +# for imports dumper in compiler +-keep class kotlinx.serialization.** { *; } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java index 43b16583d2e..68f7e79f8a4 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -103,7 +103,7 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey PARAMETERS_METADATA = CompilerConfigurationKey.create("Parameters metadata for java 1.8 reflection"); - + public static final CompilerConfigurationKey INCREMENTAL_COMPILATION_COMPONENTS = CompilerConfigurationKey.create("incremental cache provider"); @@ -137,6 +137,9 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey> ADDITIONAL_JAVA_MODULES = CompilerConfigurationKey.create("additional Java modules"); + public static final CompilerConfigurationKey OUTPUT_IMPORTS = + CompilerConfigurationKey.create("output imports"); + public static final CompilerConfigurationKey ENABLE_JVM_DEFAULT = CompilerConfigurationKey.create("Allow to use '@JvmDefault'"); } diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index af680395050..51143a54813 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -32,6 +32,7 @@ where advanced options include: -Xno-optimize Disable optimizations -Xno-param-assertions Don't generate not-null assertions on parameters of methods accessible from Java -Xno-receiver-assertions Don't generate not-null assertion for extension receiver arguments of platform types + -Xoutput-imports= Output imports from all compiled files to the specified file in JSON format -Xscript-resolver-environment= Script resolver environment in key-value pairs (the value could be quoted and escaped) -Xsingle-module Combine modules for source files and binary dependencies into a single module diff --git a/compiler/testData/cli/jvm/importsProducer.args b/compiler/testData/cli/jvm/importsProducer.args new file mode 100644 index 00000000000..edea8c07f59 --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/importsProducer +-d +$TEMP_DIR$ +-Xoutput-imports=$TESTDATA_DIR$/importsProducerDump.txt diff --git a/compiler/testData/cli/jvm/importsProducer.out b/compiler/testData/cli/jvm/importsProducer.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer.out @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/cli/jvm/importsProducer/a/A1.kt b/compiler/testData/cli/jvm/importsProducer/a/A1.kt new file mode 100644 index 00000000000..6ad9bad949d --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer/a/A1.kt @@ -0,0 +1,7 @@ +package a + +import c.JavaC + +class A1 { + val j: JavaC = JavaC() +} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/importsProducer/a/A2.kt b/compiler/testData/cli/jvm/importsProducer/a/A2.kt new file mode 100644 index 00000000000..563518175d9 --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer/a/A2.kt @@ -0,0 +1,5 @@ +package a + +class A2 { + val a1: A1? = null +} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/importsProducer/b/B1.kt b/compiler/testData/cli/jvm/importsProducer/b/B1.kt new file mode 100644 index 00000000000..fa6a87b78c3 --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer/b/B1.kt @@ -0,0 +1,10 @@ +package b + +import a.* + +class B1 { + companion object { + val a1: A1 = A1() + val a2: A2 = A2() + } +} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/importsProducer/b/nestedB/B2.kt b/compiler/testData/cli/jvm/importsProducer/b/nestedB/B2.kt new file mode 100644 index 00000000000..7303173cb3d --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer/b/nestedB/B2.kt @@ -0,0 +1,7 @@ +package b.nestedB + +import a.A1 as AliasedA1 +import a.A1 + +fun foo(x: AliasedA1): Int = TODO() +fun bar(x: A1): Int = TODO() diff --git a/compiler/testData/cli/jvm/importsProducer/c/C1.kt b/compiler/testData/cli/jvm/importsProducer/c/C1.kt new file mode 100644 index 00000000000..8c89ed78010 --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer/c/C1.kt @@ -0,0 +1,16 @@ +package c + +import a.A1 +import a.A2 +import b.B1.Companion.a2 +import b.nestedB.bar +import b.nestedB.foo + +class C1 { + val x = foo(TODO()) + val y = bar(TODO()) + + val z: A1? = null + val t: A2? = a2 + +} \ No newline at end of file diff --git a/compiler/testData/cli/jvm/importsProducer/c/JavaC.java b/compiler/testData/cli/jvm/importsProducer/c/JavaC.java new file mode 100644 index 00000000000..2c2742b9de4 --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducer/c/JavaC.java @@ -0,0 +1,13 @@ +package c; + +import a.A1; +import b.B1; +import b.nestedB.B2Kt; + +public class JavaC { + private void doStuff() { + C1 c1 = new C1(); + B1 b1 = new B1(); + B2Kt.bar(new A1()); + } +} diff --git a/compiler/testData/cli/jvm/importsProducerDump.txt b/compiler/testData/cli/jvm/importsProducerDump.txt new file mode 100644 index 00000000000..5ebbf4c5c0c --- /dev/null +++ b/compiler/testData/cli/jvm/importsProducerDump.txt @@ -0,0 +1 @@ +{"\/home\/dsavvinov\/Repos\/kotlin-fork\/kotlin\/compiler\/testData\/cli\/jvm\/importsProducer\/a\/A1.kt":["import c.JavaC"],"\/home\/dsavvinov\/Repos\/kotlin-fork\/kotlin\/compiler\/testData\/cli\/jvm\/importsProducer\/a\/A2.kt":[],"\/home\/dsavvinov\/Repos\/kotlin-fork\/kotlin\/compiler\/testData\/cli\/jvm\/importsProducer\/b\/B1.kt":["import a.*"],"\/home\/dsavvinov\/Repos\/kotlin-fork\/kotlin\/compiler\/testData\/cli\/jvm\/importsProducer\/b\/nestedB\/B2.kt":["import a.A1 as AliasedA1","import a.A1"],"\/home\/dsavvinov\/Repos\/kotlin-fork\/kotlin\/compiler\/testData\/cli\/jvm\/importsProducer\/c\/C1.kt":["import a.A1","import a.A2","import b.B1.Companion.a2","import b.nestedB.bar","import b.nestedB.foo"]} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java index 113a36ad4d2..e60511d7448 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -221,6 +221,12 @@ public class CliTestGenerated extends AbstractCliTest { runTest("compiler/testData/cli/jvm/help.args"); } + @TestMetadata("importsProducer.args") + public void testImportsProducer() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/importsProducer.args"); + doJvmTest(fileName); + } + @TestMetadata("inlineCycle.args") public void testInlineCycle() throws Exception { runTest("compiler/testData/cli/jvm/inlineCycle.args"); diff --git a/include/kotlin-compiler/build.gradle.kts b/include/kotlin-compiler/build.gradle.kts index 23db7d5dceb..04f518a597e 100644 --- a/include/kotlin-compiler/build.gradle.kts +++ b/include/kotlin-compiler/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { fatJarContents(commonDep("com.google.code.findbugs", "jsr305")) fatJarContents(commonDep("io.javaslang", "javaslang")) fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } + fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-serialization-runtime")) { isTransitive = false } fatJarContents(intellijCoreDep()) { includeJars("intellij-core") } fatJarContents(intellijDep()) { includeIntellijCoreJarDependencies(project, { !(it.startsWith("jdom") || it.startsWith("log4j")) }) } diff --git a/include/kotlin-compiler/build.gradle.kts.173 b/include/kotlin-compiler/build.gradle.kts.173 index bf2853e497e..b463e3d322e 100644 --- a/include/kotlin-compiler/build.gradle.kts.173 +++ b/include/kotlin-compiler/build.gradle.kts.173 @@ -24,6 +24,7 @@ dependencies { fatJarContents(commonDep("com.google.code.findbugs", "jsr305")) fatJarContents(commonDep("io.javaslang", "javaslang")) fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } + fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-serialization-runtime")) { isTransitive = false } fatJarContents(intellijCoreDep()) { includeJars("intellij-core") } fatJarContents(intellijDep()) { includeIntellijCoreJarDependencies(project, { !(it.startsWith("jdom") || it.startsWith("log4j")) }) } diff --git a/prepare/compiler/build.gradle.kts b/prepare/compiler/build.gradle.kts index 4cd4e24d76c..a5c75cb8081 100644 --- a/prepare/compiler/build.gradle.kts +++ b/prepare/compiler/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { fatJarContents(commonDep("com.google.code.findbugs", "jsr305")) fatJarContents(commonDep("io.javaslang", "javaslang")) fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } + fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-serialization-runtime")) { isTransitive = false } proguardLibraryJars(files(firstFromJavaHomeThatExists("jre/lib/rt.jar", "../Classes/classes.jar"), firstFromJavaHomeThatExists("jre/lib/jsse.jar", "../Classes/jsse.jar"), diff --git a/prepare/compiler/build.gradle.kts.173 b/prepare/compiler/build.gradle.kts.173 index c86dc575fa0..edb08e4e537 100644 --- a/prepare/compiler/build.gradle.kts.173 +++ b/prepare/compiler/build.gradle.kts.173 @@ -56,6 +56,7 @@ dependencies { fatJarContents(commonDep("com.google.code.findbugs", "jsr305")) fatJarContents(commonDep("io.javaslang", "javaslang")) fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } + fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-serialization-runtime")) { isTransitive = false } proguardLibraryJars(files(firstFromJavaHomeThatExists("jre/lib/rt.jar", "../Classes/classes.jar"), firstFromJavaHomeThatExists("jre/lib/jsse.jar", "../Classes/jsse.jar"), diff --git a/prepare/compiler/build.gradle.kts.182 b/prepare/compiler/build.gradle.kts.182 index 78e2058f7ea..92577933722 100644 --- a/prepare/compiler/build.gradle.kts.182 +++ b/prepare/compiler/build.gradle.kts.182 @@ -56,6 +56,7 @@ dependencies { fatJarContents(commonDep("com.google.code.findbugs", "jsr305")) fatJarContents(commonDep("io.javaslang", "javaslang")) fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } + fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-serialization-runtime")) { isTransitive = false } proguardLibraryJars(files(firstFromJavaHomeThatExists("jre/lib/rt.jar", "../Classes/classes.jar"), firstFromJavaHomeThatExists("jre/lib/jsse.jar", "../Classes/jsse.jar"),