From 86aa82da6ccaa46f2cb0afa6a7f5f4ee6c9bd1e2 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Sun, 30 Oct 2016 02:34:40 +0300 Subject: [PATCH] Kapt3: Minor: Refactor kapt3 module (move/rename) --- .../kotlin/generators/tests/GenerateTests.kt | 4 +- .../Kapt3AnalysisCompletedHandlerExtension.kt | 220 ------------------ .../kotlin/kapt3/Kapt3BuilderFactory.kt | 73 ++++++ .../jetbrains/kotlin/kapt3/Kapt3Extension.kt | 200 ++++++++++++++++ .../org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt | 5 +- .../org/jetbrains/kotlin/kapt3/KaptContext.kt | 55 +++++ .../org/jetbrains/kotlin/kapt3/KaptRunner.kt | 150 ------------ .../kotlin/kapt3/annotationProcessing.kt | 90 +++++++ .../kotlin/kapt3/diagnostic/KaptError.kt | 36 +++ .../kapt3/{ => javac}/KaptJavaCompiler.kt | 4 +- .../KaptJavaFileObject.kt} | 6 +- .../kotlin/kapt3/{ => javac}/KaptTreeMaker.kt | 20 +- .../ClassFileToSourceStubConverter.kt} | 116 +++------ .../{ => stubs}/SignatureParserVisitor.kt | 35 +-- .../kotlin/kapt3/stubs/parseParameters.kt | 62 +++++ .../kapt3/{Logger.kt => util/KaptLogger.kt} | 4 +- .../jetbrains/kotlin/kapt3/util/asmUtils.kt | 33 +++ .../{utils.kt => util/javacListUtils.kt} | 1 + .../kapt3/test/AbstractKotlinKapt3Test.kt | 41 ++-- ...leToSourceStubConverterTestGenerated.java} | 2 +- .../kotlin/kapt3/test/KaptRunnerTest.kt | 42 ++-- 21 files changed, 661 insertions(+), 538 deletions(-) delete mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3AnalysisCompletedHandlerExtension.kt create mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3BuilderFactory.kt create mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt create mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt delete mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptRunner.kt create mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/annotationProcessing.kt create mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/diagnostic/KaptError.kt rename plugins/kapt3/src/org/jetbrains/kotlin/kapt3/{ => javac}/KaptJavaCompiler.kt (91%) rename plugins/kapt3/src/org/jetbrains/kotlin/kapt3/{SyntheticJavaFileObject.kt => javac/KaptJavaFileObject.kt} (96%) rename plugins/kapt3/src/org/jetbrains/kotlin/kapt3/{ => javac}/KaptTreeMaker.kt (77%) rename plugins/kapt3/src/org/jetbrains/kotlin/kapt3/{JCTreeConverter.kt => stubs/ClassFileToSourceStubConverter.kt} (77%) rename plugins/kapt3/src/org/jetbrains/kotlin/kapt3/{ => stubs}/SignatureParserVisitor.kt (89%) create mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/parseParameters.kt rename plugins/kapt3/src/org/jetbrains/kotlin/kapt3/{Logger.kt => util/KaptLogger.kt} (92%) create mode 100644 plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt rename plugins/kapt3/src/org/jetbrains/kotlin/kapt3/{utils.kt => util/javacListUtils.kt} (99%) rename plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/{JCTreeConverterTestGenerated.java => ClassFileToSourceStubConverterTestGenerated.java} (96%) diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index f4e3447ac0e..7263ef942dc 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -136,7 +136,7 @@ import org.jetbrains.kotlin.js.test.semantics.* import org.jetbrains.kotlin.jvm.compiler.* import org.jetbrains.kotlin.jvm.runtime.AbstractJvm8RuntimeDescriptorLoaderTest import org.jetbrains.kotlin.jvm.runtime.AbstractJvmRuntimeDescriptorLoaderTest -import org.jetbrains.kotlin.kapt3.test.AbstractJCTreeConverterTest +import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTest import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptRunnerTest import org.jetbrains.kotlin.kdoc.AbstractKDocLexerTest import org.jetbrains.kotlin.lang.resolve.android.test.AbstractAndroidBoxTest @@ -1140,7 +1140,7 @@ fun main(args: Array) { } testGroup("plugins/kapt3/test", "plugins/kapt3/testData") { - testClass { + testClass { model("converter") } diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3AnalysisCompletedHandlerExtension.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3AnalysisCompletedHandlerExtension.kt deleted file mode 100644 index b6cfecb7f92..00000000000 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3AnalysisCompletedHandlerExtension.kt +++ /dev/null @@ -1,220 +0,0 @@ -/* - * 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.kapt3 - -import com.intellij.openapi.project.Project -import com.sun.tools.javac.tree.JCTree -import org.jetbrains.kotlin.analyzer.AnalysisResult -import org.jetbrains.kotlin.codegen.* -import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.kapt3.diagnostic.ErrorsKapt3 -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin -import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension -import org.jetbrains.org.objectweb.asm.FieldVisitor -import org.jetbrains.org.objectweb.asm.MethodVisitor -import org.jetbrains.org.objectweb.asm.tree.ClassNode -import org.jetbrains.org.objectweb.asm.tree.FieldNode -import org.jetbrains.org.objectweb.asm.tree.MethodNode -import java.io.File -import java.net.URLClassLoader -import java.util.* -import javax.annotation.processing.Processor -import com.sun.tools.javac.util.List as JavacList - -class Kapt3AnalysisCompletedHandlerExtension( - val annotationProcessingClasspath: List, - val javaSourceRoots: List, - val sourcesOutputDir: File, - val classFilesOutputDir: File, - val stubsOutputDir: File?, - val options: Map, //TODO - val aptOnly: Boolean, - val pluginInitializedTime: Long, - val logger: Logger -) : AnalysisCompletedHandlerExtension { - private var annotationProcessingComplete = false - - override fun analysisCompleted( - project: Project, - module: ModuleDescriptor, - bindingTrace: BindingTrace, - files: Collection - ): AnalysisResult? { - if (annotationProcessingComplete) { - return null - } - - annotationProcessingComplete = true - - fun doNotGenerateCode() = AnalysisResult.Companion.success(BindingContext.EMPTY, module, shouldGenerateCode = false) - - if (files.isEmpty()) { - logger.info("No Kotlin source files, aborting") - return if (aptOnly) doNotGenerateCode() else null - } - - logger.info { "Initial analysis took ${System.currentTimeMillis() - pluginInitializedTime} ms" } - logger.info { "Kotlin files: " + files.map { it.virtualFile?.name ?: "" } } - - val processors = loadProcessors(annotationProcessingClasspath) - if (processors.isEmpty()) { - logger.info("No annotation processors available, aborting") - return if (aptOnly) doNotGenerateCode() else null - } - - logger.info { "Annotation processors: " + processors.joinToString { it.javaClass.canonicalName } } - - val builderFactory = Kapt3BuilderFactory() - - val generationState = GenerationState( - project, - builderFactory, - module, - bindingTrace.bindingContext, - files.toList(), - disableCallAssertions = false, - disableParamAssertions = false) - - try { - val (stubCompilationTime) = measureTimeMillis { - KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) - } - - val compiledClasses = builderFactory.compiledClasses - val origins = builderFactory.origins - logger.info { "Compiled classes: " + compiledClasses.joinToString { it.name } } - - val javaFilesFromJavaSourceRoots = javaSourceRoots.flatMap { - root -> root.walk().filter { it.isFile && it.extension == "java" }.toList() - } - logger.info { "Java source files: " + javaFilesFromJavaSourceRoots.joinToString { it.canonicalPath } } - - val kaptRunner = KaptRunner(logger) - - val (jcStubGenerationTime, jcCompilationUnitsForKotlinClasses) = measureTimeMillis { - val treeConverter = JCTreeConverter(kaptRunner.context, generationState.typeMapper, compiledClasses, origins) - treeConverter.convert() - } - - logger.info { "Stubs for Kotlin classes: " + jcCompilationUnitsForKotlinClasses.joinToString { it.sourcefile.name } } - - logger.info { "Stubs compilation took $stubCompilationTime ms" } - logger.info { "Java stub generation took $jcStubGenerationTime ms" } - - if (stubsOutputDir != null) { - saveStubs(stubsOutputDir, jcCompilationUnitsForKotlinClasses) - } - - val (annotationProcessingTime) = measureTimeMillis { - kaptRunner.doAnnotationProcessing( - javaFilesFromJavaSourceRoots, processors, - annotationProcessingClasspath, sourcesOutputDir, classFilesOutputDir, jcCompilationUnitsForKotlinClasses) - } - - logger.info { "Annotation processing took $annotationProcessingTime ms" } - } catch (thr: Throwable) { - if (thr !is KaptError || thr.kind != KaptError.Kind.ERROR_RAISED) { - logger.exception(thr) - } - bindingTrace.report(ErrorsKapt3.KAPT3_PROCESSING_ERROR.on(files.first())) - return null // Compilation will be aborted anyway because of the error above - } finally { - generationState.destroy() - } - - return if (aptOnly) { - doNotGenerateCode() - } else { - AnalysisResult.RetryWithAdditionalJavaRoots( - bindingTrace.bindingContext, - module, - listOf(sourcesOutputDir), - addToEnvironment = true) - } - } - - private inline fun measureTimeMillis(block: () -> T) : Pair { - val start = System.currentTimeMillis() - val result = block() - return Pair(System.currentTimeMillis() - start, result) - } - - private fun saveStubs(outputDir: File, stubs: JavacList) { - for (stub in stubs) { - val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString() - - val packageName = stub.packageName?.toString() ?: "" - val packageDir = if (packageName.isEmpty()) outputDir else File(outputDir, packageName.replace('.', '/')) - packageDir.mkdirs() - File(packageDir, className + ".java").writeText(stub.toString()) - } - } - - private fun loadProcessors(classpath: List): List { - val classLoader = URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray()) - return ServiceLoader.load(Processor::class.java, classLoader).toList() - } -} - -class Kapt3BuilderFactory : ClassBuilderFactory { - val compiledClasses = mutableListOf() - val origins = mutableMapOf() - - override fun getClassBuilderMode(): ClassBuilderMode = ClassBuilderMode.KAPT3 - - override fun newClassBuilder(origin: JvmDeclarationOrigin): AbstractClassBuilder.Concrete { - val classNode = ClassNode() - compiledClasses += classNode - origins.put(classNode, origin) - - return object : AbstractClassBuilder.Concrete(classNode) { - override fun newField( - origin: JvmDeclarationOrigin, - access: Int, - name: String, - desc: String, - signature: String?, - value: Any? - ): FieldVisitor { - val fieldNode = super.newField(origin, access, name, desc, signature, value) as FieldNode - origins.put(fieldNode, origin) - return fieldNode - } - - override fun newMethod( - origin: JvmDeclarationOrigin, - access: Int, - name: String, - desc: String, - signature: String?, - exceptions: Array? - ): MethodVisitor { - val methodNode = super.newMethod(origin, access, name, desc, signature, exceptions) as MethodNode - origins.put(methodNode, origin) - return methodNode - } - } - } - - override fun asText(builder: ClassBuilder) = throw UnsupportedOperationException() - override fun asBytes(builder: ClassBuilder) = throw UnsupportedOperationException() - override fun close() {} -} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3BuilderFactory.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3BuilderFactory.kt new file mode 100644 index 00000000000..cc5048f81b7 --- /dev/null +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3BuilderFactory.kt @@ -0,0 +1,73 @@ +/* + * 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.kapt3 + +import org.jetbrains.kotlin.codegen.AbstractClassBuilder +import org.jetbrains.kotlin.codegen.ClassBuilder +import org.jetbrains.kotlin.codegen.ClassBuilderFactory +import org.jetbrains.kotlin.codegen.ClassBuilderMode +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin +import org.jetbrains.org.objectweb.asm.FieldVisitor +import org.jetbrains.org.objectweb.asm.MethodVisitor +import org.jetbrains.org.objectweb.asm.tree.ClassNode +import org.jetbrains.org.objectweb.asm.tree.FieldNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode + +class Kapt3BuilderFactory : ClassBuilderFactory { + val compiledClasses = mutableListOf() + val origins = mutableMapOf() + + override fun getClassBuilderMode(): ClassBuilderMode = ClassBuilderMode.KAPT3 + + override fun newClassBuilder(origin: JvmDeclarationOrigin): AbstractClassBuilder.Concrete { + val classNode = ClassNode() + compiledClasses += classNode + origins.put(classNode, origin) + + return object : AbstractClassBuilder.Concrete(classNode) { + override fun newField( + origin: JvmDeclarationOrigin, + access: Int, + name: String, + desc: String, + signature: String?, + value: Any? + ): FieldVisitor { + val fieldNode = super.newField(origin, access, name, desc, signature, value) as FieldNode + origins.put(fieldNode, origin) + return fieldNode + } + + override fun newMethod( + origin: JvmDeclarationOrigin, + access: Int, + name: String, + desc: String, + signature: String?, + exceptions: Array? + ): MethodVisitor { + val methodNode = super.newMethod(origin, access, name, desc, signature, exceptions) as MethodNode + origins.put(methodNode, origin) + return methodNode + } + } + } + + override fun asText(builder: ClassBuilder) = throw UnsupportedOperationException() + override fun asBytes(builder: ClassBuilder) = throw UnsupportedOperationException() + override fun close() {} +} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt new file mode 100644 index 00000000000..51e2558836b --- /dev/null +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt @@ -0,0 +1,200 @@ +/* + * 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.kapt3 + +import com.intellij.openapi.project.Project +import com.sun.tools.javac.tree.JCTree +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit +import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.kapt3.diagnostic.ErrorsKapt3 +import org.jetbrains.kotlin.kapt3.diagnostic.KaptError +import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter +import org.jetbrains.kotlin.kapt3.util.KaptLogger +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension +import java.io.File +import java.net.URLClassLoader +import java.util.* +import javax.annotation.processing.Processor +import com.sun.tools.javac.util.List as JavacList + +class Kapt3Extension( + val annotationProcessingClasspath: List, + val javaSourceRoots: List, + val sourcesOutputDir: File, + val classFilesOutputDir: File, + val stubsOutputDir: File?, + val options: Map, //TODO + val aptOnly: Boolean, + val pluginInitializedTime: Long, + val logger: KaptLogger +) : AnalysisCompletedHandlerExtension { + private var annotationProcessingComplete = false + + private fun setAnnotationProcessingComplete(): Boolean { + if (annotationProcessingComplete) return true + + annotationProcessingComplete = true + return false + } + + override fun analysisCompleted( + project: Project, + module: ModuleDescriptor, + bindingTrace: BindingTrace, + files: Collection + ): AnalysisResult? { + if (setAnnotationProcessingComplete()) return null + + fun doNotGenerateCode() = AnalysisResult.Companion.success(BindingContext.EMPTY, module, shouldGenerateCode = false) + + if (files.isEmpty()) { + logger.info("No Kotlin source files, aborting") + return if (aptOnly) doNotGenerateCode() else null + } + + logger.info { "Initial analysis took ${System.currentTimeMillis() - pluginInitializedTime} ms" } + logger.info { "Kotlin files to compile: " + files.map { it.virtualFile?.name ?: "" } } + + val processors = loadProcessors(annotationProcessingClasspath) + if (processors.isEmpty()) return if (aptOnly) doNotGenerateCode() else null + + val (kaptContext, generationState) = compileStubs(project, module, bindingTrace.bindingContext, files.toList()) + + try { + val javaSourceFiles = collectJavaSourceFiles() + val kotlinSourceStubs = generateKotlinSourceStubs(kaptContext, generationState.typeMapper) + + val (annotationProcessingTime) = measureTimeMillis { + kaptContext.doAnnotationProcessing( + javaSourceFiles, processors, + annotationProcessingClasspath, sourcesOutputDir, classFilesOutputDir, kotlinSourceStubs) + } + + logger.info { "Annotation processing took $annotationProcessingTime ms" } + } catch (thr: Throwable) { + if (thr !is KaptError || thr.kind != KaptError.Kind.ERROR_RAISED) { + logger.exception(thr) + } + bindingTrace.report(ErrorsKapt3.KAPT3_PROCESSING_ERROR.on(files.first())) + return null // Compilation will be aborted anyway because of the error above + } finally { + generationState.destroy() + kaptContext.close() + } + + return if (aptOnly) { + doNotGenerateCode() + } else { + AnalysisResult.RetryWithAdditionalJavaRoots( + bindingTrace.bindingContext, + module, + listOf(sourcesOutputDir), + addToEnvironment = true) + } + } + + private fun compileStubs( + project: Project, + module: ModuleDescriptor, + bindingContext: BindingContext, + files: List + ): Pair { + val builderFactory = Kapt3BuilderFactory() + + val generationState = GenerationState( + project, + builderFactory, + module, + bindingContext, + files, + CompilerConfiguration.EMPTY) + + val (classFilesCompilationTime) = measureTimeMillis { + KotlinCodegenFacade.compileCorrectFiles(generationState, CompilationErrorHandler.THROW_EXCEPTION) + } + + val compiledClasses = builderFactory.compiledClasses + val origins = builderFactory.origins + + logger.info { "Stubs compilation took $classFilesCompilationTime ms" } + logger.info { "Compiled classes: " + compiledClasses.joinToString { it.name } } + + return Pair(KaptContext(logger, compiledClasses, origins), generationState) + } + + private fun generateKotlinSourceStubs(kaptContext: KaptContext, typeMapper: KotlinTypeMapper): JavacList { + val (stubGenerationTime, kotlinSourceStubs) = measureTimeMillis { + ClassFileToSourceStubConverter(kaptContext, typeMapper).convert() + } + + logger.info { "Java stub generation took $stubGenerationTime ms" } + logger.info { "Stubs for Kotlin classes: " + kotlinSourceStubs.joinToString { it.sourcefile.name } } + + if (stubsOutputDir != null) { + saveStubs(stubsOutputDir, kotlinSourceStubs) + } + + return kotlinSourceStubs + } + + private fun saveStubs(outputDir: File, stubs: JavacList) { + for (stub in stubs) { + val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString() + + val packageName = stub.packageName?.toString() ?: "" + val packageDir = if (packageName.isEmpty()) outputDir else File(outputDir, packageName.replace('.', '/')) + packageDir.mkdirs() + File(packageDir, className + ".java").writeText(stub.toString()) + } + } + + private fun collectJavaSourceFiles(): List { + val javaFilesFromJavaSourceRoots = javaSourceRoots.flatMap { + root -> root.walk().filter { it.isFile && it.extension == "java" }.toList() + } + logger.info { "Java source files: " + javaFilesFromJavaSourceRoots.joinToString { it.canonicalPath } } + + return javaFilesFromJavaSourceRoots + } + + private fun loadProcessors(classpath: List): List { + val classLoader = URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray()) + val processors = ServiceLoader.load(Processor::class.java, classLoader).toList() + + if (processors.isEmpty()) { + logger.info("No annotation processors available, aborting") + } else { + logger.info { "Annotation processors: " + processors.joinToString { it.javaClass.canonicalName } } + } + + return processors + } +} + +private inline fun measureTimeMillis(block: () -> T) : Pair { + val start = System.currentTimeMillis() + val result = block() + return Pair(System.currentTimeMillis() - start, result) +} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt index 70187b263fb..91c2cfce6f5 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.config.CompilerConfigurationKey import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.kapt3.diagnostic.DefaultErrorMessagesKapt3 +import org.jetbrains.kotlin.kapt3.util.KaptLogger import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension import java.io.File @@ -139,7 +140,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar { Extensions.getRootArea().getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME).registerExtension(DefaultErrorMessagesKapt3()) - val logger = Logger(isVerbose) + val logger = KaptLogger(isVerbose) if (isVerbose) { logger.info("Kapt3 is enabled.") logger.info("Do annotation processing only: $isAptOnly") @@ -151,7 +152,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar { logger.info("Options: $apOptions") } - val kapt3AnalysisCompletedHandlerExtension = Kapt3AnalysisCompletedHandlerExtension( + val kapt3AnalysisCompletedHandlerExtension = Kapt3Extension( classpath, javaSourceRoots, sourcesOutputDir, classFilesOutputDir, stubsOutputDir, apOptions, isAptOnly, System.currentTimeMillis(), logger) AnalysisCompletedHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension) diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt new file mode 100644 index 00000000000..2aae5adfd19 --- /dev/null +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptContext.kt @@ -0,0 +1,55 @@ +/* + * 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.kapt3 + +import com.sun.tools.javac.file.JavacFileManager +import com.sun.tools.javac.main.JavaCompiler +import com.sun.tools.javac.util.Context +import com.sun.tools.javac.util.Options +import org.jetbrains.kotlin.kapt3.javac.KaptJavaCompiler +import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker +import org.jetbrains.kotlin.kapt3.util.KaptLogger +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin +import org.jetbrains.org.objectweb.asm.tree.ClassNode +import javax.tools.JavaFileManager + +class KaptContext( + val logger: KaptLogger, + val compiledClasses: List, + val origins: Map +) { + val context = Context() + val compiler: KaptJavaCompiler + val fileManager: JavacFileManager + val options: Options + + init { + JavacFileManager.preRegister(context) + KaptTreeMaker.preRegister(context) + KaptJavaCompiler.preRegister(context) + + fileManager = context.get(JavaFileManager::class.java) as JavacFileManager + compiler = JavaCompiler.instance(context) as KaptJavaCompiler + + options = Options.instance(context) + } + + fun close() { + compiler.close() + fileManager.close() + } +} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptRunner.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptRunner.kt deleted file mode 100644 index 797b577112f..00000000000 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptRunner.kt +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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.kapt3 - -import com.sun.tools.javac.comp.CompileStates -import com.sun.tools.javac.file.JavacFileManager -import com.sun.tools.javac.main.JavaCompiler -import com.sun.tools.javac.main.Option -import com.sun.tools.javac.processing.AnnotationProcessingError -import com.sun.tools.javac.processing.JavacFiler -import com.sun.tools.javac.processing.JavacMessager -import com.sun.tools.javac.processing.JavacProcessingEnvironment -import com.sun.tools.javac.tree.JCTree -import com.sun.tools.javac.util.Context -import com.sun.tools.javac.util.Log -import com.sun.tools.javac.util.Options -import java.io.File -import javax.annotation.processing.Processor -import javax.tools.JavaFileManager -import com.sun.tools.javac.util.List as JavacList - -class KaptError : RuntimeException { - val kind: Kind - - enum class Kind(val message: String) { - JAVA_FILE_PARSING_ERROR("Java file parsing error"), - EXCEPTION("Exception while annotation processing"), - ERROR_RAISED("Error while annotation processing"), - UNKNOWN("Unknown error while annotation processing") - } - - constructor(kind: Kind) : super(kind.message) { - this.kind = kind - } - - constructor(kind: Kind, cause: Throwable) : super(kind.message, cause) { - this.kind = kind - } -} - -class KaptRunner(val logger: Logger) { - val context = Context() - val compiler: KaptJavaCompiler - val fileManager: JavacFileManager - private val options: Options - - init { - JavacFileManager.preRegister(context) - KaptTreeMaker.preRegister(context) - KaptJavaCompiler.preRegister(context) - - fileManager = context.get(JavaFileManager::class.java) as JavacFileManager - compiler = JavaCompiler.instance(context) as KaptJavaCompiler - - options = Options.instance(context) - } - - fun close() { - compiler.close() - fileManager.close() - } - - fun parseJavaFiles( - javaSourceFiles: List, - classpath: List - ): JavacList { - classpath.forEach { options.put(Option.CLASSPATH, it.canonicalPath) } - - val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager - - try { - val javaFileObjects = fileManager.getJavaFileObjectsFromFiles(javaSourceFiles) - return compiler.parseFiles(javaFileObjects) - } finally { - fileManager.close() - compiler.close() - } - } - - fun doAnnotationProcessing( - javaSourceFiles: List, - processors: List, - classpath: List, - sourcesOutputDir: File, - classesOutputDir: File, - additionalSources: JavacList = JavacList.nil() - ) { - options.put(Option.PROC, "only") // Only process annotations - options.put(Option.CLASSPATH, classpath.joinToString(File.pathSeparator) { it.canonicalPath }) - options.put(Option.S, sourcesOutputDir.canonicalPath) - options.put(Option.D, classesOutputDir.canonicalPath) - - val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager - val processingEnvironment = JavacProcessingEnvironment.instance(context) - - try { - compiler.initProcessAnnotations(processors) - - val javaFileObjects = fileManager.getJavaFileObjectsFromFiles(javaSourceFiles) - val parsedJavaFiles = compiler.parseFiles(javaFileObjects) - if (compiler.shouldStop(CompileStates.CompileState.PARSE)) { - throw KaptError(KaptError.Kind.JAVA_FILE_PARSING_ERROR) - } - - val log = Log.instance(context) - val errorCountBeforeAp = log.nerrors - val warningsBeforeAp = log.nwarnings - - val compilerAfterAnnotationProcessing: JavaCompiler? = null - try { - compiler.processAnnotations(compiler.enterTrees(parsedJavaFiles + additionalSources)) - } catch (e: AnnotationProcessingError) { - throw KaptError(KaptError.Kind.EXCEPTION, e.cause ?: e) - } - - val filer = processingEnvironment.filer as JavacFiler - val errorCount = Math.max(log.nerrors, errorCountBeforeAp) - val warningCount = log.nwarnings - warningsBeforeAp - - logger.info { "Annotation processing complete, errors: $errorCount, warnings: $warningCount" } - if (logger.isVerbose) { - filer.displayState() - } - - if (log.nerrors > 0) { - throw KaptError(KaptError.Kind.ERROR_RAISED) - } - - compilerAfterAnnotationProcessing?.close() - } finally { - processingEnvironment.close() - compiler.close() - fileManager.close() - } - } -} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/annotationProcessing.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/annotationProcessing.kt new file mode 100644 index 00000000000..48a1e15d9e0 --- /dev/null +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/annotationProcessing.kt @@ -0,0 +1,90 @@ +/* + * 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.kapt3 + +import com.sun.tools.javac.comp.CompileStates +import com.sun.tools.javac.file.JavacFileManager +import com.sun.tools.javac.main.JavaCompiler +import com.sun.tools.javac.main.Option +import com.sun.tools.javac.processing.AnnotationProcessingError +import com.sun.tools.javac.processing.JavacFiler +import com.sun.tools.javac.processing.JavacProcessingEnvironment +import com.sun.tools.javac.tree.JCTree +import com.sun.tools.javac.util.Log +import org.jetbrains.kotlin.kapt3.diagnostic.KaptError +import java.io.File +import javax.annotation.processing.Processor +import javax.tools.JavaFileManager +import com.sun.tools.javac.util.List as JavacList + +fun KaptContext.doAnnotationProcessing( + javaSourceFiles: List, + processors: List, + classpath: List, + sourcesOutputDir: File, + classesOutputDir: File, + additionalSources: JavacList = JavacList.nil() +) { + with (options) { + put(Option.PROC, "only") // Only process annotations + put(Option.CLASSPATH, classpath.joinToString(File.pathSeparator) { it.canonicalPath }) + put(Option.S, sourcesOutputDir.canonicalPath) + put(Option.D, classesOutputDir.canonicalPath) + } + + val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager + val processingEnvironment = JavacProcessingEnvironment.instance(context) + + try { + compiler.initProcessAnnotations(processors) + + val javaFileObjects = fileManager.getJavaFileObjectsFromFiles(javaSourceFiles) + val parsedJavaFiles = compiler.parseFiles(javaFileObjects) + if (compiler.shouldStop(CompileStates.CompileState.PARSE)) { + throw KaptError(KaptError.Kind.JAVA_FILE_PARSING_ERROR) + } + + val log = Log.instance(context) + val errorCountBeforeAp = log.nerrors + val warningsBeforeAp = log.nwarnings + + val compilerAfterAnnotationProcessing: JavaCompiler? = null + try { + compiler.processAnnotations(compiler.enterTrees(parsedJavaFiles + additionalSources)) + } catch (e: AnnotationProcessingError) { + throw KaptError(KaptError.Kind.EXCEPTION, e.cause ?: e) + } + + val filer = processingEnvironment.filer as JavacFiler + val errorCount = Math.max(log.nerrors, errorCountBeforeAp) + val warningCount = log.nwarnings - warningsBeforeAp + + logger.info { "Annotation processing complete, errors: $errorCount, warnings: $warningCount" } + if (logger.isVerbose) { + filer.displayState() + } + + if (log.nerrors > 0) { + throw KaptError(KaptError.Kind.ERROR_RAISED) + } + + compilerAfterAnnotationProcessing?.close() + } finally { + processingEnvironment.close() + this@doAnnotationProcessing.close() + } +} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/diagnostic/KaptError.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/diagnostic/KaptError.kt new file mode 100644 index 00000000000..c082fe9e96b --- /dev/null +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/diagnostic/KaptError.kt @@ -0,0 +1,36 @@ +/* + * 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.kapt3.diagnostic + +class KaptError : RuntimeException { + val kind: Kind + + enum class Kind(val message: String) { + JAVA_FILE_PARSING_ERROR("Java file parsing error"), + EXCEPTION("Exception while annotation processing"), + ERROR_RAISED("Error while annotation processing"), + UNKNOWN("Unknown error while annotation processing") + } + + constructor(kind: Kind) : super(kind.message) { + this.kind = kind + } + + constructor(kind: Kind, cause: Throwable) : super(kind.message, cause) { + this.kind = kind + } +} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptJavaCompiler.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaCompiler.kt similarity index 91% rename from plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptJavaCompiler.kt rename to plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaCompiler.kt index 4adc7cb5deb..4d226cede67 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptJavaCompiler.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaCompiler.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.kapt3 +package org.jetbrains.kotlin.kapt3.javac import com.sun.tools.javac.comp.CompileStates import com.sun.tools.javac.main.JavaCompiler @@ -24,7 +24,7 @@ class KaptJavaCompiler(context: Context) : JavaCompiler(context) { public override fun shouldStop(cs: CompileStates.CompileState) = super.shouldStop(cs) companion object { - fun preRegister(context: Context) { + internal fun preRegister(context: Context) { context.put(compilerKey, Context.Factory(::KaptJavaCompiler)) } } diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/SyntheticJavaFileObject.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaFileObject.kt similarity index 96% rename from plugins/kapt3/src/org/jetbrains/kotlin/kapt3/SyntheticJavaFileObject.kt rename to plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaFileObject.kt index 8ff8fbfe049..a0afd364eb2 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/SyntheticJavaFileObject.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptJavaFileObject.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.kapt3 +package org.jetbrains.kotlin.kapt3.javac import com.sun.tools.javac.file.BaseFileObject import com.sun.tools.javac.file.JavacFileManager @@ -26,7 +26,7 @@ import javax.lang.model.element.Modifier import javax.lang.model.element.NestingKind import javax.tools.JavaFileObject -class SyntheticJavaFileObject( +class KaptJavaFileObject( val compilationUnit: JCTree.JCCompilationUnit, val clazz: JCTree.JCClassDecl, val timestamp: Long, @@ -81,7 +81,7 @@ class SyntheticJavaFileObject( if (this === other) return true if (other?.javaClass != javaClass) return false - other as SyntheticJavaFileObject + other as KaptJavaFileObject if (compilationUnit != other.compilationUnit) return false if (clazz != other.clazz) return false diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptTreeMaker.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptTreeMaker.kt similarity index 77% rename from plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptTreeMaker.kt rename to plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptTreeMaker.kt index c2a164c5b7e..978a5d938a7 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/KaptTreeMaker.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/javac/KaptTreeMaker.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.kapt3 +package org.jetbrains.kotlin.kapt3.javac import com.sun.tools.javac.code.TypeTag import com.sun.tools.javac.tree.JCTree @@ -24,23 +24,23 @@ import com.sun.tools.javac.util.Names import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type.* -class KaptTreeMaker(context: Context?) : TreeMaker(context) { +class KaptTreeMaker(context: Context) : TreeMaker(context) { private val nameTable = Names.instance(context).table - fun convertType(type: Type): JCTree.JCExpression { + fun Type(type: Type): JCTree.JCExpression { convertBuiltinType(type)?.let { return it } if (type.sort == ARRAY) { - return TypeArray(convertType(type.elementType)) + return TypeArray(Type(type.elementType)) } - return convertFqName(type.className) + return FqName(type.className) } - fun convertFqName(internalOrFqName: String): JCTree.JCExpression { + fun FqName(internalOrFqName: String): JCTree.JCExpression { val path = internalOrFqName.replace('/', '.').split('.') assert(path.isNotEmpty()) - if (path.size == 1) return convertSimpleName(path.single()) + if (path.size == 1) return SimpleName(path.single()) - var expr = Select(convertSimpleName(path[0]), name(path[1])) + var expr = Select(SimpleName(path[0]), name(path[1])) for (index in 2..path.lastIndex) { expr = Select(expr, name(path[index])) } @@ -63,12 +63,12 @@ class KaptTreeMaker(context: Context?) : TreeMaker(context) { return TypeIdent(typeTag) } - fun convertSimpleName(name: String): JCTree.JCExpression = Ident(name(name)) + fun SimpleName(name: String): JCTree.JCExpression = Ident(name(name)) fun name(name: String) = nameTable.fromString(name) companion object { - fun preRegister(context: Context) { + internal fun preRegister(context: Context) { context.put(treeMakerKey, Context.Factory(::KaptTreeMaker)) } } diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/JCTreeConverter.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt similarity index 77% rename from plugins/kapt3/src/org/jetbrains/kotlin/kapt3/JCTreeConverter.kt rename to plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index 23e87fb429e..39fc07034a8 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/JCTreeConverter.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.kapt3 +package org.jetbrains.kotlin.kapt3.stubs import com.sun.tools.javac.code.Flags import com.sun.tools.javac.code.TypeTag @@ -22,28 +22,25 @@ import com.sun.tools.javac.file.JavacFileManager import com.sun.tools.javac.tree.JCTree import com.sun.tools.javac.tree.JCTree.* import com.sun.tools.javac.tree.TreeMaker -import com.sun.tools.javac.util.Context +import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.kapt3.* +import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker +import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject +import org.jetbrains.kotlin.kapt3.util.* import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny -import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.tree.* -import java.util.* import javax.lang.model.element.ElementKind import javax.tools.JavaFileManager import com.sun.tools.javac.util.List as JavacList -class JCTreeConverter( - context: Context, - val typeMapper: KotlinTypeMapper, - val classes: List, - val origins: Map -) { +class ClassFileToSourceStubConverter(val kaptContext: KaptContext, val typeMapper: KotlinTypeMapper) { private companion object { private val VISIBILITY_MODIFIERS = (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED).toLong() private val MODALITY_MODIFIERS = (Opcodes.ACC_FINAL or Opcodes.ACC_ABSTRACT).toLong() @@ -68,20 +65,20 @@ class JCTreeConverter( ) } - private val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager - private val treeMaker = TreeMaker.instance(context) as KaptTreeMaker + private val fileManager = kaptContext.context.get(JavaFileManager::class.java) as JavacFileManager + private val treeMaker = TreeMaker.instance(kaptContext.context) as KaptTreeMaker private val signatureParser = SignatureParser(treeMaker) private var done = false fun convert(): JavacList { - if (done) error(JCTreeConverter::class.java.simpleName + " can convert classes only once") + if (done) error(ClassFileToSourceStubConverter::class.java.simpleName + " can convert classes only once") done = true - return mapValues(classes) { convertTopLevelClass(it) } + return mapValues(kaptContext.compiledClasses) { convertTopLevelClass(it) } } private fun convertTopLevelClass(clazz: ClassNode): JCCompilationUnit? { - val origin = origins[clazz] ?: return null + val origin = kaptContext.origins[clazz] ?: return null val ktFile = origin.element?.containingFile as? KtFile ?: return null val descriptor = origin.descriptor as? ClassDescriptor ?: return null @@ -92,13 +89,13 @@ class JCTreeConverter( val packageAnnotations = JavacList.nil() val packageName = ktFile.packageFqName.asString() - val packageClause = if (packageName.isEmpty()) null else treeMaker.convertFqName(packageName) + val packageClause = if (packageName.isEmpty()) null else treeMaker.FqName(packageName) val imports = JavacList.nil() val classes = JavacList.of(classDeclaration) val topLevel = treeMaker.TopLevel(packageAnnotations, packageClause, imports + classes) - val javaFileObject = SyntheticJavaFileObject(topLevel, classDeclaration, System.currentTimeMillis(), fileManager) + val javaFileObject = KaptJavaFileObject(topLevel, classDeclaration, System.currentTimeMillis(), fileManager) topLevel.sourcefile = javaFileObject return topLevel } @@ -109,7 +106,7 @@ class JCTreeConverter( private fun convertClass(clazz: ClassNode, isTopLevel: Boolean): JCClassDecl? { if (isSynthetic(clazz.access)) return null - val descriptor = origins[clazz]?.descriptor as? ClassDescriptor ?: return null + val descriptor = kaptContext.origins[clazz]?.descriptor as? ClassDescriptor ?: return null val modifiers = convertModifiers( if (!descriptor.isInner && descriptor.isNested) (clazz.access or Opcodes.ACC_STATIC) else clazz.access, ElementKind.CLASS, clazz.visibleAnnotations, clazz.invisibleAnnotations) @@ -130,10 +127,10 @@ class JCTreeConverter( val interfaces = mapValues(clazz.interfaces) { if (isAnnotation && it == "java/lang/annotation/Annotation") return@mapValues null - treeMaker.convertFqName(it) + treeMaker.FqName(it) } - val superClass = treeMaker.convertFqName(clazz.superName) + val superClass = treeMaker.FqName(clazz.superName) val hasSuperClass = clazz.superName != "java/lang/Object" && !isEnum val genericType = signatureParser.parseClassSignature(clazz.signature, superClass, interfaces) @@ -149,7 +146,7 @@ class JCTreeConverter( } val nestedClasses = mapValues(clazz.innerClasses) { innerClass -> if (innerClass.outerName != clazz.name) return@mapValues null - val innerClassNode = classes.firstOrNull { it.name == innerClass.name } ?: return@mapValues null + val innerClassNode = kaptContext.compiledClasses.firstOrNull { it.name == innerClass.name } ?: return@mapValues null convertClass(innerClassNode, false) } @@ -171,9 +168,9 @@ class JCTreeConverter( // Enum type must be an identifier (Javac requirement) val typeExpression = if (isEnum(field.access)) { - treeMaker.convertSimpleName(type.className.substringAfterLast('.')) + treeMaker.SimpleName(type.className.substringAfterLast('.')) } else { - signatureParser.parseFieldSignature(field.signature, treeMaker.convertType(type)) + signatureParser.parseFieldSignature(field.signature, treeMaker.Type(type)) } val value = field.value @@ -189,7 +186,7 @@ class JCTreeConverter( private fun convertMethod(method: MethodNode, containingClass: ClassNode): JCMethodDecl? { if (isSynthetic(method.access)) return null - val descriptor = origins[method]?.descriptor as? CallableDescriptor ?: return null + val descriptor = kaptContext.origins[method]?.descriptor as? CallableDescriptor ?: return null val isOverridden = descriptor.overriddenDescriptors.isNotEmpty() val visibleAnnotations = if (isOverridden) { @@ -206,7 +203,7 @@ class JCTreeConverter( val name = treeMaker.name(method.name) val returnType = Type.getReturnType(method.desc) - val jcReturnType = if (isConstructor) null else treeMaker.convertType(returnType) + val jcReturnType = if (isConstructor) null else treeMaker.Type(returnType) val parametersInfo = method.getParametersInfo(containingClass) @Suppress("NAME_SHADOWING") @@ -219,11 +216,11 @@ class JCTreeConverter( info.flags or varargs or Flags.PARAMETER, ElementKind.PARAMETER, info.visibleAnnotations, info.invisibleAnnotations) val name = treeMaker.name(info.name) - val type = treeMaker.convertType(info.type) + val type = treeMaker.Type(info.type) treeMaker.VarDef(modifiers, name, type, null) } - val exceptionTypes = mapValues(method.exceptions) { treeMaker.convertFqName(it) } + val exceptionTypes = mapValues(method.exceptions) { treeMaker.FqName(it) } val genericType = signatureParser.parseMethodSignature(method.signature, parameters, exceptionTypes, jcReturnType) @@ -237,7 +234,7 @@ class JCTreeConverter( treeMaker.Block(0, JavacList.nil()) } else if (isConstructor) { // We already checked it in convertClass() - val declaration = origins[containingClass]?.descriptor as ClassDescriptor + val declaration = kaptContext.origins[containingClass]?.descriptor as ClassDescriptor val superClass = declaration.getSuperClassOrAny() val superClassConstructor = superClass.constructors.firstOrNull { it.visibility.isVisible(null, it, declaration) } @@ -245,7 +242,7 @@ class JCTreeConverter( val args = mapValues(superClassConstructor.valueParameters) { param -> convertLiteralExpression(getDefaultValue(typeMapper.mapType(param.type))) } - val call = treeMaker.Apply(JavacList.nil(), treeMaker.convertSimpleName("super"), args) + val call = treeMaker.Apply(JavacList.nil(), treeMaker.SimpleName("super"), args) JavacList.of(treeMaker.Exec(call)) } else { JavacList.nil() @@ -301,9 +298,9 @@ class JCTreeConverter( val fqName = annotationType.className if (BLACKLISTED_ANNOTATATIONS.any { fqName.startsWith(it) }) return null - val name = treeMaker.convertType(annotationType) + val name = treeMaker.Type(annotationType) val values = mapPairedValues(annotation.values) { key, value -> - treeMaker.Assign(treeMaker.convertSimpleName(key), convertLiteralExpression(value)) + treeMaker.Assign(treeMaker.SimpleName(key), convertLiteralExpression(value)) } return treeMaker.Annotation(name, values) } @@ -326,11 +323,11 @@ class JCTreeConverter( assert(value.size == 2) val enumType = Type.getType(value[0] as String) val valueName = value[1] as String - treeMaker.Select(treeMaker.convertType(enumType), treeMaker.name(valueName)) + treeMaker.Select(treeMaker.Type(enumType), treeMaker.name(valueName)) } - is List<*> -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value) { convertLiteralExpression(it) }) + is List<*> -> treeMaker.NewArray(null, JavacList.nil(), org.jetbrains.kotlin.kapt3.mapValues(value) { convertLiteralExpression(it) }) - is Type -> treeMaker.Select(treeMaker.convertType(value), treeMaker.name("class")) + is Type -> treeMaker.Select(treeMaker.Type(value), treeMaker.name("class")) is AnnotationNode -> convertAnnotation(value) ?: error("Annotation is filtered out") else -> throw IllegalArgumentException("Illegal literal expression value: $value (${value.javaClass.canonicalName})") } @@ -349,54 +346,5 @@ class JCTreeConverter( } } -private class ParameterInfo( - val flags: Long, - val name: String, - val type: Type, - val visibleAnnotations: List?, - val invisibleAnnotations: List?) - -private fun MethodNode.getParametersInfo(containingClass: ClassNode): List { - val localVariables = this.localVariables ?: emptyList() - val parameters = this.parameters ?: emptyList() - val isStatic = isStatic(access) - - // First and second parameters in enum constructors are synthetic, we should ignore them - val isEnumConstructor = (name == "") && containingClass.isEnum() - val startParameterIndex = if (isEnumConstructor) 2 else 0 - - val parameterTypes = Type.getArgumentTypes(desc) - - val parameterInfos = ArrayList(parameterTypes.size - startParameterIndex) - for (index in startParameterIndex..parameterTypes.lastIndex) { - val type = parameterTypes[index] - var name = parameters.getOrNull(index - startParameterIndex)?.name - ?: localVariables.getOrNull(index + (if (isStatic) 0 else 1))?.name - ?: "p${index - startParameterIndex}" - - // Property setters has bad parameter names - if (name.startsWith("<") && name.endsWith(">")) { - name = "p${index - startParameterIndex}" - } - - val visibleAnnotations = visibleParameterAnnotations?.get(index) - val invisibleAnnotations = invisibleParameterAnnotations?.get(index) - parameterInfos += ParameterInfo(0, name, type, visibleAnnotations, invisibleAnnotations) - } - return parameterInfos -} - private val ClassDescriptor.isNested: Boolean - get() = containingDeclaration is ClassDescriptor - -private fun isEnum(access: Int) = (access and Opcodes.ACC_ENUM) > 0 -private fun isPublic(access: Int) = (access and Opcodes.ACC_PUBLIC) > 0 -private fun isSynthetic(access: Int) = (access and Opcodes.ACC_SYNTHETIC) > 0 -private fun isFinal(access: Int) = (access and Opcodes.ACC_FINAL) > 0 -private fun isStatic(access: Int) = (access and Opcodes.ACC_STATIC) > 0 -private fun isAbstract(access: Int) = (access and Opcodes.ACC_ABSTRACT) > 0 -private fun ClassNode.isEnum() = (access and Opcodes.ACC_ENUM) > 0 -private fun ClassNode.isAnnotation() = (access and Opcodes.ACC_ANNOTATION) > 0 -private fun MethodNode.isVarargs() = (access and Opcodes.ACC_VARARGS) > 0 - -private fun List?.isNullOrEmpty() = this == null || this.isEmpty() \ No newline at end of file + get() = containingDeclaration is ClassDescriptor \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/SignatureParserVisitor.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/SignatureParserVisitor.kt similarity index 89% rename from plugins/kapt3/src/org/jetbrains/kotlin/kapt3/SignatureParserVisitor.kt rename to plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/SignatureParserVisitor.kt index 964a1dc5e4f..14c46992946 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/SignatureParserVisitor.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/SignatureParserVisitor.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.kotlin.kapt3 +package org.jetbrains.kotlin.kapt3.stubs import com.sun.tools.javac.code.BoundKind import com.sun.tools.javac.code.TypeTag @@ -22,7 +22,10 @@ import com.sun.tools.javac.tree.JCTree.* import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor import java.util.* -import org.jetbrains.kotlin.kapt3.ElementKind.* +import org.jetbrains.kotlin.kapt3.stubs.ElementKind.* +import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker +import org.jetbrains.kotlin.kapt3.mapValues +import org.jetbrains.kotlin.kapt3.mapValuesIndexed import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.org.objectweb.asm.signature.SignatureReader import com.sun.tools.javac.util.List as JavacList @@ -76,35 +79,35 @@ import com.sun.tools.javac.util.List as JavacList + ClassType */ -enum class ElementKind { +internal enum class ElementKind { Root, TypeParameter, ClassBound, InterfaceBound, SuperClass, Interface, TypeArgument, ParameterType, ReturnType, ExceptionType, ClassType, TypeVariable, PrimitiveType, ArrayType } -class SignatureNode(val kind: ElementKind, val name: String? = null) { +private class SignatureNode(val kind: ElementKind, val name: String? = null) { val children: MutableList = SmartList() } class SignatureParser(val treeMaker: KaptTreeMaker) { class ClassGenericSignature( - val typeParameters: JavacList, + val typeParameters: com.sun.tools.javac.util.List, val superClass: JCExpression, - val interfaces: JavacList) + val interfaces: com.sun.tools.javac.util.List) class MethodGenericSignature( - val typeParameters: JavacList, - val parameterTypes: JavacList, - val exceptionTypes: JavacList, + val typeParameters: com.sun.tools.javac.util.List, + val parameterTypes: com.sun.tools.javac.util.List, + val exceptionTypes: com.sun.tools.javac.util.List, val returnType: JCExpression? ) fun parseClassSignature( signature: String?, rawSuperClass: JCExpression, - rawInterfaces: JavacList + rawInterfaces: com.sun.tools.javac.util.List ): ClassGenericSignature { if (signature == null) { - return ClassGenericSignature(JavacList.nil(), rawSuperClass, rawInterfaces) + return ClassGenericSignature(com.sun.tools.javac.util.List.nil(), rawSuperClass, rawInterfaces) } val root = parse(signature) @@ -121,12 +124,12 @@ class SignatureParser(val treeMaker: KaptTreeMaker) { fun parseMethodSignature( signature: String?, - rawParameters: JavacList, - rawExceptionTypes: JavacList, + rawParameters: com.sun.tools.javac.util.List, + rawExceptionTypes: com.sun.tools.javac.util.List, rawReturnType: JCExpression? ): MethodGenericSignature { if (signature == null) { - return MethodGenericSignature(JavacList.nil(), rawParameters, rawExceptionTypes, rawReturnType) + return MethodGenericSignature(com.sun.tools.javac.util.List.nil(), rawParameters, rawExceptionTypes, rawReturnType) } val root = parse(signature) @@ -186,7 +189,7 @@ class SignatureParser(val treeMaker: KaptTreeMaker) { ClassType -> { val classFqName = node.name!!.replace('/', '.') val args = node.children - val fqNameExpression = treeMaker.convertFqName(classFqName) + val fqNameExpression = treeMaker.FqName(classFqName) if (args.isEmpty()) return fqNameExpression treeMaker.TypeApply(fqNameExpression, mapValues(args) { arg -> @@ -202,7 +205,7 @@ class SignatureParser(val treeMaker: KaptTreeMaker) { } }) } - TypeVariable -> treeMaker.convertSimpleName(node.name!!) + TypeVariable -> treeMaker.SimpleName(node.name!!) ArrayType -> treeMaker.TypeArray(parseType(node.children.single())) PrimitiveType -> { val typeTag = when (node.name!!.single()) { diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/parseParameters.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/parseParameters.kt new file mode 100644 index 00000000000..d38eb16f130 --- /dev/null +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/stubs/parseParameters.kt @@ -0,0 +1,62 @@ +/* + * 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.kapt3.stubs + +import org.jetbrains.kotlin.kapt3.util.isEnum +import org.jetbrains.kotlin.kapt3.util.isStatic +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.tree.AnnotationNode +import org.jetbrains.org.objectweb.asm.tree.ClassNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import java.util.* + +internal class ParameterInfo( + val flags: Long, + val name: String, + val type: Type, + val visibleAnnotations: List?, + val invisibleAnnotations: List?) + +internal fun MethodNode.getParametersInfo(containingClass: ClassNode): List { + val localVariables = this.localVariables ?: emptyList() + val parameters = this.parameters ?: emptyList() + val isStatic = isStatic(access) + + // First and second parameters in enum constructors are synthetic, we should ignore them + val isEnumConstructor = (name == "") && containingClass.isEnum() + val startParameterIndex = if (isEnumConstructor) 2 else 0 + + val parameterTypes = Type.getArgumentTypes(desc) + + val parameterInfos = ArrayList(parameterTypes.size - startParameterIndex) + for (index in startParameterIndex..parameterTypes.lastIndex) { + val type = parameterTypes[index] + var name = parameters.getOrNull(index - startParameterIndex)?.name + ?: localVariables.getOrNull(index + (if (isStatic) 0 else 1))?.name + ?: "p${index - startParameterIndex}" + + // Property setters has bad parameter names + if (name.startsWith("<") && name.endsWith(">")) { + name = "p${index - startParameterIndex}" + } + + val visibleAnnotations = visibleParameterAnnotations?.get(index) + val invisibleAnnotations = invisibleParameterAnnotations?.get(index) + parameterInfos += ParameterInfo(0, name, type, visibleAnnotations, invisibleAnnotations) + } + return parameterInfos +} \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Logger.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/KaptLogger.kt similarity index 92% rename from plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Logger.kt rename to plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/KaptLogger.kt index c4b822ec9a7..e9e41e4108c 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/Logger.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/KaptLogger.kt @@ -14,9 +14,9 @@ * limitations under the License. */ -package org.jetbrains.kotlin.kapt3 +package org.jetbrains.kotlin.kapt3.util -class Logger(val isVerbose: Boolean) { +class KaptLogger(val isVerbose: Boolean) { private companion object { val PREFIX = "[kapt] " } diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt new file mode 100644 index 00000000000..ab3d46cefd6 --- /dev/null +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/asmUtils.kt @@ -0,0 +1,33 @@ +/* + * 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.kapt3.util + +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.tree.ClassNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode + +internal fun isEnum(access: Int) = (access and Opcodes.ACC_ENUM) > 0 +internal fun isPublic(access: Int) = (access and Opcodes.ACC_PUBLIC) > 0 +internal fun isSynthetic(access: Int) = (access and Opcodes.ACC_SYNTHETIC) > 0 +internal fun isFinal(access: Int) = (access and Opcodes.ACC_FINAL) > 0 +internal fun isStatic(access: Int) = (access and Opcodes.ACC_STATIC) > 0 +internal fun isAbstract(access: Int) = (access and Opcodes.ACC_ABSTRACT) > 0 +internal fun ClassNode.isEnum() = (access and Opcodes.ACC_ENUM) > 0 +internal fun ClassNode.isAnnotation() = (access and Opcodes.ACC_ANNOTATION) > 0 +internal fun MethodNode.isVarargs() = (access and Opcodes.ACC_VARARGS) > 0 + +internal fun List?.isNullOrEmpty() = this == null || this.isEmpty() \ No newline at end of file diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/utils.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/javacListUtils.kt similarity index 99% rename from plugins/kapt3/src/org/jetbrains/kotlin/kapt3/utils.kt rename to plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/javacListUtils.kt index c2dad949426..52a100292ec 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/utils.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/util/javacListUtils.kt @@ -15,6 +15,7 @@ */ package org.jetbrains.kotlin.kapt3 + import com.sun.tools.javac.util.List as JavacList internal inline fun mapValues(values: Iterable?, f: (T) -> R?): JavacList { diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt index b39f840ae8c..2a42d09e15f 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/AbstractKotlinKapt3Test.kt @@ -18,19 +18,16 @@ package org.jetbrains.kotlin.kapt3.test import com.intellij.openapi.util.text.StringUtil import com.sun.tools.javac.comp.CompileStates -import com.sun.tools.javac.tree.JCTree +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.codegen.CodegenTestUtil import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper -import org.jetbrains.kotlin.kapt3.JCTreeConverter -import org.jetbrains.kotlin.kapt3.Kapt3BuilderFactory -import org.jetbrains.kotlin.kapt3.KaptRunner -import org.jetbrains.kotlin.kapt3.Logger -import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin +import org.jetbrains.kotlin.kapt3.* +import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter +import org.jetbrains.kotlin.kapt3.util.KaptLogger import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.util.trimTrailingWhitespacesAndAddNewlineAtEOF -import org.jetbrains.org.objectweb.asm.tree.ClassNode import com.sun.tools.javac.util.List as JavacList import java.io.File import java.nio.file.Files @@ -51,35 +48,29 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() { val factory = CodegenTestUtil.generateFiles(myEnvironment, myFiles, classBuilderFactory) val typeMapper = factory.generationState.typeMapper - val logger = Logger(isVerbose = true) - val kaptRunner = KaptRunner(logger) + val logger = KaptLogger(isVerbose = true) + val kaptContext = KaptContext(logger, classBuilderFactory.compiledClasses, classBuilderFactory.origins) try { - check(kaptRunner, typeMapper, classBuilderFactory, txtFile) + check(kaptContext, typeMapper, txtFile) } finally { - kaptRunner.close() + kaptContext.close() } } - protected fun convert( - kaptRunner: KaptRunner, - typeMapper: KotlinTypeMapper, - compiledClasses: List, - origins: Map - ): JavacList { - val converter = JCTreeConverter(kaptRunner.context, typeMapper, compiledClasses, origins) + protected fun convert(kaptRunner: KaptContext, typeMapper: KotlinTypeMapper): JavacList { + val converter = ClassFileToSourceStubConverter(kaptRunner, typeMapper) return converter.convert() } protected abstract fun check( - kaptRunner: KaptRunner, + kaptRunner: KaptContext, typeMapper: KotlinTypeMapper, - classBuilderFactory: Kapt3BuilderFactory, txtFile: File) } -abstract class AbstractJCTreeConverterTest : AbstractKotlinKapt3Test() { - override fun check(kaptRunner: KaptRunner, typeMapper: KotlinTypeMapper, classBuilderFactory: Kapt3BuilderFactory, txtFile: File) { - val javaFiles = convert(kaptRunner, typeMapper, classBuilderFactory.compiledClasses, classBuilderFactory.origins) +abstract class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test() { + override fun check(kaptRunner: KaptContext, typeMapper: KotlinTypeMapper, txtFile: File) { + val javaFiles = convert(kaptRunner, typeMapper) kaptRunner.compiler.enterTrees(javaFiles) val actualRaw = javaFiles.joinToString (FILE_SEPARATOR) @@ -93,8 +84,8 @@ abstract class AbstractJCTreeConverterTest : AbstractKotlinKapt3Test() { } abstract class AbstractKotlinKaptRunnerTest : AbstractKotlinKapt3Test() { - override fun check(kaptRunner: KaptRunner, typeMapper: KotlinTypeMapper, classBuilderFactory: Kapt3BuilderFactory, txtFile: File) { - val compilationUnits = convert(kaptRunner, typeMapper, classBuilderFactory.compiledClasses, classBuilderFactory.origins) + override fun check(kaptRunner: KaptContext, typeMapper: KotlinTypeMapper, txtFile: File) { + val compilationUnits = convert(kaptRunner, typeMapper) val sourceOutputDir = Files.createTempDirectory("kaptRunner").toFile() try { kaptRunner.doAnnotationProcessing(emptyList(), listOf(KaptRunnerTest.simpleProcessor()), diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JCTreeConverterTestGenerated.java b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java similarity index 96% rename from plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JCTreeConverterTestGenerated.java rename to plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java index 5b112aa0164..3eb848abb11 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JCTreeConverterTestGenerated.java +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java @@ -30,7 +30,7 @@ import java.util.regex.Pattern; @TestMetadata("plugins/kapt3/testData/converter") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) -public class JCTreeConverterTestGenerated extends AbstractJCTreeConverterTest { +public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFileToSourceStubConverterTest { public void testAllFilesPresentInConverter() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/kapt3/testData/converter"), Pattern.compile("^(.+)\\.kt$"), true); } diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KaptRunnerTest.kt b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KaptRunnerTest.kt index a48bcea1425..738315c876f 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KaptRunnerTest.kt +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/KaptRunnerTest.kt @@ -16,14 +16,16 @@ package org.jetbrains.kotlin.kapt3.test -import org.jetbrains.kotlin.kapt3.KaptError -import org.jetbrains.kotlin.kapt3.KaptRunner -import org.jetbrains.kotlin.kapt3.Logger +import org.jetbrains.kotlin.kapt3.KaptContext +import org.jetbrains.kotlin.kapt3.diagnostic.KaptError +import org.jetbrains.kotlin.kapt3.doAnnotationProcessing +import org.jetbrains.kotlin.kapt3.util.KaptLogger import org.junit.Assert.* import org.junit.Test import java.io.File import java.nio.file.Files import javax.annotation.processing.AbstractProcessor +import javax.annotation.processing.Processor import javax.annotation.processing.RoundEnvironment import javax.lang.model.element.TypeElement @@ -72,16 +74,20 @@ class KaptRunnerTest { } } + private fun doAnnotationProcessing(javaSourceFile: File, processor: Processor, outputDir: File) { + KaptContext(KaptLogger(isVerbose = true), emptyList(), emptyMap()).doAnnotationProcessing( + listOf(javaSourceFile), + listOf(processor), + emptyList(), // classpath + outputDir, + outputDir) + } + @Test fun testSimple() { val sourceOutputDir = Files.createTempDirectory("kaptRunner").toFile() try { - KaptRunner(Logger(isVerbose = true)).doAnnotationProcessing( - listOf(File(TEST_DATA_DIR, "Simple.java")), - listOf(simpleProcessor()), - emptyList(), // classpath - sourceOutputDir, - sourceOutputDir) + doAnnotationProcessing(File(TEST_DATA_DIR, "Simple.java"), simpleProcessor(), sourceOutputDir) val myMethodFile = File(sourceOutputDir, "generated/MyMethodMyAnnotation.java") assertTrue(myMethodFile.exists()) } finally { @@ -102,12 +108,7 @@ class KaptRunnerTest { } try { - KaptRunner(Logger(isVerbose = true)).doAnnotationProcessing( - listOf(File(TEST_DATA_DIR, "Simple.java")), - listOf(processor), - emptyList(), - TEST_DATA_DIR, - TEST_DATA_DIR) + doAnnotationProcessing(File(TEST_DATA_DIR, "Simple.java"), processor, TEST_DATA_DIR) } catch (e: KaptError) { assertEquals(KaptError.Kind.EXCEPTION, e.kind) assertEquals("Here we are!", e.cause!!.message) @@ -116,15 +117,14 @@ class KaptRunnerTest { @Test fun testParsingError() { + var catched = false try { - KaptRunner(Logger(isVerbose = true)).doAnnotationProcessing( - listOf(File(TEST_DATA_DIR, "ParseError.java")), - listOf(simpleProcessor()), - emptyList(), - TEST_DATA_DIR, - TEST_DATA_DIR) + doAnnotationProcessing(File(TEST_DATA_DIR, "ParseError.java"), simpleProcessor(), TEST_DATA_DIR) } catch (e: KaptError) { assertEquals(KaptError.Kind.JAVA_FILE_PARSING_ERROR, e.kind) + catched = true } + + assertTrue("Exception was not catched", catched) } } \ No newline at end of file