From d4d1d5ad0f557dabbbb1fc89fec1fca15b350171 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Wed, 28 Dec 2016 21:04:25 +0300 Subject: [PATCH] Refactor daemon interface --- .../kotlin/incremental/ICReporter.kt | 2 +- .../common/AdditionalCompilerArguments.kt | 40 ++++ .../kotlin/daemon/common/CompileService.kt | 17 +- .../common/CompilerServicesFacadeBase.kt | 52 +++++ .../kotlin/daemon/common/ReportCategory.kt | 40 ++++ .../kotlin/daemon/common/ReportingFilter.kt | 28 +++ .../kotlin/daemon/CompileServiceImpl.kt | 187 ++++++++++++------ .../RemoteAnnotationsFileUpdater.kt | 3 +- .../RemoteArtifactChangesProvider.kt | 4 +- .../incremental/RemoteChangesRegostry.kt | 4 +- .../daemon/incremental/RemoteICReporter.kt | 29 ++- .../daemon/report/CompileServiceReporter.kt | 49 +++++ .../CompileServicesFacadeMessageCollector.kt | 45 +++++ .../daemon/report/FilteringReporterBase.kt | 39 ++++ .../IncrementalJvmCompilerRunner.kt | 4 +- ...linStandaloneIncrementalCompilationTest.kt | 2 +- 16 files changed, 461 insertions(+), 84 deletions(-) create mode 100644 compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/AdditionalCompilerArguments.kt create mode 100644 compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt create mode 100644 compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportCategory.kt create mode 100644 compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportingFilter.kt create mode 100644 compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServiceReporter.kt create mode 100644 compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServicesFacadeMessageCollector.kt create mode 100644 compiler/daemon/src/org/jetbrains/kotlin/daemon/report/FilteringReporterBase.kt diff --git a/build-common/src/org/jetbrains/kotlin/incremental/ICReporter.kt b/build-common/src/org/jetbrains/kotlin/incremental/ICReporter.kt index a4e2d769e84..b32a9e8c9b9 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/ICReporter.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/ICReporter.kt @@ -24,7 +24,7 @@ interface ICReporter { // used in Gradle plugin @Suppress("unused") - fun reportCompileIteration(sourceFiles: Iterable, exitCode: ExitCode) {} + fun reportCompileIteration(sourceFiles: Collection, exitCode: ExitCode) {} fun pathsAsString(files: Iterable): String = files.map { it.canonicalPath }.joinToString() diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/AdditionalCompilerArguments.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/AdditionalCompilerArguments.kt new file mode 100644 index 00000000000..02f76b6049b --- /dev/null +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/AdditionalCompilerArguments.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.daemon.common + +import java.io.File +import java.io.Serializable + +open class AdditionalCompilerArguments(val reportingFilters: List) : Serializable { + companion object { + const val serialVersionUID: Long = 0 + } +} + +class IncrementalCompilerArguments( + val areFileChangesKnown: Boolean, + val modifiedFiles: List?, + val deletedFiles: List?, + val workingDir: File, + val customCacheVersionFileName: String, + val customCacheVersion: Int, + reportingFilters: List +) : AdditionalCompilerArguments(reportingFilters) { + companion object { + const val serialVersionUID: Long = 0 + } +} diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt index 7f1ea908f59..d6a6d2b31a8 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompileService.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.daemon.common +import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.repl.* import java.io.File import java.io.Serializable @@ -35,6 +36,11 @@ interface CompileService : Remote { METADATA } + enum class CompilerMode : Serializable { + NON_INCREMENTAL_COMPILER, + INCREMENTAL_COMPILER + } + companion object { val NO_SESSION: Int = 0 } @@ -127,12 +133,13 @@ interface CompileService : Remote { ): CallResult @Throws(RemoteException::class) - fun serverSideJvmIC( + fun compile( sessionId: Int, - args: Array, - servicesFacade: IncrementalCompilationServicesFacade, - compilerOutputStream: RemoteOutputStream, - serviceOutputStream: RemoteOutputStream, + compilerMode: CompilerMode, + targetPlatform: TargetPlatform, + compilerArguments: CommonCompilerArguments, + additionalCompilerArguments: AdditionalCompilerArguments, + servicesFacade: CompilerServicesFacadeBase, operationsTracer: RemoteOperationsTracer? ): CallResult diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt new file mode 100644 index 00000000000..2539d56f275 --- /dev/null +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerServicesFacadeBase.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.daemon.common + +import java.io.File +import java.io.Serializable +import java.rmi.Remote +import java.rmi.RemoteException + +interface CompilerServicesFacadeBase : Remote { + /** + * Reports different kind of diagnostic messages from compile daemon to compile daemon clients (jps, gradle, ...) + */ + @Throws(RemoteException::class) + fun report(category: ReportCategory, severity: Int, message: String?, attachment: Serializable?) +} + +interface IncrementalCompilerServicesFacade : CompilerServicesFacadeBase { + // AnnotationFileUpdater + @Throws(RemoteException::class) + fun hasAnnotationsFileUpdater(): Boolean + + @Throws(RemoteException::class) + fun updateAnnotations(outdatedClassesJvmNames: Iterable) + + @Throws(RemoteException::class) + fun revert() + + // ChangesRegistry + @Throws(RemoteException::class) + fun registerChanges(timestamp: Long, dirtyData: SimpleDirtyData) + + @Throws(RemoteException::class) + fun unknownChanges(timestamp: Long) + + @Throws(RemoteException::class) + fun getChanges(artifact: File, sinceTS: Long): Iterable? +} \ No newline at end of file diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportCategory.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportCategory.kt new file mode 100644 index 00000000000..58d840580d5 --- /dev/null +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportCategory.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.daemon.common + +import java.io.Serializable + +enum class ReportCategory : Serializable { + /** + * Messages from compiler + * For related severities see [org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity] + */ + COMPILER_MESSAGE, + /** + * Messages from compile daemon + * For related severities see [org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity] + */ + DAEMON_MESSAGE, + /** + * For related severities see [org.jetbrains.kotlin.daemon.incremental.IncrementalCompilationSeverity] + */ + INCREMENTAL_COMPILATION; + + companion object { + const val serialVersionUID: Long = 0 + } +} \ No newline at end of file diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportingFilter.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportingFilter.kt new file mode 100644 index 00000000000..16789ef97e0 --- /dev/null +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/ReportingFilter.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.daemon.common + +import java.io.Serializable + +/** + * Allows daemon clients to specify report category and severities for that category that should be reported from daemon + */ +data class ReportingFilter(val category: ReportCategory, val severities: List) : Serializable { + companion object { + const val serialVersionUID: Long = 0 + } +} \ No newline at end of file diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index eca80876bcd..f9aeb2ae686 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -20,34 +20,36 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.impl.ZipHandler import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem -import org.jetbrains.kotlin.annotation.AnnotationFileUpdater import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY +import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments +import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.cli.common.messages.* import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser import org.jetbrains.kotlin.cli.common.repl.ReplCheckResult import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult +import org.jetbrains.kotlin.cli.js.K2JSCompiler import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.daemon.incremental.* +import org.jetbrains.kotlin.daemon.report.CompileServiceReporter +import org.jetbrains.kotlin.daemon.report.CompileServiceReporterImpl +import org.jetbrains.kotlin.daemon.report.CompileServiceReporterStreamAdapter +import org.jetbrains.kotlin.daemon.report.CompileServicesFacadeMessageCollector import org.jetbrains.kotlin.incremental.* -import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider -import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents -import org.jetbrains.kotlin.modules.Module -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.CompilationCanceledStatus -import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.utils.addToStdlib.check import java.io.BufferedOutputStream -import java.io.ByteArrayOutputStream import java.io.File import java.io.PrintStream import java.rmi.NoSuchObjectException @@ -99,7 +101,6 @@ class CompileServiceImpl( val timer: Timer, val onShutdown: () -> Unit ) : CompileService { - init { System.setProperty(KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true") } @@ -320,63 +321,98 @@ class CompileServiceImpl( } } - override fun serverSideJvmIC( + override fun compile( sessionId: Int, - args: Array, - servicesFacade: IncrementalCompilationServicesFacade, - compilerOutputStream: RemoteOutputStream, - serviceOutputStream: RemoteOutputStream, + compilerMode: CompileService.CompilerMode, + targetPlatform: CompileService.TargetPlatform, + compilerArguments: CommonCompilerArguments, + additionalCompilerArguments: AdditionalCompilerArguments, + servicesFacade: CompilerServicesFacadeBase, operationsTracer: RemoteOperationsTracer? ): CompileService.CallResult { - return doCompile(sessionId, args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, eventManager, profiler -> - val reporter = RemoteICReporter(servicesFacade) - val annotationFileUpdater = if (servicesFacade.hasAnnotationsFileUpdater()) RemoteAnnotationsFileUpdater(servicesFacade) else null + val messageCollector = CompileServicesFacadeMessageCollector(servicesFacade, additionalCompilerArguments) + val serviceReporter = CompileServiceReporterImpl(servicesFacade, additionalCompilerArguments) - // these flags do not have any effect on the compiler (only on caches, incremental compilation logic, jps plugin) - // so it's OK to just set them true - IncrementalCompilation.setIsEnabled(true) - IncrementalCompilation.setIsExperimental(true) - - val k2jvmArgs = K2JVMCompilerArguments() - (compiler[CompileService.TargetPlatform.JVM] as K2JVMCompiler).parseArguments(args, k2jvmArgs) - - val moduleFile = k2jvmArgs.module?.let(::File) - assert(moduleFile?.exists() ?: false) { "Module does not exist ${k2jvmArgs.module}" } - val renderer = MessageRenderer.XML - val messageCollector = PrintingMessageCollector(printStream, renderer, k2jvmArgs.verbose) - val filteringMessageCollector = FilteringMessageCollector(messageCollector) { it == CompilerMessageSeverity.ERROR } - - val parsedModule = ModuleXmlParser.parseModuleScript(k2jvmArgs.module, filteringMessageCollector) - val javaSourceRoots = parsedModule.modules.flatMapTo(HashSet()) { it.getJavaSourceRoots().map { File(it.path) } } - val allKotlinFiles = parsedModule.modules.flatMap { it.getSourceFiles().map(::File) } - k2jvmArgs.friendPaths = parsedModule.modules.flatMap(Module::getFriendPaths).toTypedArray() - - val changedFiles = if (servicesFacade.areFileChangesKnown()) { - ChangedFiles.Known(servicesFacade.modifiedFiles()!!, servicesFacade.deletedFiles()!!) - } - else { - ChangedFiles.Unknown() + return when (compilerMode) { + CompileService.CompilerMode.NON_INCREMENTAL_COMPILER -> { + doCompile(sessionId, serviceReporter, operationsTracer) { eventManger, profiler -> + execCompiler(targetPlatform, Services.EMPTY, compilerArguments, messageCollector) + } } + CompileService.CompilerMode.INCREMENTAL_COMPILER -> { + if (targetPlatform != CompileService.TargetPlatform.JVM) { + throw IllegalStateException("Incremental compilation is not supported for target platform: $targetPlatform") + } - val artifactChanges = RemoteArtifactChangesProvider(servicesFacade) - val changesRegistry = RemoteChangesRegostry(servicesFacade) + val k2jvmArgs = compilerArguments as K2JVMCompilerArguments + val gradleIncrementalArgs = additionalCompilerArguments as IncrementalCompilerArguments + val gradleIncrementalServicesFacade = servicesFacade as IncrementalCompilerServicesFacade - val workingDir = servicesFacade.workingDir() - val versions = commonCacheVersions(workingDir) + - customCacheVersion(servicesFacade.customCacheVersion(), servicesFacade.customCacheVersionFileName(), workingDir, forceEnable = true) + withIC { + doCompile(sessionId, serviceReporter, operationsTracer) { eventManger, profiler -> + execIncrementalCompiler(k2jvmArgs, gradleIncrementalArgs, gradleIncrementalServicesFacade, messageCollector) + } + } - try { - printStream.print(renderer.renderPreamble()) - IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions, reporter, annotationFileUpdater, - artifactChanges, changesRegistry) - .compile(allKotlinFiles, k2jvmArgs, messageCollector, { changedFiles }) - } - finally { - printStream.print(renderer.renderConclusion()) } + else -> throw IllegalStateException("Unknown compilation mode $compilerMode") } } + private fun execCompiler( + targetPlatform: CompileService.TargetPlatform, + services: Services, + args: CommonCompilerArguments, + messageCollector: MessageCollector + ): ExitCode = + when(targetPlatform) { + CompileService.TargetPlatform.JVM -> { + K2JVMCompiler().exec(messageCollector, services, args as K2JVMCompilerArguments) + } + CompileService.TargetPlatform.JS -> { + K2JSCompiler().exec(messageCollector, services, args as K2JSCompilerArguments) + } + CompileService.TargetPlatform.METADATA -> { + K2MetadataCompiler().exec(messageCollector, services, args as K2MetadataCompilerArguments) + } + } + + private fun execIncrementalCompiler( + k2jvmArgs: K2JVMCompilerArguments, + incrementalCompilerArgs: IncrementalCompilerArguments, + servicesFacade: IncrementalCompilerServicesFacade, + messageCollector: CompileServicesFacadeMessageCollector + ): ExitCode { + val reporter = RemoteICReporter(servicesFacade, incrementalCompilerArgs) + val annotationFileUpdater = if (servicesFacade.hasAnnotationsFileUpdater()) RemoteAnnotationsFileUpdater(servicesFacade) else null + + val moduleFile = k2jvmArgs.module?.let(::File) + assert(moduleFile?.exists() ?: false) { "Module does not exist ${k2jvmArgs.module}" } + + val temporaryMessageCollectorForModuleParsing = FilteringMessageCollector(messageCollector) { it != CompilerMessageSeverity.ERROR } + val parsedModule = ModuleXmlParser.parseModuleScript(k2jvmArgs.module, temporaryMessageCollectorForModuleParsing) + val javaSourceRoots = parsedModule.modules.flatMapTo(HashSet()) { it.getJavaSourceRoots().map { File(it.path) } } + val allKotlinFiles = parsedModule.modules.flatMap { it.getSourceFiles().map(::File) } + + val changedFiles = if (incrementalCompilerArgs.areFileChangesKnown) { + ChangedFiles.Known(incrementalCompilerArgs.modifiedFiles!!, incrementalCompilerArgs.deletedFiles!!) + } + else { + ChangedFiles.Unknown() + } + + val artifactChanges = RemoteArtifactChangesProvider(servicesFacade) + val changesRegistry = RemoteChangesRegostry(servicesFacade) + + val workingDir = incrementalCompilerArgs.workingDir + val versions = commonCacheVersions(workingDir) + + customCacheVersion(incrementalCompilerArgs.customCacheVersion, incrementalCompilerArgs.customCacheVersionFileName, workingDir, forceEnable = true) + + return IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions, reporter, annotationFileUpdater, + artifactChanges, changesRegistry) + .compile(allKotlinFiles, k2jvmArgs, messageCollector, { changedFiles }) + } + override fun leaseReplSession( aliveFlagPath: String?, targetPlatform: CompileService.TargetPlatform, @@ -599,6 +635,7 @@ class CompileServiceImpl( return res } + // todo: remove after remoteIncrementalCompile is removed private fun doCompile(sessionId: Int, args: Array, compilerMessagesStreamProxy: RemoteOutputStream, @@ -613,10 +650,14 @@ class CompileServiceImpl( val compilerMessagesStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(compilerMessagesStreamProxy, rpcProfiler), REMOTE_STREAM_BUFFER_SIZE)) val serviceOutputStream = PrintStream(BufferedOutputStream(RemoteOutputStreamClient(serviceOutputStreamProxy, rpcProfiler), REMOTE_STREAM_BUFFER_SIZE)) try { - CompileService.CallResult.Good( - checkedCompile(args, serviceOutputStream, rpcProfiler) { - body(compilerMessagesStream, eventManger, rpcProfiler).code - }) + val compileServiceReporter = CompileServiceReporterStreamAdapter(serviceOutputStream) + if (args.none()) + throw IllegalArgumentException("Error: empty arguments list.") + log.info("Starting compilation with args: " + args.joinToString(" ")) + val exitCode = checkedCompile(compileServiceReporter, rpcProfiler) { + body(compilerMessagesStream, eventManger, rpcProfiler).code + } + CompileService.CallResult.Good(exitCode) } finally { serviceOutputStream.flush() @@ -627,6 +668,28 @@ class CompileServiceImpl( } } + private fun doCompile(sessionId: Int, + compileServiceReporter: CompileServiceReporter, + operationsTracer: RemoteOperationsTracer?, + body: (EventManger, Profiler) -> ExitCode): CompileService.CallResult = + ifAlive { + withValidClientOrSessionProxy(sessionId) { session -> + operationsTracer?.before("compile") + val rpcProfiler = if (daemonOptions.reportPerf) WallAndThreadTotalProfiler() else DummyProfiler() + val eventManger = EventMangerImpl() + try { + val exitCode = checkedCompile(compileServiceReporter, rpcProfiler) { + body(eventManger, rpcProfiler).code + } + CompileService.CallResult.Good(exitCode) + } + finally { + eventManger.fireCompilationFinished() + operationsTracer?.after("compile") + } + } + } + private fun createCompileServices(facade: CompilerCallbackServicesFacade, eventManger: EventManger, rpcProfiler: Profiler): Services { val builder = Services.Builder() if (facade.hasIncrementalCaches() || facade.hasLookupTracker()) { @@ -639,12 +702,8 @@ class CompileServiceImpl( } - private fun checkedCompile(args: Array, serviceOut: PrintStream, rpcProfiler: Profiler, body: () -> R): R { + private fun checkedCompile(compileServiceReporter: CompileServiceReporter, rpcProfiler: Profiler, body: () -> R): R { try { - if (args.none()) - throw IllegalArgumentException("Error: empty arguments list.") - log.info("Starting compilation with args: " + args.joinToString(" ")) - val profiler = if (daemonOptions.reportPerf) WallAndThreadAndMemoryTotalProfiler(withGC = false) else DummyProfiler() val res = profiler.withMeasure(null, body) @@ -660,14 +719,14 @@ class CompileServiceImpl( val rpc = rpcProfiler.getTotalCounters() "PERF: Compile on daemon: ${pc.time.ms()} ms; thread: user ${pc.threadUserTime.ms()} ms, sys ${(pc.threadTime - pc.threadUserTime).ms()} ms; rpc: ${rpc.count} calls, ${rpc.time.ms()} ms, thread ${rpc.threadTime.ms()} ms; memory: ${endMem.kb()} kb (${"%+d".format(pc.memory.kb())} kb)".let { - serviceOut.println(it) + compileServiceReporter.info(it) log.info(it) } // this will only be reported if if appropriate (e.g. ByClass) profiler is used for ((obj, counters) in rpcProfiler.getCounters()) { "PERF: rpc by $obj: ${counters.count} calls, ${counters.time.ms()} ms, thread ${counters.threadTime.ms()} ms".let { - serviceOut.println(it) + compileServiceReporter.info(it) log.info(it) } } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteAnnotationsFileUpdater.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteAnnotationsFileUpdater.kt index 859f5d355e7..13068428547 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteAnnotationsFileUpdater.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteAnnotationsFileUpdater.kt @@ -18,12 +18,13 @@ package org.jetbrains.kotlin.daemon.incremental import org.jetbrains.kotlin.annotation.AnnotationFileUpdater import org.jetbrains.kotlin.cli.common.ExitCode +import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade import org.jetbrains.kotlin.incremental.ICReporter import org.jetbrains.kotlin.resolve.jvm.JvmClassName import java.io.File -internal class RemoteAnnotationsFileUpdater(private val servicesFacade: IncrementalCompilationServicesFacade) : AnnotationFileUpdater { +internal class RemoteAnnotationsFileUpdater(private val servicesFacade: IncrementalCompilerServicesFacade) : AnnotationFileUpdater { override fun updateAnnotations(outdatedClasses: Iterable) { servicesFacade.updateAnnotations(outdatedClasses.map { it.internalName }) } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteArtifactChangesProvider.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteArtifactChangesProvider.kt index 867a8ca827c..505abf43c90 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteArtifactChangesProvider.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteArtifactChangesProvider.kt @@ -16,12 +16,12 @@ package org.jetbrains.kotlin.daemon.incremental -import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade +import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade import org.jetbrains.kotlin.incremental.DirtyData import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider import java.io.File -class RemoteArtifactChangesProvider(private val servicesFacade: IncrementalCompilationServicesFacade) : ArtifactChangesProvider { +class RemoteArtifactChangesProvider(private val servicesFacade: IncrementalCompilerServicesFacade) : ArtifactChangesProvider { override fun getChanges(artifact: File, sinceTS: Long): Iterable? = servicesFacade.getChanges(artifact, sinceTS)?.map { it.toDirtyData() } } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteChangesRegostry.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteChangesRegostry.kt index de4397cddce..514474da7a7 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteChangesRegostry.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteChangesRegostry.kt @@ -16,11 +16,11 @@ package org.jetbrains.kotlin.daemon.incremental -import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade +import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade import org.jetbrains.kotlin.incremental.DirtyData import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry -internal class RemoteChangesRegostry(private val servicesFacade: IncrementalCompilationServicesFacade) : ChangesRegistry { +internal class RemoteChangesRegostry(private val servicesFacade: IncrementalCompilerServicesFacade) : ChangesRegistry { override fun unknownChanges(timestamp: Long) { servicesFacade.unknownChanges(timestamp) } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteICReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteICReporter.kt index 80463bf7a8f..5a30ab09868 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteICReporter.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteICReporter.kt @@ -17,20 +17,37 @@ package org.jetbrains.kotlin.daemon.incremental import org.jetbrains.kotlin.cli.common.ExitCode +import org.jetbrains.kotlin.daemon.report.FilteringReporterBase +import org.jetbrains.kotlin.daemon.common.CompilerServicesFacadeBase +import org.jetbrains.kotlin.daemon.common.AdditionalCompilerArguments import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade +import org.jetbrains.kotlin.daemon.common.ReportCategory +import org.jetbrains.kotlin.daemon.incremental.IncrementalCompilationSeverity.COMPILED_FILES +import org.jetbrains.kotlin.daemon.incremental.IncrementalCompilationSeverity.LOGGING import org.jetbrains.kotlin.incremental.ICReporter import java.io.File -internal class RemoteICReporter(private val servicesFacade: IncrementalCompilationServicesFacade) : ICReporter() { +internal class RemoteICReporter( + servicesFacade: CompilerServicesFacadeBase, + additionalCompilerArgs: AdditionalCompilerArguments +) : FilteringReporterBase(servicesFacade, additionalCompilerArgs, ReportCategory.INCREMENTAL_COMPILATION), ICReporter { override fun report(message: () -> String) { - if (servicesFacade.shouldReportIC()) { - servicesFacade.reportIC(message()) + if (shouldReport(LOGGING.value)) { + report(LOGGING.value, message()) } } - override fun reportCompileIteration(sourceFiles: Iterable, exitCode: ExitCode) { - if (servicesFacade.shouldReportIC()) { - servicesFacade.reportCompileIteration(sourceFiles, exitCode.code) + override fun reportCompileIteration(sourceFiles: Collection, exitCode: ExitCode) { + if (shouldReport(COMPILED_FILES.value)) { + report(COMPILED_FILES.value, message = null, attachment = ArrayList(sourceFiles)) } } +} + +/** + * See [RemoteICReporter] + */ +enum class IncrementalCompilationSeverity(val value: Int) { + COMPILED_FILES(0), + LOGGING(10) } \ No newline at end of file diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServiceReporter.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServiceReporter.kt new file mode 100644 index 00000000000..607f574ddef --- /dev/null +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServiceReporter.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.daemon.report + +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.daemon.common.AdditionalCompilerArguments +import org.jetbrains.kotlin.daemon.common.CompilerServicesFacadeBase +import org.jetbrains.kotlin.daemon.common.ReportCategory +import org.jetbrains.kotlin.daemon.report.FilteringReporterBase +import java.io.PrintStream + +// For messages of about compile daemon +internal interface CompileServiceReporter { + fun info(message: String) { + report(CompilerMessageSeverity.INFO, message) + } + + fun report(severity: CompilerMessageSeverity, message: String) +} + +internal class CompileServiceReporterStreamAdapter(private val out: PrintStream) : CompileServiceReporter { + override fun report(severity: CompilerMessageSeverity, message: String) { + out.print("[Kotlin daemon][$severity] $message") + } +} + +internal class CompileServiceReporterImpl( + servicesFacade: CompilerServicesFacadeBase, + additionalCompilerArguments: AdditionalCompilerArguments +) : FilteringReporterBase(servicesFacade, additionalCompilerArguments, ReportCategory.DAEMON_MESSAGE), CompileServiceReporter { + + override fun report(severity: CompilerMessageSeverity, message: String) { + report(severity.value, message) + } +} \ No newline at end of file diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServicesFacadeMessageCollector.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServicesFacadeMessageCollector.kt new file mode 100644 index 00000000000..f2aa8d9a244 --- /dev/null +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/CompileServicesFacadeMessageCollector.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.daemon.report + +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.daemon.common.AdditionalCompilerArguments +import org.jetbrains.kotlin.daemon.common.CompilerServicesFacadeBase +import org.jetbrains.kotlin.daemon.common.ReportCategory + +internal class CompileServicesFacadeMessageCollector( + private val servicesFacade: CompilerServicesFacadeBase, + additionalCompilerArguments: AdditionalCompilerArguments +) : MessageCollector { + private var hasErrors = false + private val reportingFilter = additionalCompilerArguments.reportingFilters.firstOrNull { it.category == ReportCategory.DAEMON_MESSAGE } + + override fun clear() { + hasErrors = false + } + + override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) { + if (reportingFilter != null && severity.value !in reportingFilter.severities) return + + hasErrors = hasErrors || severity == CompilerMessageSeverity.ERROR + servicesFacade.report(ReportCategory.DAEMON_MESSAGE, severity.value, message, location) + } + + override fun hasErrors(): Boolean = hasErrors +} \ No newline at end of file diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/FilteringReporterBase.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/FilteringReporterBase.kt new file mode 100644 index 00000000000..bf5e86c7712 --- /dev/null +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/report/FilteringReporterBase.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.daemon.report + +import org.jetbrains.kotlin.daemon.common.AdditionalCompilerArguments +import org.jetbrains.kotlin.daemon.common.CompilerServicesFacadeBase +import org.jetbrains.kotlin.daemon.common.ReportCategory +import java.io.Serializable + +internal open class FilteringReporterBase( + private val servicesFacade: CompilerServicesFacadeBase, + additionalCompilerArgs: AdditionalCompilerArguments, + private val reportCategory: ReportCategory +) { + private val reportingFilter = additionalCompilerArgs.reportingFilters.firstOrNull { it.category == reportCategory } + + protected fun report(severity: Int, message: String?, attachment: Serializable? = null) { + if (shouldReport(severity)) { + servicesFacade.report(reportCategory, severity, message, attachment) + } + } + + protected fun shouldReport(severity: Int): Boolean = + reportingFilter == null || severity in reportingFilter.severities +} \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt index ea562e88cf5..494b601ff0e 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt @@ -71,14 +71,14 @@ private object EmptyICReporter : ICReporter { } } -private inline fun withIC(fn: ()->Unit) { +inline fun withIC(fn: ()->R): R { val isEnabledBackup = IncrementalCompilation.isEnabled() val isExperimentalBackup = IncrementalCompilation.isExperimental() IncrementalCompilation.setIsEnabled(true) IncrementalCompilation.setIsExperimental(true) try { - fn() + return fn() } finally { IncrementalCompilation.setIsEnabled(isEnabledBackup) diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/KotlinStandaloneIncrementalCompilationTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/KotlinStandaloneIncrementalCompilationTest.kt index 15fa455f04e..608e553fead 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/KotlinStandaloneIncrementalCompilationTest.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/KotlinStandaloneIncrementalCompilationTest.kt @@ -128,7 +128,7 @@ class KotlinStandaloneIncrementalCompilationTest : TestWithWorkingDir() { override fun report(message: ()->String) { } - override fun reportCompileIteration(sourceFiles: Iterable, exitCode: ExitCode) { + override fun reportCompileIteration(sourceFiles: Collection, exitCode: ExitCode) { compiledSources.addAll(sourceFiles) resultExitCode = exitCode }