Reformat jps-plugin module

Original commit: 455fe7fe61
This commit is contained in:
Alexey Tsvetkov
2018-03-27 16:30:07 +03:00
parent 78ee6ba693
commit d849d47e22
23 changed files with 380 additions and 335 deletions
@@ -25,30 +25,36 @@ import org.jetbrains.kotlin.load.java.NULLABLE_ANNOTATIONS
import java.util.* import java.util.*
internal class NullabilityAnnotationsTracker : AnnotationsChangeTracker() { internal class NullabilityAnnotationsTracker : AnnotationsChangeTracker() {
private val annotations = (NULLABLE_ANNOTATIONS + JAVAX_NONNULL_ANNOTATION + NOT_NULL_ANNOTATIONS).mapTo(HashSet()) { it.internalNameWithoutInnerClasses }.toTypedArray() private val annotations =
(NULLABLE_ANNOTATIONS + JAVAX_NONNULL_ANNOTATION + NOT_NULL_ANNOTATIONS).mapTo(HashSet()) { it.internalNameWithoutInnerClasses }
.toTypedArray()
override fun methodAnnotationsChanged( override fun methodAnnotationsChanged(
context: DependencyContext, context: DependencyContext,
method: MethodRepr, method: MethodRepr,
annotationsDiff: Difference.Specifier<ClassType, Difference>, annotationsDiff: Difference.Specifier<ClassType, Difference>,
paramAnnotationsDiff: Difference.Specifier<ParamAnnotation, Difference> paramAnnotationsDiff: Difference.Specifier<ParamAnnotation, Difference>
): Set<Recompile> { ): Set<Recompile> {
val changedAnnotations = annotationsDiff.addedOrRemoved() + val changedAnnotations = annotationsDiff.addedOrRemoved() +
paramAnnotationsDiff.addedOrRemoved().map { it.type } paramAnnotationsDiff.addedOrRemoved().map { it.type }
return handleNullAnnotationsChanges(context, method, changedAnnotations) return handleNullAnnotationsChanges(context, method, changedAnnotations)
} }
override fun fieldAnnotationsChanged( override fun fieldAnnotationsChanged(
context: NamingContext, context: NamingContext,
field: FieldRepr, field: FieldRepr,
annotationsDiff: Difference.Specifier<ClassType, Difference> annotationsDiff: Difference.Specifier<ClassType, Difference>
): Set<Recompile> { ): Set<Recompile> {
return handleNullAnnotationsChanges(context, field, annotationsDiff.addedOrRemoved()) return handleNullAnnotationsChanges(context, field, annotationsDiff.addedOrRemoved())
} }
private fun handleNullAnnotationsChanges(context: NamingContext, protoMember: ProtoMember, annotations: Sequence<TypeRepr.ClassType>): Set<Recompile> { private fun handleNullAnnotationsChanges(
context: NamingContext,
protoMember: ProtoMember,
annotations: Sequence<TypeRepr.ClassType>
): Set<Recompile> {
val nullabilityAnnotations = TIntHashSet(this.annotations.toIntArray { context.get(it) }) val nullabilityAnnotations = TIntHashSet(this.annotations.toIntArray { context.get(it) })
val changedNullAnnotation = annotations.firstOrNull { nullabilityAnnotations.contains(it.className) } val changedNullAnnotation = annotations.firstOrNull { nullabilityAnnotations.contains(it.className) }
@@ -66,8 +72,8 @@ internal class NullabilityAnnotationsTracker : AnnotationsChangeTracker() {
} }
private fun <T> Difference.Specifier<T, Difference>.addedOrRemoved(): Sequence<T> = private fun <T> Difference.Specifier<T, Difference>.addedOrRemoved(): Sequence<T> =
added().asSequence() + removed().asSequence() added().asSequence() + removed().asSequence()
private inline fun <T> Array<T>.toIntArray(fn: (T)->Int): IntArray = private inline fun <T> Array<T>.toIntArray(fn: (T) -> Int): IntArray =
IntArray(size) { i -> fn(get(i)) } IntArray(size) { i -> fn(get(i)) }
} }
@@ -125,5 +125,4 @@ public class CompilerRunnerUtil {
return null; return null;
} }
} }
@@ -22,11 +22,11 @@ import org.jetbrains.kotlin.preloading.ClassCondition
import org.jetbrains.kotlin.utils.KotlinPaths import org.jetbrains.kotlin.utils.KotlinPaths
class JpsCompilerEnvironment( class JpsCompilerEnvironment(
val kotlinPaths: KotlinPaths, val kotlinPaths: KotlinPaths,
services: Services, services: Services,
val classesToLoadByParent: ClassCondition, val classesToLoadByParent: ClassCondition,
messageCollector: MessageCollector, messageCollector: MessageCollector,
outputItemsCollector: OutputItemsCollectorImpl outputItemsCollector: OutputItemsCollectorImpl
) : CompilerEnvironment(services, messageCollector, outputItemsCollector) { ) : CompilerEnvironment(services, messageCollector, outputItemsCollector) {
override val outputItemsCollector: OutputItemsCollectorImpl override val outputItemsCollector: OutputItemsCollectorImpl
get() = super.outputItemsCollector as OutputItemsCollectorImpl get() = super.outputItemsCollector as OutputItemsCollectorImpl
@@ -26,17 +26,20 @@ import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import java.io.Serializable import java.io.Serializable
internal class JpsCompilerServicesFacadeImpl( internal class JpsCompilerServicesFacadeImpl(
private val env: JpsCompilerEnvironment, private val env: JpsCompilerEnvironment,
port: Int = SOCKET_ANY_FREE_PORT port: Int = SOCKET_ANY_FREE_PORT
) : CompilerCallbackServicesFacadeServer(env.services.get(IncrementalCompilationComponents::class.java), ) : CompilerCallbackServicesFacadeServer(
env.services.get(LookupTracker::class.java), env.services.get(IncrementalCompilationComponents::class.java),
env.services.get(CompilationCanceledStatus::class.java), env.services.get(LookupTracker::class.java),
port), env.services.get(CompilationCanceledStatus::class.java),
JpsCompilerServicesFacade { port
),
JpsCompilerServicesFacade {
override fun report(category: Int, severity: Int, message: String?, attachment: Serializable?) { override fun report(category: Int, severity: Int, message: String?, attachment: Serializable?) {
env.messageCollector.reportFromDaemon( env.messageCollector.reportFromDaemon(
{ outFile, srcFiles -> env.outputItemsCollector.add(srcFiles, outFile) }, { outFile, srcFiles -> env.outputItemsCollector.add(srcFiles, outFile) },
category, severity, message, attachment) category, severity, message, attachment
)
} }
} }
@@ -39,13 +39,12 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
private var compilerSettings: CompilerSettings? = null private var compilerSettings: CompilerSettings? = null
private inline fun withCompilerSettings(settings: CompilerSettings, fn: ()->Unit) { private inline fun withCompilerSettings(settings: CompilerSettings, fn: () -> Unit) {
val old = compilerSettings val old = compilerSettings
try { try {
compilerSettings = settings compilerSettings = settings
fn() fn()
} } finally {
finally {
compilerSettings = old compilerSettings = old
} }
} }
@@ -55,14 +54,14 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
private var _jpsCompileServiceSession: CompileServiceSession? = null private var _jpsCompileServiceSession: CompileServiceSession? = null
@Synchronized @Synchronized
private fun getOrCreateDaemonConnection(newConnection: ()-> CompileServiceSession?): CompileServiceSession? { private fun getOrCreateDaemonConnection(newConnection: () -> CompileServiceSession?): CompileServiceSession? {
// TODO: consider adding state "ping" to the daemon interface // TODO: consider adding state "ping" to the daemon interface
if (_jpsCompileServiceSession == null || _jpsCompileServiceSession!!.compileService.getDaemonOptions() !is CompileService.CallResult.Good<DaemonOptions>) { if (_jpsCompileServiceSession == null || _jpsCompileServiceSession!!.compileService.getDaemonOptions() !is CompileService.CallResult.Good<DaemonOptions>) {
_jpsCompileServiceSession?. let { _jpsCompileServiceSession?.let {
try { try {
it.compileService.releaseCompileSession(it.sessionId) it.compileService.releaseCompileSession(it.sessionId)
} catch (_: Throwable) {
} }
catch (_: Throwable) {}
} }
_jpsCompileServiceSession = newConnection() _jpsCompileServiceSession = newConnection()
} }
@@ -74,11 +73,11 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
} }
fun runK2JvmCompiler( fun runK2JvmCompiler(
commonArguments: CommonCompilerArguments, commonArguments: CommonCompilerArguments,
k2jvmArguments: K2JVMCompilerArguments, k2jvmArguments: K2JVMCompilerArguments,
compilerSettings: CompilerSettings, compilerSettings: CompilerSettings,
environment: JpsCompilerEnvironment, environment: JpsCompilerEnvironment,
moduleFile: File moduleFile: File
) { ) {
val arguments = mergeBeans(commonArguments, XmlSerializerUtil.createCopy(k2jvmArguments)) val arguments = mergeBeans(commonArguments, XmlSerializerUtil.createCopy(k2jvmArguments))
setupK2JvmArguments(moduleFile, arguments) setupK2JvmArguments(moduleFile, arguments)
@@ -88,15 +87,15 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
} }
fun runK2JsCompiler( fun runK2JsCompiler(
commonArguments: CommonCompilerArguments, commonArguments: CommonCompilerArguments,
k2jsArguments: K2JSCompilerArguments, k2jsArguments: K2JSCompilerArguments,
compilerSettings: CompilerSettings, compilerSettings: CompilerSettings,
environment: JpsCompilerEnvironment, environment: JpsCompilerEnvironment,
sourceFiles: Collection<File>, sourceFiles: Collection<File>,
sourceRoots: Collection<File>, sourceRoots: Collection<File>,
libraries: List<String>, libraries: List<String>,
friendModules: List<String>, friendModules: List<String>,
outputFile: File outputFile: File
) { ) {
log.debug("K2JS: common arguments: " + ArgumentUtils.convertArgumentsToStringList(commonArguments)) log.debug("K2JS: common arguments: " + ArgumentUtils.convertArgumentsToStringList(commonArguments))
log.debug("K2JS: JS arguments: " + ArgumentUtils.convertArgumentsToStringList(k2jsArguments)) log.debug("K2JS: JS arguments: " + ArgumentUtils.convertArgumentsToStringList(k2jsArguments))
@@ -117,25 +116,24 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
} }
override fun compileWithDaemonOrFallback( override fun compileWithDaemonOrFallback(
compilerClassName: String, compilerClassName: String,
compilerArgs: CommonCompilerArguments, compilerArgs: CommonCompilerArguments,
environment: JpsCompilerEnvironment environment: JpsCompilerEnvironment
): ExitCode { ): ExitCode {
log.debug("Using kotlin-home = " + environment.kotlinPaths.homePath) log.debug("Using kotlin-home = " + environment.kotlinPaths.homePath)
return if (isDaemonEnabled()) { return if (isDaemonEnabled()) {
val daemonExitCode = compileWithDaemon(compilerClassName, compilerArgs, environment) val daemonExitCode = compileWithDaemon(compilerClassName, compilerArgs, environment)
daemonExitCode ?: fallbackCompileStrategy(compilerArgs, compilerClassName, environment) daemonExitCode ?: fallbackCompileStrategy(compilerArgs, compilerClassName, environment)
} } else {
else {
fallbackCompileStrategy(compilerArgs, compilerClassName, environment) fallbackCompileStrategy(compilerArgs, compilerClassName, environment)
} }
} }
override fun compileWithDaemon( override fun compileWithDaemon(
compilerClassName: String, compilerClassName: String,
compilerArgs: CommonCompilerArguments, compilerArgs: CommonCompilerArguments,
environment: JpsCompilerEnvironment environment: JpsCompilerEnvironment
): ExitCode? { ): ExitCode? {
val targetPlatform = when (compilerClassName) { val targetPlatform = when (compilerClassName) {
K2JVM_COMPILER -> CompileService.TargetPlatform.JVM K2JVM_COMPILER -> CompileService.TargetPlatform.JVM
@@ -154,15 +152,22 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
val (daemon, sessionId) = connection val (daemon, sessionId) = connection
val compilerMode = CompilerMode.JPS_COMPILER val compilerMode = CompilerMode.JPS_COMPILER
val verbose = compilerArgs.verbose val verbose = compilerArgs.verbose
val options = CompilationOptions(compilerMode, targetPlatform, reportCategories(verbose), reportSeverity(verbose), requestedCompilationResults = emptyArray()) val options = CompilationOptions(
val res = daemon.compile(sessionId, withAdditionalCompilerArgs(compilerArgs), options, JpsCompilerServicesFacadeImpl(environment), null) compilerMode,
targetPlatform,
reportCategories(verbose),
reportSeverity(verbose),
requestedCompilationResults = emptyArray()
)
val res =
daemon.compile(sessionId, withAdditionalCompilerArgs(compilerArgs), options, JpsCompilerServicesFacadeImpl(environment), null)
// TODO: consider implementing connection retry, instead of fallback here // TODO: consider implementing connection retry, instead of fallback here
return res.takeUnless { it is CompileService.CallResult.Dying }?.let { exitCodeFromProcessExitCode(it.get()) } return res.takeUnless { it is CompileService.CallResult.Dying }?.let { exitCodeFromProcessExitCode(it.get()) }
} }
private fun withAdditionalCompilerArgs(compilerArgs: CommonCompilerArguments): Array<String> { private fun withAdditionalCompilerArgs(compilerArgs: CommonCompilerArguments): Array<String> {
val allArgs = ArgumentUtils.convertArgumentsToStringList(compilerArgs) + val allArgs = ArgumentUtils.convertArgumentsToStringList(compilerArgs) +
(compilerSettings?.additionalArgumentsAsList ?: emptyList()) (compilerSettings?.additionalArgumentsAsList ?: emptyList())
return allArgs.toTypedArray() return allArgs.toTypedArray()
} }
@@ -170,8 +175,7 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
val categories = val categories =
if (!verbose) { if (!verbose) {
arrayOf(ReportCategory.COMPILER_MESSAGE, ReportCategory.EXCEPTION) arrayOf(ReportCategory.COMPILER_MESSAGE, ReportCategory.EXCEPTION)
} } else {
else {
ReportCategory.values() ReportCategory.values()
} }
@@ -180,17 +184,16 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
private fun reportSeverity(verbose: Boolean): Int = private fun reportSeverity(verbose: Boolean): Int =
if (!verbose) { if (!verbose) {
ReportSeverity.INFO.code ReportSeverity.INFO.code
} } else {
else { ReportSeverity.DEBUG.code
ReportSeverity.DEBUG.code }
}
private fun fallbackCompileStrategy( private fun fallbackCompileStrategy(
compilerArgs: CommonCompilerArguments, compilerArgs: CommonCompilerArguments,
compilerClassName: String, compilerClassName: String,
environment: JpsCompilerEnvironment environment: JpsCompilerEnvironment
): ExitCode { ): ExitCode {
if ("true" == System.getProperty("kotlin.jps.tests") && "true" == System.getProperty(FAIL_ON_FALLBACK_PROPERTY)) { if ("true" == System.getProperty("kotlin.jps.tests") && "true" == System.getProperty(FAIL_ON_FALLBACK_PROPERTY)) {
error("Fallback strategy is disabled in tests!") error("Fallback strategy is disabled in tests!")
@@ -227,7 +230,13 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
} }
} }
private fun setupK2JsArguments(_outputFile: File, sourceFiles: Collection<File>, _libraries: List<String>, _friendModules: List<String>, settings: K2JSCompilerArguments) { private fun setupK2JsArguments(
_outputFile: File,
sourceFiles: Collection<File>,
_libraries: List<String>,
_friendModules: List<String>,
settings: K2JSCompilerArguments
) {
with(settings) { with(settings) {
noStdlib = true noStdlib = true
freeArgs = sourceFiles.map { it.path }.toMutableList() freeArgs = sourceFiles.map { it.path }.toMutableList()
@@ -245,15 +254,15 @@ class JpsKotlinCompilerRunner : KotlinCompilerRunner<JpsCompilerEnvironment>() {
} }
override fun getDaemonConnection(environment: JpsCompilerEnvironment): CompileServiceSession? = override fun getDaemonConnection(environment: JpsCompilerEnvironment): CompileServiceSession? =
getOrCreateDaemonConnection { getOrCreateDaemonConnection {
val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, environment.messageCollector) val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, environment.messageCollector)
val compilerPath = File(libPath, "kotlin-compiler.jar") val compilerPath = File(libPath, "kotlin-compiler.jar")
val toolsJarPath = CompilerRunnerUtil.getJdkToolsJar() val toolsJarPath = CompilerRunnerUtil.getJdkToolsJar()
val compilerId = CompilerId.makeCompilerId(listOfNotNull(compilerPath, toolsJarPath) ) val compilerId = CompilerId.makeCompilerId(listOfNotNull(compilerPath, toolsJarPath))
val daemonOptions = configureDaemonOptions() val daemonOptions = configureDaemonOptions()
val clientFlagFile = KotlinCompilerClient.getOrCreateClientFlagFile(daemonOptions) val clientFlagFile = KotlinCompilerClient.getOrCreateClientFlagFile(daemonOptions)
val sessionFlagFile = makeAutodeletingFlagFile("compiler-jps-session-", File(daemonOptions.runFilesPathOrDefault)) val sessionFlagFile = makeAutodeletingFlagFile("compiler-jps-session-", File(daemonOptions.runFilesPathOrDefault))
newDaemonConnection(compilerId, clientFlagFile, sessionFlagFile, environment, daemonOptions) newDaemonConnection(compilerId, clientFlagFile, sessionFlagFile, environment, daemonOptions)
} }
} }
@@ -69,9 +69,9 @@ class JpsKotlinCompilerSettings : JpsElementBase<JpsKotlinCompilerSettings>() {
val facetArguments = facetSettings.compilerArguments ?: return defaultArguments val facetArguments = facetSettings.compilerArguments ?: return defaultArguments
return copyBean(facetArguments).apply { return copyBean(facetArguments).apply {
multiPlatform = module multiPlatform = module
.dependenciesList .dependenciesList
.dependencies .dependencies
.any { (it as? JpsModuleDependency)?.module?.targetPlatform == TargetPlatformKind.Common } .any { (it as? JpsModuleDependency)?.module?.targetPlatform == TargetPlatformKind.Common }
} }
} }
@@ -30,9 +30,9 @@ import java.io.File
import java.util.HashMap import java.util.HashMap
class FSOperationsHelper( class FSOperationsHelper(
private val compileContext: CompileContext, private val compileContext: CompileContext,
private val chunk: ModuleChunk, private val chunk: ModuleChunk,
private val log: Logger private val log: Logger
) { ) {
private val moduleBasedFilter = ModulesBasedFileFilter(compileContext, chunk) private val moduleBasedFilter = ModulesBasedFileFilter(compileContext, chunk)
@@ -53,8 +53,7 @@ class FSOperationsHelper(
if (recursively) { if (recursively) {
FSOperations.markDirtyRecursively(compileContext, CompilationRound.NEXT, chunk, ::shouldMark) FSOperations.markDirtyRecursively(compileContext, CompilationRound.NEXT, chunk, ::shouldMark)
} } else {
else {
FSOperations.markDirty(compileContext, CompilationRound.NEXT, chunk, ::shouldMark) FSOperations.markDirty(compileContext, CompilationRound.NEXT, chunk, ::shouldMark)
} }
} }
@@ -67,7 +66,7 @@ class FSOperationsHelper(
markFilesImpl(files) { it !in excludeFiles && it.exists() && moduleBasedFilter.accept(it) } markFilesImpl(files) { it !in excludeFiles && it.exists() && moduleBasedFilter.accept(it) }
} }
private inline fun markFilesImpl(files: Iterable<File>, shouldMark: (File)->Boolean) { private inline fun markFilesImpl(files: Iterable<File>, shouldMark: (File) -> Boolean) {
val filesToMark = files.filterTo(HashSet(), shouldMark) val filesToMark = files.filterTo(HashSet(), shouldMark)
if (filesToMark.isEmpty()) return if (filesToMark.isEmpty()) return
@@ -83,9 +82,9 @@ class FSOperationsHelper(
// Based on `JavaBuilderUtil#ModulesBasedFileFilter` from Intellij // Based on `JavaBuilderUtil#ModulesBasedFileFilter` from Intellij
private class ModulesBasedFileFilter( private class ModulesBasedFileFilter(
private val context: CompileContext, private val context: CompileContext,
chunk: ModuleChunk chunk: ModuleChunk
): Mappings.DependentFilesFilter { ) : Mappings.DependentFilesFilter {
private val chunkTargets = chunk.targets private val chunkTargets = chunk.targets
private val buildRootIndex = context.projectDescriptor.buildRootIndex private val buildRootIndex = context.projectDescriptor.buildRootIndex
private val buildTargetIndex = context.projectDescriptor.buildTargetIndex private val buildTargetIndex = context.projectDescriptor.buildTargetIndex
@@ -70,24 +70,25 @@ object JpsJsModuleUtils {
@JvmStatic @JvmStatic
fun getOutputMetaFile(module: JpsModule, isTests: Boolean): File { fun getOutputMetaFile(module: JpsModule, isTests: Boolean): File {
val moduleBuildTarget = ModuleBuildTarget(module, if (isTests) JavaModuleBuildTargetType.TEST else JavaModuleBuildTargetType.PRODUCTION) val moduleBuildTarget =
ModuleBuildTarget(module, if (isTests) JavaModuleBuildTargetType.TEST else JavaModuleBuildTargetType.PRODUCTION)
val outputDir = KotlinBuilderModuleScriptGenerator.getOutputDirSafe(moduleBuildTarget) val outputDir = KotlinBuilderModuleScriptGenerator.getOutputDirSafe(moduleBuildTarget)
return getOutputMetaFile(outputDir, module.name, isTests) return getOutputMetaFile(outputDir, module.name, isTests)
} }
@JvmStatic @JvmStatic
fun getOutputFile(outputDir: File, moduleName: String, isTests: Boolean) fun getOutputFile(outputDir: File, moduleName: String, isTests: Boolean) =
= File(outputDir, moduleName + suffix(isTests) + KotlinJavascriptMetadataUtils.JS_EXT) File(outputDir, moduleName + suffix(isTests) + KotlinJavascriptMetadataUtils.JS_EXT)
@JvmStatic @JvmStatic
fun getOutputMetaFile(outputDir: File, moduleName: String, isTests: Boolean) fun getOutputMetaFile(outputDir: File, moduleName: String, isTests: Boolean) =
= File(outputDir, moduleName + suffix(isTests) + KotlinJavascriptMetadataUtils.META_JS_SUFFIX) File(outputDir, moduleName + suffix(isTests) + KotlinJavascriptMetadataUtils.META_JS_SUFFIX)
private fun suffix(isTests: Boolean) = if (isTests) "_test" else "" private fun suffix(isTests: Boolean) = if (isTests) "_test" else ""
} }
val JpsModule.hasProductionSourceRoot val JpsModule.hasProductionSourceRoot
get() = sourceRoots.any { it.rootType == JavaSourceRootType.SOURCE} get() = sourceRoots.any { it.rootType == JavaSourceRootType.SOURCE }
val JpsModule.hasTestSourceRoot val JpsModule.hasTestSourceRoot
get() = sourceRoots.any { it.rootType == JavaSourceRootType.TEST_SOURCE} get() = sourceRoots.any { it.rootType == JavaSourceRootType.TEST_SOURCE }
@@ -37,7 +37,9 @@ import java.util.concurrent.ConcurrentHashMap;
class JpsUtils { class JpsUtils {
private static final Map<ModuleBuildTarget, Boolean> IS_KOTLIN_JS_MODULE_CACHE = new ConcurrentHashMap<ModuleBuildTarget, Boolean>(); private static final Map<ModuleBuildTarget, Boolean> IS_KOTLIN_JS_MODULE_CACHE = new ConcurrentHashMap<ModuleBuildTarget, Boolean>();
private static final Map<String, Boolean> IS_KOTLIN_JS_STDLIB_JAR_CACHE = new ConcurrentHashMap<String, Boolean>(); private static final Map<String, Boolean> IS_KOTLIN_JS_STDLIB_JAR_CACHE = new ConcurrentHashMap<String, Boolean>();
private JpsUtils() {}
private JpsUtils() {
}
@NotNull @NotNull
static JpsJavaDependenciesEnumerator getAllDependencies(@NotNull ModuleBuildTarget target) { static JpsJavaDependenciesEnumerator getAllDependencies(@NotNull ModuleBuildTarget target) {
@@ -66,8 +68,12 @@ class JpsUtils {
Boolean cachedValue = IS_KOTLIN_JS_STDLIB_JAR_CACHE.get(url); Boolean cachedValue = IS_KOTLIN_JS_STDLIB_JAR_CACHE.get(url);
if (cachedValue != null) { if (cachedValue != null) {
if (cachedValue.booleanValue()) return true; if (cachedValue.booleanValue()) {
else continue; return true;
}
else {
continue;
}
} }
boolean isKotlinJavascriptStdLibrary = LibraryUtils.isKotlinJavascriptStdLibrary(JpsPathUtil.urlToFile(url)); boolean isKotlinJavascriptStdLibrary = LibraryUtils.isKotlinJavascriptStdLibrary(JpsPathUtil.urlToFile(url));
@@ -29,7 +29,6 @@ import org.jetbrains.jps.builders.java.JavaBuilderUtil
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.incremental.* import org.jetbrains.jps.incremental.*
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.* import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.*
import org.jetbrains.jps.incremental.fs.CompilationRound
import org.jetbrains.jps.incremental.java.JavaBuilder import org.jetbrains.jps.incremental.java.JavaBuilder
import org.jetbrains.jps.incremental.messages.BuildMessage import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.CompilerMessage import org.jetbrains.jps.incremental.messages.CompilerMessage
@@ -70,10 +69,11 @@ import java.io.File
import java.io.IOException import java.io.IOException
import java.net.URI import java.net.URI
import java.util.* import java.util.*
import kotlin.collections.HashSet
class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
companion object { companion object {
@JvmField val KOTLIN_BUILDER_NAME: String = "Kotlin Builder" const val KOTLIN_BUILDER_NAME: String = "Kotlin Builder"
val LOG = Logger.getInstance("#org.jetbrains.kotlin.jps.build.KotlinBuilder") val LOG = Logger.getInstance("#org.jetbrains.kotlin.jps.build.KotlinBuilder")
const val JVM_BUILD_META_INFO_FILE_NAME = "jvm-build-meta-info.txt" const val JVM_BUILD_META_INFO_FILE_NAME = "jvm-build-meta-info.txt"
@@ -83,14 +83,14 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val classesToLoadByParent: ClassCondition val classesToLoadByParent: ClassCondition
get() = ClassCondition { className -> get() = ClassCondition { className ->
className.startsWith("org.jetbrains.kotlin.load.kotlin.incremental.components.") className.startsWith("org.jetbrains.kotlin.load.kotlin.incremental.components.")
|| className.startsWith("org.jetbrains.kotlin.incremental.components.") || className.startsWith("org.jetbrains.kotlin.incremental.components.")
|| className.startsWith("org.jetbrains.kotlin.incremental.js") || className.startsWith("org.jetbrains.kotlin.incremental.js")
|| className == "org.jetbrains.kotlin.config.Services" || className == "org.jetbrains.kotlin.config.Services"
|| className.startsWith("org.apache.log4j.") // For logging from compiler || className.startsWith("org.apache.log4j.") // For logging from compiler
|| className == "org.jetbrains.kotlin.progress.CompilationCanceledStatus" || className == "org.jetbrains.kotlin.progress.CompilationCanceledStatus"
|| className == "org.jetbrains.kotlin.progress.CompilationCanceledException" || className == "org.jetbrains.kotlin.progress.CompilationCanceledException"
|| className == "org.jetbrains.kotlin.modules.TargetId" || className == "org.jetbrains.kotlin.modules.TargetId"
|| className == "org.jetbrains.kotlin.cli.common.ExitCode" || className == "org.jetbrains.kotlin.cli.common.ExitCode"
} }
} }
@@ -174,18 +174,19 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
if (!file.exists()) continue if (!file.exists()) continue
val lastBuildMetaInfo = val lastBuildMetaInfo =
try { try {
JvmBuildMetaInfo.deserializeFromString(file.readText()) ?: continue JvmBuildMetaInfo.deserializeFromString(file.readText()) ?: continue
} } catch (e: Exception) {
catch (e: Exception) { LOG.error("Could not deserialize jvm build meta info", e)
LOG.error("Could not deserialize jvm build meta info", e) continue
continue }
}
val lastBuildLangVersion = LanguageVersion.fromVersionString(lastBuildMetaInfo.languageVersionString) val lastBuildLangVersion = LanguageVersion.fromVersionString(lastBuildMetaInfo.languageVersionString)
val lastBuildApiVersion = ApiVersion.parse(lastBuildMetaInfo.apiVersionString) val lastBuildApiVersion = ApiVersion.parse(lastBuildMetaInfo.apiVersionString)
val currentLangVersion = args.languageVersion?.let { LanguageVersion.fromVersionString(it) } ?: LanguageVersion.LATEST_STABLE val currentLangVersion =
val currentApiVersion = args.apiVersion?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(currentLangVersion) args.languageVersion?.let { LanguageVersion.fromVersionString(it) } ?: LanguageVersion.LATEST_STABLE
val currentApiVersion =
args.apiVersion?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(currentLangVersion)
val reasonToRebuild = when { val reasonToRebuild = when {
currentLangVersion != lastBuildLangVersion -> { currentLangVersion != lastBuildLangVersion -> {
@@ -220,10 +221,10 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
override fun build( override fun build(
context: CompileContext, context: CompileContext,
chunk: ModuleChunk, chunk: ModuleChunk,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
outputConsumer: ModuleLevelBuilder.OutputConsumer outputConsumer: ModuleLevelBuilder.OutputConsumer
): ModuleLevelBuilder.ExitCode { ): ModuleLevelBuilder.ExitCode {
if (chunk.isDummy(context)) return NOTHING_DONE if (chunk.isDummy(context)) return NOTHING_DONE
@@ -235,30 +236,28 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val actualExitCode = if (proposedExitCode == OK && fsOperations.hasMarkedDirty) ADDITIONAL_PASS_REQUIRED else proposedExitCode val actualExitCode = if (proposedExitCode == OK && fsOperations.hasMarkedDirty) ADDITIONAL_PASS_REQUIRED else proposedExitCode
LOG.debug("Build result: " + actualExitCode) LOG.debug("Build result: $actualExitCode")
context.testingContext?.buildLogger?.buildFinished(actualExitCode) context.testingContext?.buildLogger?.buildFinished(actualExitCode)
return actualExitCode return actualExitCode
} } catch (e: StopBuildException) {
catch (e: StopBuildException) { LOG.info("Caught exception: $e")
LOG.info("Caught exception: " + e)
throw e throw e
} } catch (e: Throwable) {
catch (e: Throwable) { LOG.info("Caught exception: $e")
LOG.info("Caught exception: " + e)
MessageCollectorUtil.reportException(messageCollector, e) MessageCollectorUtil.reportException(messageCollector, e)
return ABORT return ABORT
} }
} }
private fun doBuild( private fun doBuild(
chunk: ModuleChunk, chunk: ModuleChunk,
context: CompileContext, context: CompileContext,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
messageCollector: MessageCollectorAdapter, messageCollector: MessageCollectorAdapter,
outputConsumer: OutputConsumer, outputConsumer: OutputConsumer,
fsOperations: FSOperationsHelper fsOperations: FSOperationsHelper
): ModuleLevelBuilder.ExitCode { ): ModuleLevelBuilder.ExitCode {
// Workaround for Android Studio // Workaround for Android Studio
if (!JavaBuilder.IS_ENABLED[context, true] && !JpsUtils.isJsKotlinModule(chunk.representativeTarget())) { if (!JavaBuilder.IS_ENABLED[context, true] && !JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
@@ -272,15 +271,14 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val hasKotlin = HasKotlinMarker(dataManager) val hasKotlin = HasKotlinMarker(dataManager)
val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager) val rebuildAfterCacheVersionChanged = RebuildAfterCacheVersionChangeMarker(dataManager)
val isChunkRebuilding = JavaBuilderUtil.isForcedRecompilationAllJavaModules(context) val isChunkRebuilding = JavaBuilderUtil.isForcedRecompilationAllJavaModules(context)
|| targets.any { rebuildAfterCacheVersionChanged[it] == true } || targets.any { rebuildAfterCacheVersionChanged[it] == true }
if (hasKotlinDirtyOrRemovedFiles(dirtyFilesHolder, chunk)) { if (hasKotlinDirtyOrRemovedFiles(dirtyFilesHolder, chunk)) {
if (!isChunkRebuilding && !IncrementalCompilation.isEnabled()) { if (!isChunkRebuilding && !IncrementalCompilation.isEnabled()) {
targets.forEach { rebuildAfterCacheVersionChanged[it] = true } targets.forEach { rebuildAfterCacheVersionChanged[it] = true }
return CHUNK_REBUILD_REQUIRED return CHUNK_REBUILD_REQUIRED
} }
} } else {
else {
if (isChunkRebuilding) { if (isChunkRebuilding) {
targets.forEach { hasKotlin[it] = false } targets.forEach { hasKotlin[it] = false }
} }
@@ -311,8 +309,10 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
LOG.debug("Compiling files: ${filesToCompile.values()}") LOG.debug("Compiling files: ${filesToCompile.values()}")
val start = System.nanoTime() val start = System.nanoTime()
val outputItemCollector = doCompileModuleChunk(allCompiledFiles, chunk, commonArguments, context, dirtyFilesHolder, val outputItemCollector = doCompileModuleChunk(
environment, filesToCompile, incrementalCaches, project) allCompiledFiles, chunk, commonArguments, context, dirtyFilesHolder,
environment, filesToCompile, incrementalCaches, project
)
statisticsLogger.registerStatistic(chunk, System.nanoTime() - start) statisticsLogger.registerStatistic(chunk, System.nanoTime() - start)
@@ -324,8 +324,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
if (compilationErrors) { if (compilationErrors) {
LOG.info("Compiled with errors") LOG.info("Compiled with errors")
return ABORT return ABORT
} } else {
else {
LOG.info("Compiled successfully") LOG.info("Compiled successfully")
} }
@@ -372,12 +371,12 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
private fun applyActionsOnCacheVersionChange( private fun applyActionsOnCacheVersionChange(
actions: Set<CacheVersion.Action>, actions: Set<CacheVersion.Action>,
cacheVersionsProvider: CacheVersionProvider, cacheVersionsProvider: CacheVersionProvider,
context: CompileContext, context: CompileContext,
dataManager: BuildDataManager, dataManager: BuildDataManager,
targets: MutableSet<ModuleBuildTarget>, targets: MutableSet<ModuleBuildTarget>,
fsOperations: FSOperationsHelper fsOperations: FSOperationsHelper
) { ) {
val hasKotlin = HasKotlinMarker(dataManager) val hasKotlin = HasKotlinMarker(dataManager)
val sortedActions = actions.sorted() val sortedActions = actions.sorted()
@@ -463,13 +462,13 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
private fun compilerArgumentsForChunk(chunk: ModuleChunk): CommonCompilerArguments = private fun compilerArgumentsForChunk(chunk: ModuleChunk): CommonCompilerArguments =
JpsKotlinCompilerSettings.getCommonCompilerArguments(chunk.representativeTarget().module) JpsKotlinCompilerSettings.getCommonCompilerArguments(chunk.representativeTarget().module)
private fun doCompileModuleChunk( private fun doCompileModuleChunk(
allCompiledFiles: MutableSet<File>, chunk: ModuleChunk, commonArguments: CommonCompilerArguments, context: CompileContext, allCompiledFiles: MutableSet<File>, chunk: ModuleChunk, commonArguments: CommonCompilerArguments, context: CompileContext,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, environment: JpsCompilerEnvironment, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, environment: JpsCompilerEnvironment,
filesToCompile: MultiMap<ModuleBuildTarget, File>, incrementalCaches: Map<ModuleBuildTarget, IncrementalJvmCache>, filesToCompile: MultiMap<ModuleBuildTarget, File>, incrementalCaches: Map<ModuleBuildTarget, IncrementalJvmCache>,
project: JpsProject project: JpsProject
): OutputItemsCollector? { ): OutputItemsCollector? {
val representativeTarget = chunk.representativeTarget() val representativeTarget = chunk.representativeTarget()
@@ -478,11 +477,15 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
for (argumentProvider in ServiceLoader.load(KotlinJpsCompilerArgumentsProvider::class.java)) { for (argumentProvider in ServiceLoader.load(KotlinJpsCompilerArgumentsProvider::class.java)) {
// appending to pluginOptions // appending to pluginOptions
commonArguments.pluginOptions = concatenate(commonArguments.pluginOptions, commonArguments.pluginOptions = concatenate(
argumentProvider.getExtraArguments(representativeTarget, context)) commonArguments.pluginOptions,
argumentProvider.getExtraArguments(representativeTarget, context)
)
// appending to classpath // appending to classpath
commonArguments.pluginClasspaths = concatenate(commonArguments.pluginClasspaths, commonArguments.pluginClasspaths = concatenate(
argumentProvider.getClasspath(representativeTarget, context)) commonArguments.pluginClasspaths,
argumentProvider.getClasspath(representativeTarget, context)
)
LOG.debug("Plugin loaded: ${argumentProvider::class.java.simpleName}") LOG.debug("Plugin loaded: ${argumentProvider::class.java.simpleName}")
} }
@@ -504,15 +507,17 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
private fun createCompileEnvironment( private fun createCompileEnvironment(
incrementalCaches: Map<ModuleBuildTarget, IncrementalCache>, incrementalCaches: Map<ModuleBuildTarget, IncrementalCache>,
lookupTracker: LookupTracker, lookupTracker: LookupTracker,
context: CompileContext, context: CompileContext,
messageCollector: MessageCollectorAdapter messageCollector: MessageCollectorAdapter
): JpsCompilerEnvironment? { ): JpsCompilerEnvironment? {
val compilerServices = with(Services.Builder()) { val compilerServices = with(Services.Builder()) {
register(LookupTracker::class.java, lookupTracker) register(LookupTracker::class.java, lookupTracker)
register(IncrementalCompilationComponents::class.java, register(
IncrementalCompilationComponentsImpl(incrementalCaches.mapKeys { TargetId(it.key) })) IncrementalCompilationComponents::class.java,
IncrementalCompilationComponentsImpl(incrementalCaches.mapKeys { TargetId(it.key) })
)
register(CompilationCanceledStatus::class.java, object : CompilationCanceledStatus { register(CompilationCanceledStatus::class.java, object : CompilationCanceledStatus {
override fun checkCanceled() { override fun checkCanceled() {
if (context.cancelStatus.isCanceled) throw CompilationCanceledException() if (context.cancelStatus.isCanceled) throw CompilationCanceledException()
@@ -523,17 +528,19 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val paths = computeKotlinPathsForJpsPlugin() val paths = computeKotlinPathsForJpsPlugin()
if (paths == null || !paths.homePath.exists()) { if (paths == null || !paths.homePath.exists()) {
messageCollector.report(ERROR, "Cannot find kotlinc home. Make sure the plugin is properly installed, " + messageCollector.report(
"or specify $JPS_KOTLIN_HOME_PROPERTY system property") ERROR, "Cannot find kotlinc home. Make sure the plugin is properly installed, " +
"or specify $JPS_KOTLIN_HOME_PROPERTY system property"
)
return null return null
} }
return JpsCompilerEnvironment( return JpsCompilerEnvironment(
paths, paths,
compilerServices, compilerServices,
classesToLoadByParent, classesToLoadByParent,
messageCollector, messageCollector,
OutputItemsCollectorImpl() OutputItemsCollectorImpl()
) )
} }
@@ -559,35 +566,39 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
private fun getGeneratedFiles( private fun getGeneratedFiles(
chunk: ModuleChunk, chunk: ModuleChunk,
outputItemCollector: OutputItemsCollectorImpl outputItemCollector: OutputItemsCollectorImpl
): Map<ModuleBuildTarget, List<GeneratedFile>> { ): Map<ModuleBuildTarget, List<GeneratedFile>> {
// If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below // If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below
val sourceToTarget = HashMap<File, ModuleBuildTarget>() val sourceToTarget = HashMap<File, ModuleBuildTarget>()
if (chunk.targets.size > 1) { if (chunk.targets.size > 1) {
for (target in chunk.targets) { for (target in chunk.targets) {
for (file in KotlinSourceFileCollector.getAllKotlinSourceFiles(target)) { for (file in KotlinSourceFileCollector.getAllKotlinSourceFiles(target)) {
sourceToTarget.put(file, target) sourceToTarget[file] = target
} }
} }
} }
val representativeTarget = chunk.representativeTarget() val representativeTarget = chunk.representativeTarget()
fun SimpleOutputItem.target() = fun SimpleOutputItem.target() =
sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?: sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?: chunk.targets.singleOrNull {
chunk.targets.singleOrNull { it.outputDir?.let { outputFile.startsWith(it) } ?: false } ?: it.outputDir?.let {
representativeTarget outputFile.startsWith(
it
)
} ?: false
} ?: representativeTarget
return outputItemCollector.outputs.groupBy(SimpleOutputItem::target, SimpleOutputItem::toGeneratedFile) return outputItemCollector.outputs.groupBy(SimpleOutputItem::target, SimpleOutputItem::toGeneratedFile)
} }
private fun updateJavaMappings( private fun updateJavaMappings(
chunk: ModuleChunk, chunk: ModuleChunk,
context: CompileContext, context: CompileContext,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
filesToCompile: MultiMap<ModuleBuildTarget, File>, filesToCompile: MultiMap<ModuleBuildTarget, File>,
outputItems: Map<ModuleBuildTarget, Iterable<GeneratedFile>>, outputItems: Map<ModuleBuildTarget, Iterable<GeneratedFile>>,
incrementalCaches: Map<ModuleBuildTarget, JpsIncrementalJvmCache> incrementalCaches: Map<ModuleBuildTarget, JpsIncrementalJvmCache>
) { ) {
val previousMappings = context.projectDescriptor.dataManager.mappings val previousMappings = context.projectDescriptor.dataManager.mappings
val callback = JavaBuilderUtil.getDependenciesRegistrar(context) val callback = JavaBuilderUtil.getDependenciesRegistrar(context)
@@ -619,9 +630,9 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
sourceFiles.addAll(output.sourceFiles) sourceFiles.addAll(output.sourceFiles)
callback.associate( callback.associate(
FileUtil.toSystemIndependentName(output.outputFile.canonicalPath), FileUtil.toSystemIndependentName(output.outputFile.canonicalPath),
sourceFiles.map { FileUtil.toSystemIndependentName(it.canonicalPath) }, sourceFiles.map { FileUtil.toSystemIndependentName(it.canonicalPath) },
ClassReader(output.outputClass.fileContents) ClassReader(output.outputClass.fileContents)
) )
} }
} }
@@ -640,13 +651,14 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
private fun updateLookupStorage( private fun updateLookupStorage(
chunk: ModuleChunk, chunk: ModuleChunk,
lookupTracker: LookupTracker, lookupTracker: LookupTracker,
dataManager: BuildDataManager, dataManager: BuildDataManager,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
filesToCompile: MultiMap<ModuleBuildTarget, File> filesToCompile: MultiMap<ModuleBuildTarget, File>
) { ) {
if (lookupTracker !is LookupTrackerImpl) throw AssertionError("Lookup tracker is expected to be LookupTrackerImpl, got ${lookupTracker::class.java}") if (lookupTracker !is LookupTrackerImpl)
throw AssertionError("Lookup tracker is expected to be LookupTrackerImpl, got ${lookupTracker::class.java}")
val removedFiles = chunk.targets.flatMap { KotlinSourceFileCollector.getRemovedKotlinFiles(dirtyFilesHolder, it) } val removedFiles = chunk.targets.flatMap { KotlinSourceFileCollector.getRemovedKotlinFiles(dirtyFilesHolder, it) }
dataManager.withLookupStorage { lookupStorage -> dataManager.withLookupStorage { lookupStorage ->
@@ -656,20 +668,21 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
// if null is returned, nothing was done // if null is returned, nothing was done
private fun compileToJs(chunk: ModuleChunk, private fun compileToJs(
commonArguments: CommonCompilerArguments, chunk: ModuleChunk,
environment: JpsCompilerEnvironment, commonArguments: CommonCompilerArguments,
project: JpsProject environment: JpsCompilerEnvironment,
project: JpsProject
): OutputItemsCollector? { ): OutputItemsCollector? {
val representativeTarget = chunk.representativeTarget() val representativeTarget = chunk.representativeTarget()
if (chunk.modules.size > 1) { if (chunk.modules.size > 1) {
// We do not support circular dependencies, but if they are present, we do our best should not break the build, // We do not support circular dependencies, but if they are present, we do our best should not break the build,
// so we simply yield a warning and report NOTHING_DONE // so we simply yield a warning and report NOTHING_DONE
environment.messageCollector.report( environment.messageCollector.report(
STRONG_WARNING, STRONG_WARNING,
"Circular dependencies are not supported. The following JS modules depend on each other: " "Circular dependencies are not supported. The following JS modules depend on each other: "
+ chunk.modules.joinToString(", ") { it.name } + ". " + chunk.modules.joinToString(", ") { it.name } + ". "
+ "Kotlin is not compiled for these modules" + "Kotlin is not compiled for these modules"
) )
return null return null
} }
@@ -698,12 +711,11 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
// If prefix is not specified (empty) in UI, we want to produce paths relative to source maps location // If prefix is not specified (empty) in UI, we want to produce paths relative to source maps location
val sourceRoots = if (k2JsArguments.sourceMapPrefix.isNullOrBlank()) { val sourceRoots = if (k2JsArguments.sourceMapPrefix.isNullOrBlank()) {
emptyList() emptyList()
} } else {
else {
representativeModule.contentRootsList.urls representativeModule.contentRootsList.urls
.map { URI.create(it) } .map { URI.create(it) }
.filter { it.scheme == "file" } .filter { it.scheme == "file" }
.map { File(it.path) } .map { File(it.path) }
} }
val friendPaths = KotlinBuilderModuleScriptGenerator.getProductionModulesWhichInternalsAreVisible(representativeTarget).mapNotNull { val friendPaths = KotlinBuilderModuleScriptGenerator.getProductionModulesWhichInternalsAreVisible(representativeTarget).mapNotNull {
@@ -712,8 +724,10 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
val compilerRunner = JpsKotlinCompilerRunner() val compilerRunner = JpsKotlinCompilerRunner()
compilerRunner.runK2JsCompiler(commonArguments, k2JsArguments, compilerSettings, environment, sourceFiles, sourceRoots, compilerRunner.runK2JsCompiler(
libraries, friendPaths, outputFile) commonArguments, k2JsArguments, compilerSettings, environment, sourceFiles, sourceRoots,
libraries, friendPaths, outputFile
)
return environment.outputItemsCollector return environment.outputItemsCollector
} }
@@ -726,26 +740,29 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val outputLibraryRuntimeDirectory = File(outputDir, compilerSettings.outputDirectoryForJsLibraryFiles).absolutePath val outputLibraryRuntimeDirectory = File(outputDir, compilerSettings.outputDirectoryForJsLibraryFiles).absolutePath
val libraryFilesToCopy = arrayListOf<String>() val libraryFilesToCopy = arrayListOf<String>()
JpsJsModuleUtils.getLibraryFiles(representativeTarget, libraryFilesToCopy) JpsJsModuleUtils.getLibraryFiles(representativeTarget, libraryFilesToCopy)
JsLibraryUtils.copyJsFilesFromLibraries(libraryFilesToCopy, outputLibraryRuntimeDirectory, JsLibraryUtils.copyJsFilesFromLibraries(
copySourceMap = k2jsCompilerSettings.sourceMap) libraryFilesToCopy, outputLibraryRuntimeDirectory,
copySourceMap = k2jsCompilerSettings.sourceMap
)
} }
} }
// if null is returned, nothing was done // if null is returned, nothing was done
private fun compileToJvm(allCompiledFiles: MutableSet<File>, private fun compileToJvm(
chunk: ModuleChunk, allCompiledFiles: MutableSet<File>,
commonArguments: CommonCompilerArguments, chunk: ModuleChunk,
context: CompileContext, commonArguments: CommonCompilerArguments,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, context: CompileContext,
environment: JpsCompilerEnvironment, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
filesToCompile: MultiMap<ModuleBuildTarget, File> environment: JpsCompilerEnvironment,
filesToCompile: MultiMap<ModuleBuildTarget, File>
): OutputItemsCollector? { ): OutputItemsCollector? {
if (chunk.modules.size > 1) { if (chunk.modules.size > 1) {
environment.messageCollector.report( environment.messageCollector.report(
STRONG_WARNING, STRONG_WARNING,
"Circular dependencies are only partially supported. The following modules depend on each other: " "Circular dependencies are only partially supported. The following modules depend on each other: "
+ chunk.modules.joinToString(", ") { it.name } + ". " + chunk.modules.joinToString(", ") { it.name } + ". "
+ "Kotlin will compile them, but some strange effect may happen" + "Kotlin will compile them, but some strange effect may happen"
) )
} }
@@ -763,7 +780,8 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
} }
val moduleFile = KotlinBuilderModuleScriptGenerator.generateModuleDescription(context, chunk, filesToCompile, totalRemovedFiles != 0) val moduleFile =
KotlinBuilderModuleScriptGenerator.generateModuleDescription(context, chunk, filesToCompile, totalRemovedFiles != 0)
if (moduleFile == null) { if (moduleFile == null) {
KotlinBuilder.LOG.debug("Not compiling, because no files affected: " + filesToCompile.keySet().joinToString { it.presentableName }) KotlinBuilder.LOG.debug("Not compiling, because no files affected: " + filesToCompile.keySet().joinToString { it.presentableName })
// No Kotlin sources found // No Kotlin sources found
@@ -775,14 +793,13 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(module) val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(module)
KotlinBuilder.LOG.debug("Compiling to JVM ${filesToCompile.values().size} files" KotlinBuilder.LOG.debug("Compiling to JVM ${filesToCompile.values().size} files"
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)") + (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
+ " in " + filesToCompile.keySet().joinToString { it.presentableName }) + " in " + filesToCompile.keySet().joinToString { it.presentableName })
try { try {
val compilerRunner = JpsKotlinCompilerRunner() val compilerRunner = JpsKotlinCompilerRunner()
compilerRunner.runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, environment, moduleFile) compilerRunner.runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, environment, moduleFile)
} } finally {
finally {
if (System.getProperty("kotlin.jps.delete.module.file.after.build") != "false") { if (System.getProperty("kotlin.jps.delete.module.file.after.build") != "false") {
moduleFile.delete() moduleFile.delete()
} }
@@ -802,7 +819,8 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
val kind = kind(severity) val kind = kind(severity)
if (kind != null) { if (kind != null) {
context.processMessage(CompilerMessage( context.processMessage(
CompilerMessage(
CompilerRunnerConstants.KOTLIN_COMPILER_NAME, CompilerRunnerConstants.KOTLIN_COMPILER_NAME,
kind, kind,
prefix + message, prefix + message,
@@ -810,9 +828,9 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
-1, -1, -1, -1, -1, -1,
location?.line?.toLong() ?: -1, location?.line?.toLong() ?: -1,
location?.column?.toLong() ?: -1 location?.column?.toLong() ?: -1
)) )
} )
else { } else {
val path = if (location != null) "${location.path}:${location.line}:${location.column}: " else "" val path = if (location != null) "${location.path}:${location.line}:${location.column}: " else ""
KotlinBuilder.LOG.debug(path + message) KotlinBuilder.LOG.debug(path + message)
} }
@@ -830,7 +848,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
ERROR, EXCEPTION -> BuildMessage.Kind.ERROR ERROR, EXCEPTION -> BuildMessage.Kind.ERROR
WARNING, STRONG_WARNING -> BuildMessage.Kind.WARNING WARNING, STRONG_WARNING -> BuildMessage.Kind.WARNING
LOGGING -> null LOGGING -> null
else -> throw IllegalArgumentException("Unsupported severity: " + severity) else -> throw IllegalArgumentException("Unsupported severity: $severity")
} }
} }
} }
@@ -845,10 +863,10 @@ private class JpsICReporter : ICReporter {
} }
private fun ChangesCollector.processChangesUsingLookups( private fun ChangesCollector.processChangesUsingLookups(
compiledFiles: Set<File>, compiledFiles: Set<File>,
dataManager: BuildDataManager, dataManager: BuildDataManager,
fsOperations: FSOperationsHelper, fsOperations: FSOperationsHelper,
caches: Iterable<IncrementalJvmCache> caches: Iterable<IncrementalJvmCache>
) { ) {
val allCaches = caches.flatMap { it.thisWithDependentCaches } val allCaches = caches.flatMap { it.thisWithDependentCaches }
val reporter = JpsICReporter() val reporter = JpsICReporter()
@@ -890,8 +908,8 @@ private fun getIncrementalCaches(chunk: ModuleChunk, context: CompileContext): M
} }
fun getDependentTargets( fun getDependentTargets(
compilingChunk: ModuleChunk, compilingChunk: ModuleChunk,
context: CompileContext context: CompileContext
): Set<ModuleBuildTarget> { ): Set<ModuleBuildTarget> {
val compilingChunkIsTests = compilingChunk.targets.any { it.isTests } val compilingChunkIsTests = compilingChunk.targets.any { it.isTests }
val classpathKind = JpsJavaClasspathKind.compile(compilingChunkIsTests) val classpathKind = JpsJavaClasspathKind.compile(compilingChunkIsTests)
@@ -922,10 +940,11 @@ fun getDependentTargets(
} }
private fun getDependenciesRecursively(module: JpsModule, kind: JpsJavaClasspathKind): Set<JpsModule> = private fun getDependenciesRecursively(module: JpsModule, kind: JpsJavaClasspathKind): Set<JpsModule> =
JpsJavaExtensionService.dependencies(module).includedIn(kind).recursivelyExportedOnly().modules JpsJavaExtensionService.dependencies(module).includedIn(kind).recursivelyExportedOnly().modules
// TODO: investigate thread safety // TODO: investigate thread safety
private val ALL_COMPILED_FILES_KEY = Key.create<MutableSet<File>>("_all_kotlin_compiled_files_") private val ALL_COMPILED_FILES_KEY = Key.create<MutableSet<File>>("_all_kotlin_compiled_files_")
private fun getAllCompiledFilesContainer(context: CompileContext): MutableSet<File> { private fun getAllCompiledFilesContainer(context: CompileContext): MutableSet<File> {
var allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context) var allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context)
if (allCompiledFiles == null) { if (allCompiledFiles == null) {
@@ -937,18 +956,19 @@ private fun getAllCompiledFilesContainer(context: CompileContext): MutableSet<Fi
// TODO: investigate thread safety // TODO: investigate thread safety
private val PROCESSED_TARGETS_WITH_REMOVED_FILES = Key.create<MutableSet<ModuleBuildTarget>>("_processed_targets_with_removed_files_") private val PROCESSED_TARGETS_WITH_REMOVED_FILES = Key.create<MutableSet<ModuleBuildTarget>>("_processed_targets_with_removed_files_")
private fun getProcessedTargetsWithRemovedFilesContainer(context: CompileContext): MutableSet<ModuleBuildTarget> { private fun getProcessedTargetsWithRemovedFilesContainer(context: CompileContext): MutableSet<ModuleBuildTarget> {
var set = PROCESSED_TARGETS_WITH_REMOVED_FILES.get(context) var set = PROCESSED_TARGETS_WITH_REMOVED_FILES.get(context)
if (set == null) { if (set == null) {
set = HashSet<ModuleBuildTarget>() set = HashSet()
PROCESSED_TARGETS_WITH_REMOVED_FILES.set(context, set) PROCESSED_TARGETS_WITH_REMOVED_FILES.set(context, set)
} }
return set return set
} }
private fun hasKotlinDirtyOrRemovedFiles( private fun hasKotlinDirtyOrRemovedFiles(
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
chunk: ModuleChunk chunk: ModuleChunk
): Boolean { ): Boolean {
if (!dirtyFilesHolder.hasDirtyFiles() && !dirtyFilesHolder.hasRemovedFiles()) return false if (!dirtyFilesHolder.hasDirtyFiles() && !dirtyFilesHolder.hasRemovedFiles()) return false
@@ -958,4 +978,4 @@ private fun hasKotlinDirtyOrRemovedFiles(
} }
fun jvmBuildMetaInfoFile(target: ModuleBuildTarget, dataManager: BuildDataManager): File = fun jvmBuildMetaInfoFile(target: ModuleBuildTarget, dataManager: BuildDataManager): File =
File(dataManager.dataPaths.getTargetDataRoot(target), KotlinBuilder.JVM_BUILD_META_INFO_FILE_NAME) File(dataManager.dataPaths.getTargetDataRoot(target), KotlinBuilder.JVM_BUILD_META_INFO_FILE_NAME)
@@ -51,21 +51,21 @@ object KotlinBuilderModuleScriptGenerator {
// TODO switch to directly using when "since-build" will be >= 144.3357.4 // TODO switch to directly using when "since-build" will be >= 144.3357.4
internal val getRelatedProductionModule: (JpsModule) -> JpsModule? = run { internal val getRelatedProductionModule: (JpsModule) -> JpsModule? = run {
val klass = val klass =
try { try {
Class.forName("org.jetbrains.jps.model.module.JpsTestModuleProperties") Class.forName("org.jetbrains.jps.model.module.JpsTestModuleProperties")
} catch (e: ClassNotFoundException) { } catch (e: ClassNotFoundException) {
return@run alwaysNull() return@run alwaysNull()
} }
val getTestModulePropertiesMethod: Method val getTestModulePropertiesMethod: Method
val getProductionModuleMethod: Method val getProductionModuleMethod: Method
try { try {
getTestModulePropertiesMethod = JpsJavaExtensionService::class.java.getDeclaredMethod("getTestModuleProperties", JpsModule::class.java) getTestModulePropertiesMethod =
JpsJavaExtensionService::class.java.getDeclaredMethod("getTestModuleProperties", JpsModule::class.java)
getProductionModuleMethod = klass.getDeclaredMethod("getProductionModule") getProductionModuleMethod = klass.getDeclaredMethod("getProductionModule")
} } catch (e: NoSuchMethodException) {
catch (e: NoSuchMethodException) {
return@run alwaysNull() return@run alwaysNull()
} }
@@ -77,10 +77,10 @@ object KotlinBuilderModuleScriptGenerator {
} }
fun generateModuleDescription( fun generateModuleDescription(
context: CompileContext, context: CompileContext,
chunk: ModuleChunk, chunk: ModuleChunk,
sourceFiles: MultiMap<ModuleBuildTarget, File>, // ignored for non-incremental compilation sourceFiles: MultiMap<ModuleBuildTarget, File>, // ignored for non-incremental compilation
hasRemovedFiles: Boolean hasRemovedFiles: Boolean
): File? { ): File? {
val builder = KotlinModuleXmlBuilder() val builder = KotlinModuleXmlBuilder()
@@ -97,10 +97,11 @@ object KotlinBuilderModuleScriptGenerator {
val friendDirs = getAdditionalOutputDirsWhereInternalsAreVisible(target) val friendDirs = getAdditionalOutputDirsWhereInternalsAreVisible(target)
val moduleSources = ArrayList( val moduleSources = ArrayList(
if (IncrementalCompilation.isEnabled()) if (IncrementalCompilation.isEnabled())
sourceFiles.get(target) sourceFiles.get(target)
else else
KotlinSourceFileCollector.getAllKotlinSourceFiles(target)) KotlinSourceFileCollector.getAllKotlinSourceFiles(target)
)
if (moduleSources.size > 0 || hasRemovedFiles) { if (moduleSources.size > 0 || hasRemovedFiles) {
noSources = false noSources = false
@@ -114,17 +115,18 @@ object KotlinBuilderModuleScriptGenerator {
assert(targetType is JavaModuleBuildTargetType) assert(targetType is JavaModuleBuildTargetType)
val targetId = TargetId(target) val targetId = TargetId(target)
builder.addModule( builder.addModule(
targetId.name, targetId.name,
outputDir.absolutePath, outputDir.absolutePath,
moduleSources, moduleSources,
findSourceRoots(context, target), findSourceRoots(context, target),
findClassPathRoots(target), findClassPathRoots(target),
findModularJdkRoot(target), findModularJdkRoot(target),
targetId.type, targetId.type,
(targetType as JavaModuleBuildTargetType).isTests, (targetType as JavaModuleBuildTargetType).isTests,
// this excludes the output directories from the class path, to be removed for true incremental compilation // this excludes the output directories from the class path, to be removed for true incremental compilation
outputDirs, outputDirs,
friendDirs) friendDirs
)
} }
if (noSources) return null if (noSources) return null
@@ -144,14 +146,12 @@ object KotlinBuilderModuleScriptGenerator {
val dir = System.getProperty("kotlin.jps.dir.for.module.files")?.let { File(it) }?.takeIf { it.isDirectory } val dir = System.getProperty("kotlin.jps.dir.for.module.files")?.let { File(it) }?.takeIf { it.isDirectory }
return try { return try {
File.createTempFile("kjps", readableSuffix + ".script.xml", dir) File.createTempFile("kjps", readableSuffix + ".script.xml", dir)
} } catch (e: IOException) {
catch (e: IOException) {
// sometimes files cannot be created, because file name is too long (Windows, Mac OS) // sometimes files cannot be created, because file name is too long (Windows, Mac OS)
// see https://bugs.openjdk.java.net/browse/JDK-8148023 // see https://bugs.openjdk.java.net/browse/JDK-8148023
try { try {
File.createTempFile("kjps", ".script.xml", dir) File.createTempFile("kjps", ".script.xml", dir)
} } catch (e: IOException) {
catch (e: IOException) {
val message = buildString { val message = buildString {
append("Could not create module file when building chunk $chunk") append("Could not create module file when building chunk $chunk")
if (dir != null) { if (dir != null) {
@@ -203,8 +203,8 @@ object KotlinBuilderModuleScriptGenerator {
// List of paths to JRE modules in the following format: // List of paths to JRE modules in the following format:
// jrt:///Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home!/java.base // jrt:///Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home!/java.base
val urls = JpsJavaExtensionService.dependencies(target.module) val urls = JpsJavaExtensionService.dependencies(target.module)
.satisfying { dependency -> dependency is JpsSdkDependency } .satisfying { dependency -> dependency is JpsSdkDependency }
.classes().urls .classes().urls
val url = urls.firstOrNull { it.startsWith(StandardFileSystems.JRT_PROTOCOL_PREFIX) } ?: return null val url = urls.firstOrNull { it.startsWith(StandardFileSystems.JRT_PROTOCOL_PREFIX) } ?: return null
@@ -42,8 +42,7 @@ public class KotlinSourceFileCollector {
// For incremental compilation // For incremental compilation
@NotNull @NotNull
public static MultiMap<ModuleBuildTarget, File> getDirtySourceFiles(DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder) public static MultiMap<ModuleBuildTarget, File> getDirtySourceFiles(DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder)
throws IOException throws IOException {
{
final MultiMap<ModuleBuildTarget, File> result = new MultiMap<ModuleBuildTarget, File>(); final MultiMap<ModuleBuildTarget, File> result = new MultiMap<ModuleBuildTarget, File>();
dirtyFilesHolder.processDirtyFiles(new FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>() { dirtyFilesHolder.processDirtyFiles(new FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>() {
@@ -84,15 +83,17 @@ public class KotlinSourceFileCollector {
@NotNull @NotNull
public static List<File> getAllKotlinSourceFiles(@NotNull ModuleBuildTarget target) { public static List<File> getAllKotlinSourceFiles(@NotNull ModuleBuildTarget target) {
final List<File> moduleExcludes = ContainerUtil.map(target.getModule().getExcludeRootsList().getUrls(), new Function<String, File>() { final List<File> moduleExcludes =
@Override ContainerUtil.map(target.getModule().getExcludeRootsList().getUrls(), new Function<String, File>() {
public File fun(String url) { @Override
return JpsPathUtil.urlToFile(url); public File fun(String url) {
} return JpsPathUtil.urlToFile(url);
}); }
});
final JpsCompilerExcludes compilerExcludes = final JpsCompilerExcludes compilerExcludes =
JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(target.getModule().getProject()).getCompilerExcludes(); JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(target.getModule().getProject())
.getCompilerExcludes();
final List<File> result = ContainerUtil.newArrayList(); final List<File> result = ContainerUtil.newArrayList();
for (JpsModuleSourceRoot sourceRoot : getRelevantSourceRoots(target)) { for (JpsModuleSourceRoot sourceRoot : getRelevantSourceRoots(target)) {
@@ -135,5 +136,6 @@ public class KotlinSourceFileCollector {
return FileUtilRt.extensionEquals(file.getName(), "kt"); return FileUtilRt.extensionEquals(file.getName(), "kt");
} }
private KotlinSourceFileCollector() {} private KotlinSourceFileCollector() {
}
} }
@@ -57,4 +57,5 @@ abstract class MarkerFile(private val fileName: String, private val paths: Build
} }
class HasKotlinMarker(dataManager: BuildDataManager) : MarkerFile(HAS_KOTLIN_MARKER_FILE_NAME, dataManager.dataPaths) class HasKotlinMarker(dataManager: BuildDataManager) : MarkerFile(HAS_KOTLIN_MARKER_FILE_NAME, dataManager.dataPaths)
class RebuildAfterCacheVersionChangeMarker(dataManager: BuildDataManager) : MarkerFile(REBUILD_AFTER_CACHE_VERSION_CHANGE_MARKER, dataManager.dataPaths) class RebuildAfterCacheVersionChangeMarker(dataManager: BuildDataManager) :
MarkerFile(REBUILD_AFTER_CACHE_VERSION_CHANGE_MARKER, dataManager.dataPaths)
@@ -47,8 +47,7 @@ class TeamcityStatisticsLogger {
val escChar = escapedChar(c) val escChar = escapedChar(c)
if (escChar == 0.toChar()) { if (escChar == 0.toChar()) {
escaped.append(c) escaped.append(c)
} } else {
else {
escaped.append('|').append(escChar) escaped.append('|').append(escChar)
} }
} }
@@ -65,8 +64,8 @@ class TeamcityStatisticsLogger {
private fun printPerChunkStatistics(moduleChunk: ModuleChunk, timeToCompileNs: Long) { private fun printPerChunkStatistics(moduleChunk: ModuleChunk, timeToCompileNs: Long) {
printStatisticMessage( printStatisticMessage(
"${KotlinBuilder.KOTLIN_BUILDER_NAME} for ${moduleChunk.presentableShortName} compilation time, ms", "${KotlinBuilder.KOTLIN_BUILDER_NAME} for ${moduleChunk.presentableShortName} compilation time, ms",
timeToCompileNs.nanosToMillis().toString() timeToCompileNs.nanosToMillis().toString()
) )
} }
@@ -74,8 +73,8 @@ class TeamcityStatisticsLogger {
if (!isOnTeamcity) return if (!isOnTeamcity) return
printStatisticMessage( printStatisticMessage(
"${KotlinBuilder.KOTLIN_BUILDER_NAME} total compilation time, ms", "${KotlinBuilder.KOTLIN_BUILDER_NAME} total compilation time, ms",
totalTime.get().nanosToMillis().toString() totalTime.get().nanosToMillis().toString()
) )
} }
@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.jps.build.KotlinBuilder
import java.io.File import java.io.File
class JpsIncrementalJvmCache( class JpsIncrementalJvmCache(
target: ModuleBuildTarget, target: ModuleBuildTarget,
paths: BuildDataPaths paths: BuildDataPaths
) : IncrementalJvmCache(paths.getTargetDataRoot(target), target.outputDir), StorageOwner { ) : IncrementalJvmCache(paths.getTargetDataRoot(target), target.outputDir), StorageOwner {
override fun debugLog(message: String) { override fun debugLog(message: String) {
KotlinBuilder.LOG.debug(message) KotlinBuilder.LOG.debug(message)
@@ -35,8 +35,8 @@ class JpsIncrementalJvmCache(
} }
private class KotlinIncrementalStorageProvider( private class KotlinIncrementalStorageProvider(
private val target: ModuleBuildTarget, private val target: ModuleBuildTarget,
private val paths: BuildDataPaths private val paths: BuildDataPaths
) : StorageProvider<JpsIncrementalJvmCache>() { ) : StorageProvider<JpsIncrementalJvmCache>() {
override fun equals(other: Any?) = other is KotlinIncrementalStorageProvider && target == other.target override fun equals(other: Any?) = other is KotlinIncrementalStorageProvider && target == other.target
@@ -44,9 +44,9 @@ private class KotlinIncrementalStorageProvider(
override fun hashCode() = target.hashCode() override fun hashCode() = target.hashCode()
override fun createStorage(targetDataDir: File): JpsIncrementalJvmCache = override fun createStorage(targetDataDir: File): JpsIncrementalJvmCache =
JpsIncrementalJvmCache(target, paths) JpsIncrementalJvmCache(target, paths)
} }
fun BuildDataManager.getKotlinCache(target: ModuleBuildTarget): JpsIncrementalJvmCache = fun BuildDataManager.getKotlinCache(target: ModuleBuildTarget): JpsIncrementalJvmCache =
getStorage(target, KotlinIncrementalStorageProvider(target, dataPaths)) getStorage(target, KotlinIncrementalStorageProvider(target, dataPaths))
@@ -30,9 +30,9 @@ object KotlinDataContainerTargetType : BuildTargetType<KotlinDataContainerTarget
override fun computeAllTargets(model: JpsModel): List<KotlinDataContainerTarget> = listOf(KotlinDataContainerTarget) override fun computeAllTargets(model: JpsModel): List<KotlinDataContainerTarget> = listOf(KotlinDataContainerTarget)
override fun createLoader(model: JpsModel): BuildTargetLoader<KotlinDataContainerTarget> = override fun createLoader(model: JpsModel): BuildTargetLoader<KotlinDataContainerTarget> =
object : BuildTargetLoader<KotlinDataContainerTarget>() { object : BuildTargetLoader<KotlinDataContainerTarget>() {
override fun createTarget(targetId: String): KotlinDataContainerTarget? = KotlinDataContainerTarget override fun createTarget(targetId: String): KotlinDataContainerTarget? = KotlinDataContainerTarget
} }
} }
// Fake target to store data per project for incremental compilation // Fake target to store data per project for incremental compilation
@@ -41,10 +41,10 @@ object KotlinDataContainerTarget : BuildTarget<BuildRootDescriptor>(KotlinDataCo
override fun getPresentableName(): String = KOTLIN_DATA_CONTAINER override fun getPresentableName(): String = KOTLIN_DATA_CONTAINER
override fun computeRootDescriptors( override fun computeRootDescriptors(
model: JpsModel?, model: JpsModel?,
index: ModuleExcludeIndex?, index: ModuleExcludeIndex?,
ignoredFileIndex: IgnoredFileIndex?, ignoredFileIndex: IgnoredFileIndex?,
dataPaths: BuildDataPaths? dataPaths: BuildDataPaths?
): List<BuildRootDescriptor> = listOf() ): List<BuildRootDescriptor> = listOf()
override fun getOutputRoots(context: CompileContext): Collection<File> { override fun getOutputRoots(context: CompileContext): Collection<File> {
@@ -56,7 +56,7 @@ object KotlinDataContainerTarget : BuildTarget<BuildRootDescriptor>(KotlinDataCo
override fun findRootDescriptor(rootId: String?, rootIndex: BuildRootIndex?): BuildRootDescriptor? = null override fun findRootDescriptor(rootId: String?, rootIndex: BuildRootIndex?): BuildRootDescriptor? = null
override fun computeDependencies( override fun computeDependencies(
targetRegistry: BuildTargetRegistry?, targetRegistry: BuildTargetRegistry?,
outputIndex: TargetOutputIndex? outputIndex: TargetOutputIndex?
): Collection<BuildTarget<*>>? = listOf() ): Collection<BuildTarget<*>>? = listOf()
} }
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.jps.incremental.storages
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
class PathFunctionPair( class PathFunctionPair(
val path: String, val path: String,
val function: String val function: String
): Comparable<PathFunctionPair> { ) : Comparable<PathFunctionPair> {
override fun compareTo(other: PathFunctionPair): Int { override fun compareTo(other: PathFunctionPair): Int {
val pathComp = FileUtil.comparePaths(path, other.path) val pathComp = FileUtil.comparePaths(path, other.path)
@@ -31,12 +31,12 @@ class PathFunctionPair(
} }
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
when (other) { when (other) {
is PathFunctionPair -> is PathFunctionPair ->
FileUtil.pathsEqual(path, other.path) && function == other.function FileUtil.pathsEqual(path, other.path) && function == other.function
else -> else ->
false false
} }
override fun hashCode(): Int = 31 * FileUtil.pathHashCode(path) + function.hashCode() override fun hashCode(): Int = 31 * FileUtil.pathHashCode(path) + function.hashCode()
} }
@@ -24,9 +24,9 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.config.SettingConstants import org.jetbrains.kotlin.config.SettingConstants
abstract class BaseJpsCompilerSettingsSerializer<T : Any>( abstract class BaseJpsCompilerSettingsSerializer<T : Any>(
componentName: String, componentName: String,
private val settingsFactory: () -> T private val settingsFactory: () -> T
): JpsProjectExtensionSerializer(SettingConstants.KOTLIN_COMPILER_SETTINGS_FILE, componentName) { ) : JpsProjectExtensionSerializer(SettingConstants.KOTLIN_COMPILER_SETTINGS_FILE, componentName) {
protected abstract fun onLoad(project: JpsProject, settings: T) protected abstract fun onLoad(project: JpsProject, settings: T)
override fun loadExtension(project: JpsProject, componentTag: Element) { override fun loadExtension(project: JpsProject, componentTag: Element) {
@@ -24,23 +24,23 @@ import org.jetbrains.kotlin.config.deserializeFacetSettings
import org.jetbrains.kotlin.config.serializeFacetSettings import org.jetbrains.kotlin.config.serializeFacetSettings
object JpsKotlinFacetConfigurationSerializer : JpsFacetConfigurationSerializer<JpsKotlinFacetModuleExtension>( object JpsKotlinFacetConfigurationSerializer : JpsFacetConfigurationSerializer<JpsKotlinFacetModuleExtension>(
JpsKotlinFacetModuleExtension.KIND, JpsKotlinFacetModuleExtension.KIND,
JpsKotlinFacetModuleExtension.FACET_TYPE_ID, JpsKotlinFacetModuleExtension.FACET_TYPE_ID,
JpsKotlinFacetModuleExtension.FACET_NAME JpsKotlinFacetModuleExtension.FACET_NAME
) { ) {
override fun loadExtension( override fun loadExtension(
facetConfigurationElement: Element, facetConfigurationElement: Element,
name: String, name: String,
parent: JpsElement?, parent: JpsElement?,
module: JpsModule module: JpsModule
): JpsKotlinFacetModuleExtension { ): JpsKotlinFacetModuleExtension {
return JpsKotlinFacetModuleExtension(deserializeFacetSettings(facetConfigurationElement)) return JpsKotlinFacetModuleExtension(deserializeFacetSettings(facetConfigurationElement))
} }
override fun saveExtension( override fun saveExtension(
extension: JpsKotlinFacetModuleExtension?, extension: JpsKotlinFacetModuleExtension?,
facetConfigurationTag: Element, facetConfigurationTag: Element,
module: JpsModule module: JpsModule
) { ) {
(extension as JpsKotlinFacetModuleExtension).settings.serializeFacetSettings(facetConfigurationTag) (extension as JpsKotlinFacetModuleExtension).settings.serializeFacetSettings(facetConfigurationTag)
} }
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_TO_JS_COMPILER_ARGUME
import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings
internal class Kotlin2JsCompilerArgumentsSerializer : BaseJpsCompilerSettingsSerializer<K2JSCompilerArguments>( internal class Kotlin2JsCompilerArgumentsSerializer : BaseJpsCompilerSettingsSerializer<K2JSCompilerArguments>(
KOTLIN_TO_JS_COMPILER_ARGUMENTS_SECTION, ::K2JSCompilerArguments KOTLIN_TO_JS_COMPILER_ARGUMENTS_SECTION, ::K2JSCompilerArguments
) { ) {
override fun onLoad(project: JpsProject, settings: K2JSCompilerArguments) { override fun onLoad(project: JpsProject, settings: K2JSCompilerArguments) {
JpsKotlinCompilerSettings.setK2JsCompilerArguments(project, settings) JpsKotlinCompilerSettings.setK2JsCompilerArguments(project, settings)
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_TO_JVM_COMPILER_ARGUM
import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings
internal class Kotlin2JvmCompilerArgumentsSerializer : BaseJpsCompilerSettingsSerializer<K2JVMCompilerArguments>( internal class Kotlin2JvmCompilerArgumentsSerializer : BaseJpsCompilerSettingsSerializer<K2JVMCompilerArguments>(
KOTLIN_TO_JVM_COMPILER_ARGUMENTS_SECTION, ::K2JVMCompilerArguments KOTLIN_TO_JVM_COMPILER_ARGUMENTS_SECTION, ::K2JVMCompilerArguments
) { ) {
override fun onLoad(project: JpsProject, settings: K2JVMCompilerArguments) { override fun onLoad(project: JpsProject, settings: K2JVMCompilerArguments) {
JpsKotlinCompilerSettings.setK2JvmCompilerArguments(project, settings) JpsKotlinCompilerSettings.setK2JvmCompilerArguments(project, settings)
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_COMMON_COMPILER_ARGUM
import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings
internal class KotlinCommonCompilerArgumentsSerializer : BaseJpsCompilerSettingsSerializer<CommonCompilerArguments.DummyImpl>( internal class KotlinCommonCompilerArgumentsSerializer : BaseJpsCompilerSettingsSerializer<CommonCompilerArguments.DummyImpl>(
KOTLIN_COMMON_COMPILER_ARGUMENTS_SECTION, CommonCompilerArguments::DummyImpl KOTLIN_COMMON_COMPILER_ARGUMENTS_SECTION, CommonCompilerArguments::DummyImpl
) { ) {
override fun onLoad(project: JpsProject, settings: CommonCompilerArguments.DummyImpl) { override fun onLoad(project: JpsProject, settings: CommonCompilerArguments.DummyImpl) {
settings.setApiVersionToLanguageVersionIfNeeded() settings.setApiVersionToLanguageVersionIfNeeded()
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.config.SettingConstants.KOTLIN_COMPILER_SETTINGS_SEC
import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings
internal class KotlinCompilerSettingsSerializer : BaseJpsCompilerSettingsSerializer<CompilerSettings>( internal class KotlinCompilerSettingsSerializer : BaseJpsCompilerSettingsSerializer<CompilerSettings>(
KOTLIN_COMPILER_SETTINGS_SECTION, ::CompilerSettings KOTLIN_COMPILER_SETTINGS_SECTION, ::CompilerSettings
) { ) {
override fun onLoad(project: JpsProject, settings: CompilerSettings) { override fun onLoad(project: JpsProject, settings: CompilerSettings) {
JpsKotlinCompilerSettings.setCompilerSettings(project, settings) JpsKotlinCompilerSettings.setCompilerSettings(project, settings)