Introduce -Xoutput-imports mode of JVM compiler
In this mode, instead of analyzing files and generating bytecode for them, compiler just saves imports of each file in JSON map of form '<path to file> -> [<import1>, <import2>, ...]' It is needed for some external tools, notably for Google3 toolchain.
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"))
|
||||
|
||||
+7
@@ -225,6 +225,13 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var noExceptionOnExplicitEqualsForBoxedNull by FreezableVar(false)
|
||||
|
||||
@Argument(
|
||||
value = "-Xoutput-imports",
|
||||
valueDescription = "<path>",
|
||||
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)
|
||||
|
||||
|
||||
@@ -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<K2JVMCompilerArguments>() {
|
||||
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) }
|
||||
}
|
||||
|
||||
|
||||
@@ -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<KtFile>,
|
||||
bindingTrace: BindingTrace,
|
||||
componentProvider: ComponentProvider
|
||||
): AnalysisResult? {
|
||||
val filePathToImports: MutableMap<String, List<String>> = 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)
|
||||
}
|
||||
}
|
||||
@@ -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.* { *; }
|
||||
|
||||
@@ -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.** { *; }
|
||||
|
||||
@@ -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.* { *; }
|
||||
|
||||
@@ -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.** { *; }
|
||||
|
||||
@@ -103,7 +103,7 @@ public class JVMConfigurationKeys {
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> PARAMETERS_METADATA =
|
||||
CompilerConfigurationKey.create("Parameters metadata for java 1.8 reflection");
|
||||
|
||||
|
||||
public static final CompilerConfigurationKey<IncrementalCompilationComponents> INCREMENTAL_COMPILATION_COMPONENTS =
|
||||
CompilerConfigurationKey.create("incremental cache provider");
|
||||
|
||||
@@ -137,6 +137,9 @@ public class JVMConfigurationKeys {
|
||||
public static final CompilerConfigurationKey<List<String>> ADDITIONAL_JAVA_MODULES =
|
||||
CompilerConfigurationKey.create("additional Java modules");
|
||||
|
||||
public static final CompilerConfigurationKey<String> OUTPUT_IMPORTS =
|
||||
CompilerConfigurationKey.create("output imports");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> ENABLE_JVM_DEFAULT =
|
||||
CompilerConfigurationKey.create("Allow to use '@JvmDefault'");
|
||||
}
|
||||
|
||||
+1
@@ -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=<path> Output imports from all compiled files to the specified file in JSON format
|
||||
-Xscript-resolver-environment=<key=value[,]>
|
||||
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
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
$TESTDATA_DIR$/importsProducer
|
||||
-d
|
||||
$TEMP_DIR$
|
||||
-Xoutput-imports=$TESTDATA_DIR$/importsProducerDump.txt
|
||||
@@ -0,0 +1 @@
|
||||
OK
|
||||
@@ -0,0 +1,7 @@
|
||||
package a
|
||||
|
||||
import c.JavaC
|
||||
|
||||
class A1 {
|
||||
val j: JavaC = JavaC()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package a
|
||||
|
||||
class A2 {
|
||||
val a1: A1? = null
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package b
|
||||
|
||||
import a.*
|
||||
|
||||
class B1 {
|
||||
companion object {
|
||||
val a1: A1 = A1()
|
||||
val a2: A2 = A2()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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"]}
|
||||
@@ -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");
|
||||
|
||||
@@ -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")) }) }
|
||||
|
||||
@@ -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")) }) }
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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"),
|
||||
|
||||
Reference in New Issue
Block a user