kapt: Light class stub producer in compiler
This commit is contained in:
@@ -152,6 +152,9 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
|||||||
Disposer.dispose(rootDisposable);
|
Disposer.dispose(rootDisposable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (CompilationInterruptedException e) {
|
||||||
|
return e.exitCode;
|
||||||
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
groupingCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(t),
|
groupingCollector.report(CompilerMessageSeverity.EXCEPTION, OutputMessageUtil.renderException(t),
|
||||||
CompilerMessageLocation.NO_LOCATION);
|
CompilerMessageLocation.NO_LOCATION);
|
||||||
@@ -201,4 +204,12 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
|||||||
return INTERNAL_ERROR;
|
return INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CompilationInterruptedException extends RuntimeException {
|
||||||
|
final ExitCode exitCode;
|
||||||
|
|
||||||
|
public CompilationInterruptedException(ExitCode exitCode) {
|
||||||
|
this.exitCode = exitCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
||||||
<orderEntry type="module" module-name="frontend.java" />
|
<orderEntry type="module" module-name="frontend.java" />
|
||||||
<orderEntry type="module" module-name="compiler-tests" scope="TEST" />
|
<orderEntry type="module" module-name="compiler-tests" scope="TEST" />
|
||||||
<orderEntry type="module" module-name="cli" scope="TEST" />
|
<orderEntry type="module" module-name="cli" />
|
||||||
<orderEntry type="library" scope="TEST" name="idea-full" level="project" />
|
<orderEntry type="library" scope="TEST" name="idea-full" level="project" />
|
||||||
|
<orderEntry type="module" module-name="light-classes" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
+14
-3
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.psi.JetCallableDeclaration
|
import org.jetbrains.kotlin.psi.JetCallableDeclaration
|
||||||
import org.jetbrains.kotlin.psi.JetDeclaration
|
import org.jetbrains.kotlin.psi.JetDeclaration
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
|
||||||
import java.io.BufferedWriter
|
import java.io.BufferedWriter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@@ -47,7 +48,9 @@ public object AnnotationCollectorConfigurationKeys {
|
|||||||
public val ANNOTATION_FILTER_LIST: CompilerConfigurationKey<List<String>> =
|
public val ANNOTATION_FILTER_LIST: CompilerConfigurationKey<List<String>> =
|
||||||
CompilerConfigurationKey.create<List<String>>("annotation filter regular expressions")
|
CompilerConfigurationKey.create<List<String>>("annotation filter regular expressions")
|
||||||
public val OUTPUT_FILENAME: CompilerConfigurationKey<String> =
|
public val OUTPUT_FILENAME: CompilerConfigurationKey<String> =
|
||||||
CompilerConfigurationKey.create<String>("output file")
|
CompilerConfigurationKey.create<String>("annotation file name")
|
||||||
|
public val STUBS_PATH: CompilerConfigurationKey<String> =
|
||||||
|
CompilerConfigurationKey.create<String>("stubs output directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
||||||
@@ -59,11 +62,14 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
|||||||
|
|
||||||
public val OUTPUT_FILENAME_OPTION: CliOption =
|
public val OUTPUT_FILENAME_OPTION: CliOption =
|
||||||
CliOption("output", "<path>", "File in which annotated declarations will be placed", required = false)
|
CliOption("output", "<path>", "File in which annotated declarations will be placed", required = false)
|
||||||
|
|
||||||
|
public val STUBS_PATH_OPTION: CliOption =
|
||||||
|
CliOption("stubs", "<path>", "Output path for stubs.", required = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val pluginId: String = ANNOTATION_COLLECTOR_COMPILER_PLUGIN_ID
|
override val pluginId: String = ANNOTATION_COLLECTOR_COMPILER_PLUGIN_ID
|
||||||
|
|
||||||
override val pluginOptions: Collection<CliOption> = listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION)
|
override val pluginOptions: Collection<CliOption> = listOf(ANNOTATION_FILTER_LIST_OPTION, OUTPUT_FILENAME_OPTION, STUBS_PATH_OPTION)
|
||||||
|
|
||||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
||||||
when (option) {
|
when (option) {
|
||||||
@@ -72,6 +78,7 @@ public class AnnotationCollectorCommandLineProcessor : CommandLineProcessor {
|
|||||||
configuration.put(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST, annotations)
|
configuration.put(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST, annotations)
|
||||||
}
|
}
|
||||||
OUTPUT_FILENAME_OPTION -> configuration.put(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME, value)
|
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}")
|
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,11 +88,15 @@ public class AnnotationCollectorComponentRegistrar : ComponentRegistrar {
|
|||||||
public override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
public override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||||
val annotationFilterList = configuration.get(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST)
|
val annotationFilterList = configuration.get(AnnotationCollectorConfigurationKeys.ANNOTATION_FILTER_LIST)
|
||||||
val outputFilename = configuration.get(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME)
|
val outputFilename = configuration.get(AnnotationCollectorConfigurationKeys.OUTPUT_FILENAME)
|
||||||
|
|
||||||
if (outputFilename != null) {
|
if (outputFilename != null) {
|
||||||
val collectorExtension = AnnotationCollectorExtension(annotationFilterList, outputFilename)
|
val collectorExtension = AnnotationCollectorExtension(annotationFilterList, outputFilename)
|
||||||
ClassBuilderInterceptorExtension.registerExtension(project, collectorExtension)
|
ClassBuilderInterceptorExtension.registerExtension(project, collectorExtension)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val stubs = configuration.get(AnnotationCollectorConfigurationKeys.STUBS_PATH)
|
||||||
|
if (stubs != null) {
|
||||||
|
AnalysisCompletedHandlerExtension.registerExtension(project, StubProducerExtension(File(stubs)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+84
@@ -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<JetFile>) {
|
||||||
|
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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user