diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java
index 197f1321b19..a418738f581 100644
--- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java
@@ -152,6 +152,9 @@ public abstract class CLICompiler {
Disposer.dispose(rootDisposable);
}
}
+ catch (CompilationInterruptedException e) {
+ return e.exitCode;
+ }
catch (Throwable t) {
groupingCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(t),
CompilerMessageLocation.NO_LOCATION);
@@ -201,4 +204,12 @@ public abstract class CLICompiler {
return INTERNAL_ERROR;
}
}
+
+ public static class CompilationInterruptedException extends RuntimeException {
+ final ExitCode exitCode;
+
+ public CompilationInterruptedException(ExitCode exitCode) {
+ this.exitCode = exitCode;
+ }
+ }
}
diff --git a/plugins/annotation-collector/annotation-collector.iml b/plugins/annotation-collector/annotation-collector.iml
index 5d5a86f5f27..27a9e081763 100644
--- a/plugins/annotation-collector/annotation-collector.iml
+++ b/plugins/annotation-collector/annotation-collector.iml
@@ -14,7 +14,8 @@
-
+
+
\ No newline at end of file
diff --git a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt
index 482dc6bd936..8043e90d8bb 100644
--- a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt
+++ b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/AnnotationCollectorPlugin.kt
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.JetCallableDeclaration
import org.jetbrains.kotlin.psi.JetDeclaration
import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
import java.io.BufferedWriter
import java.io.File
import java.io.IOException
@@ -47,7 +48,9 @@ public object AnnotationCollectorConfigurationKeys {
public val ANNOTATION_FILTER_LIST: CompilerConfigurationKey> =
CompilerConfigurationKey.create>("annotation filter regular expressions")
public val OUTPUT_FILENAME: CompilerConfigurationKey =
- CompilerConfigurationKey.create("output file")
+ CompilerConfigurationKey.create("annotation file name")
+ public val STUBS_PATH: CompilerConfigurationKey =
+ CompilerConfigurationKey.create("stubs output directory")
}
public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
@@ -59,11 +62,14 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
public val OUTPUT_FILENAME_OPTION: CliOption =
CliOption("output", "", "File in which annotated declarations will be placed", required = false)
+
+ public val STUBS_PATH_OPTION: CliOption =
+ CliOption("stubs", "", "Output path for stubs.", required = false)
}
override val pluginId: String = ANNOTATION_COLLECTOR_COMPILER_PLUGIN_ID
- override val pluginOptions: Collection = listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION)
+ override val pluginOptions: Collection = listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION, STUBS_PATH_OPTION)
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
when (option) {
@@ -72,6 +78,7 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
configuration.put(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST, annotations)
}
OUTPUT_FILENAME_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME, value)
+ STUBS_PATH_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.STUBS_PATH, value)
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
}
}
@@ -81,11 +88,15 @@ public class AnnotationCollectorComponentRegistrar : ComponentRegistrar {
public override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
val annotationFilterList = configuration.get(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST)
val outputFilename = configuration.get(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME)
-
if (outputFilename != null) {
val collectorExtension = AnnotationCollectorExtension(annotationFilterList, outputFilename)
ClassBuilderInterceptorExtension.registerExtension(project, collectorExtension)
}
+
+ val stubs = configuration.get(AnnotationCollectorConfigurationKeys.STUBS_PATH)
+ if (stubs != null) {
+ AnalysisCompletedHandlerExtension.registerExtension(project, StubProducerExtension(File(stubs)))
+ }
}
}
diff --git a/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/StubProducerExtension.kt b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/StubProducerExtension.kt
new file mode 100644
index 00000000000..83858117f99
--- /dev/null
+++ b/plugins/annotation-collector/src/org/jetbrains/kotlin/annotation/StubProducerExtension.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2015 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.annotation
+
+import com.intellij.openapi.project.Project
+import org.jetbrains.kotlin.cli.common.CLICompiler
+import org.jetbrains.kotlin.cli.common.ExitCode
+import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAllTo
+import org.jetbrains.kotlin.codegen.*
+import org.jetbrains.kotlin.codegen.state.GenerationState
+import org.jetbrains.kotlin.codegen.state.Progress
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.psi.JetFile
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.BindingTraceContext
+import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
+import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
+import org.jetbrains.org.objectweb.asm.ClassWriter
+import java.io.File
+
+public class StubProducerExtension(val stubsOutputDir: File) : AnalysisCompletedHandlerExtension {
+
+ override fun analysisCompleted(project: Project, module: ModuleDescriptor, bindingContext: BindingContext, files: Collection) {
+ val forExtraDiagnostics = BindingTraceContext()
+
+ val generationState = GenerationState(
+ project,
+ StubClassBuilderFactory(),
+ Progress.DEAF,
+ module,
+ bindingContext,
+ files.toArrayList(),
+ /*disableCallAssertions =*/ false,
+ /*disableParamAssertions =*/ false,
+ GenerationState.GenerateClassFilter.GENERATE_ALL,
+ /*disableInline =*/ false,
+ /*disableOptimization =*/ false,
+ /*packagesWithObsoleteParts =*/ null,
+ /*moduleId =*/ null,
+ forExtraDiagnostics,
+ /*outDirectory =*/ null)
+
+ KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION)
+
+ if (!stubsOutputDir.exists()) stubsOutputDir.mkdirs()
+ generationState.getFactory().writeAllTo(stubsOutputDir)
+
+ generationState.destroy()
+ throw CLICompiler.CompilationInterruptedException(ExitCode.OK)
+ }
+}
+
+private class StubClassBuilderFactory : ClassBuilderFactory {
+
+ override fun getClassBuilderMode() = ClassBuilderMode.LIGHT_CLASSES
+
+ override fun newClassBuilder(origin: JvmDeclarationOrigin) = AbstractClassBuilder.Concrete(
+ ClassWriter(ClassWriter.COMPUTE_FRAMES or ClassWriter.COMPUTE_MAXS))
+
+ override fun asText(builder: ClassBuilder) = throw UnsupportedOperationException("BINARIES generator asked for text")
+
+ override fun asBytes(builder: ClassBuilder): ByteArray {
+ val visitor = builder.getVisitor() as ClassWriter
+ return visitor.toByteArray()
+ }
+
+ override fun close() {
+
+ }
+}
\ No newline at end of file