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:
Dmitry Savvinov
2018-04-04 14:59:09 +03:00
parent bec1ae3d94
commit 70622ff668
27 changed files with 167 additions and 5 deletions
+1
View File
@@ -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"))
@@ -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)
}
}