[KAPT] Refactor Kapt 3 components for reuse in Kapt 4 (KT-51982)

- make some utility functions and classes public
- split some classes into common and Kapt 3 - specific parts
- use Kapt 4-ready filtering of @Metadata annotations in tests
This commit is contained in:
Pavel Mikhailovskii
2023-07-26 14:03:14 +00:00
committed by Space Team
parent c702f00399
commit 7ecd7b8e61
14 changed files with 238 additions and 190 deletions
@@ -191,7 +191,7 @@ fun collectAggregatedTypes(sourcesToReprocess: SourcesToReprocess = SourcesToRep
fun KaptOptions.logString(additionalInfo: String = "") = buildString {
val additionalInfoRendered = if (additionalInfo.isEmpty()) "" else " ($additionalInfo)"
appendLine("Kapt3 is enabled$additionalInfoRendered.")
appendLine("Kapt is enabled$additionalInfoRendered.")
appendLine("Annotation processing mode: ${mode.stringValue}")
appendLine("Memory leak detection mode: ${detectMemoryLeaks.stringValue}")
@@ -17,11 +17,7 @@
package org.jetbrains.kotlin.kapt3
import com.intellij.openapi.project.Project
import com.sun.tools.javac.code.Flags
import com.sun.tools.javac.tree.JCTree
import com.sun.tools.javac.tree.Pretty
import com.sun.tools.javac.tree.TreeMaker
import com.sun.tools.javac.util.Context
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.base.kapt3.AptMode.APT_ONLY
@@ -54,11 +50,12 @@ import org.jetbrains.kotlin.kapt3.base.doAnnotationProcessing
import org.jetbrains.kotlin.kapt3.base.util.KaptBaseError
import org.jetbrains.kotlin.kapt3.base.util.getPackageNameJava9Aware
import org.jetbrains.kotlin.kapt3.base.util.info
import org.jetbrains.kotlin.kapt3.base.util.isJava11OrLater
import org.jetbrains.kotlin.kapt3.diagnostic.KaptError
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter.KaptStub
import org.jetbrains.kotlin.kapt3.util.MessageCollectorBackedKaptLogger
import org.jetbrains.kotlin.kapt3.util.PrettyWithWorkarounds
import org.jetbrains.kotlin.kapt3.util.prettyPrint
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
@@ -67,7 +64,6 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtensi
import org.jetbrains.kotlin.utils.kapt.MemoryLeakDetector
import java.io.File
import java.io.StringWriter
import java.io.Writer
import java.net.URLClassLoader
import javax.annotation.processing.Processor
@@ -369,35 +365,6 @@ abstract class AbstractKapt3Extension(
protected abstract fun loadProcessors(): LoadedProcessors
}
internal fun JCTree.prettyPrint(context: Context): String {
return StringWriter().apply { PrettyWithWorkarounds(context, this, false).printStat(this@prettyPrint) }.toString()
}
private class PrettyWithWorkarounds(private val context: Context, val out: Writer, sourceOutput: Boolean) : Pretty(out, sourceOutput) {
companion object {
private const val ENUM = Flags.ENUM.toLong()
}
override fun print(s: Any) {
out.write(s.toString())
}
override fun visitVarDef(tree: JCTree.JCVariableDecl) {
if ((tree.mods.flags and ENUM) != 0L) {
// Pretty does not print annotations for enum values for some reason
printExpr(TreeMaker.instance(context).Modifiers(0, tree.mods.annotations))
if (isJava11OrLater()) {
// Print enums fully, there is an issue when using Pretty in JDK 11.
// See https://youtrack.jetbrains.com/issue/KT-33052.
print("/*public static final*/ ${tree.name}")
tree.init?.let { print(" /* = $it */") }
return
}
}
super.visitVarDef(tree)
}
}
private inline fun <T> measureTimeMillis(block: () -> T): Pair<Long, T> {
val start = System.currentTimeMillis()
@@ -166,6 +166,9 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
@Suppress("DEPRECATION")
class Kapt3ComponentRegistrar : ComponentRegistrar {
override val supportsK2: Boolean
get() = false
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
if (configuration.getBoolean(USE_FIR)) return
doOpenInternalPackagesIfRequired()
@@ -24,18 +24,12 @@ import com.sun.tools.javac.tree.DCTree
import com.sun.tools.javac.tree.DocCommentTable
import com.sun.tools.javac.tree.JCTree
import com.sun.tools.javac.tree.TreeScanner
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
import org.jetbrains.kotlin.kapt3.base.KaptContext
import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.FieldNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class KDocCommentKeeper(private val kaptContext: KaptContextForStubGeneration) {
abstract class AbstractKDocCommentKeeper<T: KaptContext>(protected val kaptContext: T) {
private val docCommentTable = KaptDocCommentTable()
fun getDocTable(file: JCTree.JCCompilationUnit): DocCommentTable {
@@ -71,32 +65,8 @@ class KDocCommentKeeper(private val kaptContext: KaptContextForStubGeneration) {
return docCommentTable
}
fun saveKDocComment(tree: JCTree, node: Any) {
val origin = kaptContext.origins[node] ?: return
val psiElement = origin.element as? KtDeclaration ?: return
val descriptor = origin.descriptor
val docComment = psiElement.docComment ?: return
if (descriptor is ConstructorDescriptor && psiElement is KtClassOrObject) {
// We don't want the class comment to be duplicated on <init>()
return
}
if (node is MethodNode
&& psiElement is KtProperty
&& descriptor is PropertyAccessorDescriptor
&& kaptContext.bindingContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor.correspondingProperty] == true
) {
// Do not place documentation on backing field and property accessors
return
}
if (node is FieldNode && psiElement is KtObjectDeclaration && descriptor == null) {
// Do not write KDoc on object instance field
return
}
docCommentTable.putComment(tree, KDocComment(escapeNestedComments(extractCommentText(docComment))))
protected fun saveKDocComment(tree: JCTree, comment: KDoc) {
docCommentTable.putComment(tree, KDocComment(escapeNestedComments(extractCommentText(comment))))
}
private fun escapeNestedComments(text: String): String {
@@ -136,7 +136,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
private val signatureParser = SignatureParser(treeMaker)
private val kdocCommentKeeper = if (keepKdocComments) KDocCommentKeeper(kaptContext) else null
private val kdocCommentKeeper = if (keepKdocComments) Kapt3DocCommentKeeper(kaptContext) else null
private val importsFromRoot by lazy(::collectImportsFromRootPackage)
@@ -468,52 +468,6 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati
).keepKdocCommentsIfNecessary(clazz)
}
private class MemberData(val name: String, val descriptor: String, val position: KotlinPosition?)
/**
* Sort class members. If the source file for the class is unknown, just sort using name and descriptor. Otherwise:
* - all members in the same source file as the class come first (members may come from other source files)
* - members from the class are sorted using their position in the source file
* - members from other source files are sorted using their name and descriptor
*
* More details: Class methods and fields are currently sorted at serialization (see DescriptorSerializer.sort) and at deserialization
* (see DeserializedMemberScope.OptimizedImplementation#addMembers). Therefore, the contents of the generated stub files are sorted in
* incremental builds but not in clean builds.
* The consequence is that the contents of the generated stub files may not be consistent across a clean build and an incremental
* build, making the build non-deterministic and dependent tasks run unnecessarily (see KT-40882).
*/
private class MembersPositionComparator(val classSource: KotlinPosition?, val memberData: Map<JCTree, MemberData>) :
Comparator<JCTree> {
override fun compare(o1: JCTree, o2: JCTree): Int {
val data1 = memberData.getValue(o1)
val data2 = memberData.getValue(o2)
classSource ?: return compareDescriptors(data1, data2)
val position1 = data1.position
val position2 = data2.position
return if (position1 != null && position1.path == classSource.path) {
if (position2 != null && position2.path == classSource.path) {
val positionCompare = position1.pos.compareTo(position2.pos)
if (positionCompare != 0) positionCompare
else compareDescriptors(data1, data2)
} else {
-1
}
} else if (position2 != null && position2.path == classSource.path) {
1
} else {
compareDescriptors(data1, data2)
}
}
private fun compareDescriptors(m1: MemberData, m2: MemberData): Int {
val nameComparison = m1.name.compareTo(m2.name)
if (nameComparison != 0) return nameComparison
return m1.descriptor.compareTo(m2.descriptor)
}
}
private class ClassSupertypes(val superClass: JCExpression?, val interfaces: JavacList<JCExpression>)
private fun calculateSuperTypes(clazz: ClassNode, genericType: SignatureParser.ClassGenericSignature): ClassSupertypes {
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.kapt3.stubs
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.org.objectweb.asm.tree.FieldNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
class Kapt3DocCommentKeeper(kaptContext: KaptContextForStubGeneration) : AbstractKDocCommentKeeper<KaptContextForStubGeneration>(kaptContext) {
fun saveKDocComment(tree: JCTree, node: Any) {
val origin = kaptContext.origins[node] ?: return
val psiElement = origin.element as? KtDeclaration ?: return
val descriptor = origin.descriptor
val docComment = psiElement.docComment ?: return
if (descriptor is ConstructorDescriptor && psiElement is KtClassOrObject) {
// We don't want the class comment to be duplicated on <init>()
return
}
if (node is MethodNode
&& psiElement is KtProperty
&& descriptor is PropertyAccessorDescriptor
&& kaptContext.bindingContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor.correspondingProperty] == true
) {
// Do not place documentation on backing field and property accessors
return
}
if (node is FieldNode && psiElement is KtObjectDeclaration && descriptor == null) {
// Do not write KDoc on object instance field
return
}
saveKDocComment(tree, docComment)
}
}
@@ -16,26 +16,15 @@
package org.jetbrains.kotlin.kapt3.stubs
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation
import org.jetbrains.kotlin.kapt3.base.stubs.KotlinPosition
import org.jetbrains.kotlin.kapt3.base.stubs.LineInfoMap
import org.jetbrains.kotlin.kapt3.base.stubs.getJavacSignature
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.*
class KaptLineMappingCollector(private val kaptContext: KaptContextForStubGeneration) {
private val lineInfo: LineInfoMap = mutableMapOf()
private val signatureInfo = mutableMapOf<String, String>()
private val filePaths = mutableMapOf<PsiFile, Pair<String, Boolean>>()
class KaptLineMappingCollector(private val kaptContext: KaptContextForStubGeneration) : KaptLineMappingCollectorBase() {
fun registerClass(clazz: ClassNode) {
register(clazz, clazz.name)
}
@@ -60,57 +49,4 @@ class KaptLineMappingCollector(private val kaptContext: KaptContextForStubGenera
val psiElement = kaptContext.origins[asmNode]?.element ?: return
register(fqName, psiElement)
}
private fun register(fqName: String, psiElement: PsiElement) {
val containingVirtualFile = psiElement.containingFile.virtualFile
if (containingVirtualFile == null || FileDocumentManager.getInstance().getDocument(containingVirtualFile) == null) {
return
}
val textRange = psiElement.textRange ?: return
val (path, isRelative) = getFilePathRelativePreferred(psiElement.containingFile)
lineInfo[fqName] = KotlinPosition(path, isRelative, textRange.startOffset)
}
private fun getFilePathRelativePreferred(file: PsiFile): Pair<String, Boolean> {
return filePaths.getOrPut(file) {
val absolutePath = file.virtualFile.canonicalPath ?: file.virtualFile.path
val absoluteFile = File(absolutePath)
val baseFile = file.project.basePath?.let { File(it) }
if (absoluteFile.exists() && baseFile != null && baseFile.exists()) {
val relativePath = absoluteFile.relativeToOrNull(baseFile)?.path
if (relativePath != null) {
return@getOrPut Pair(relativePath, true)
}
}
return@getOrPut Pair(absolutePath, false)
}
}
fun serialize(): ByteArray {
val os = ByteArrayOutputStream()
val oos = ObjectOutputStream(os)
oos.writeInt(KaptStubLineInformation.METADATA_VERSION)
oos.writeInt(lineInfo.size)
for ((fqName, kotlinPosition) in lineInfo) {
oos.writeUTF(fqName)
oos.writeUTF(kotlinPosition.path)
oos.writeBoolean(kotlinPosition.isRelativePath)
oos.writeInt(kotlinPosition.pos)
}
oos.writeInt(signatureInfo.size)
for ((javacSignature, methodDesc) in signatureInfo) {
oos.writeUTF(javacSignature)
oos.writeUTF(methodDesc)
}
oos.flush()
return os.toByteArray()
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.kapt3.stubs
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation
import org.jetbrains.kotlin.kapt3.base.stubs.KotlinPosition
import org.jetbrains.kotlin.kapt3.base.stubs.LineInfoMap
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.ObjectOutputStream
abstract class KaptLineMappingCollectorBase {
protected val lineInfo: LineInfoMap = mutableMapOf()
protected val signatureInfo = mutableMapOf<String, String>()
private val filePaths = mutableMapOf<PsiFile, Pair<String, Boolean>>()
protected fun register(fqName: String, psiElement: PsiElement) {
val containingVirtualFile = psiElement.containingFile.virtualFile
if (containingVirtualFile == null || FileDocumentManager.getInstance().getDocument(containingVirtualFile) == null) {
return
}
val textRange = psiElement.textRange ?: return
val (path, isRelative) = getFilePathRelativePreferred(psiElement.containingFile)
lineInfo[fqName] = KotlinPosition(path, isRelative, textRange.startOffset)
}
private fun getFilePathRelativePreferred(file: PsiFile): Pair<String, Boolean> {
return filePaths.getOrPut(file) {
val absolutePath = file.virtualFile.canonicalPath ?: file.virtualFile.path
val absoluteFile = File(absolutePath)
val baseFile = file.project.basePath?.let { File(it) }
if (absoluteFile.exists() && baseFile != null && baseFile.exists()) {
val relativePath = absoluteFile.relativeToOrNull(baseFile)?.path
if (relativePath != null) {
return@getOrPut Pair(relativePath, true)
}
}
return@getOrPut Pair(absolutePath, false)
}
}
fun serialize(): ByteArray {
val os = ByteArrayOutputStream()
val oos = ObjectOutputStream(os)
oos.writeInt(KaptStubLineInformation.METADATA_VERSION)
oos.writeInt(lineInfo.size)
for ((fqName, kotlinPosition) in lineInfo) {
oos.writeUTF(fqName)
oos.writeUTF(kotlinPosition.path)
oos.writeBoolean(kotlinPosition.isRelativePath)
oos.writeInt(kotlinPosition.pos)
}
oos.writeInt(signatureInfo.size)
for ((javacSignature, methodDesc) in signatureInfo) {
oos.writeUTF(javacSignature)
oos.writeUTF(methodDesc)
}
oos.flush()
return os.toByteArray()
}
}
@@ -0,0 +1,54 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.kapt3.stubs
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.kapt3.base.stubs.KotlinPosition
/**
* Sort class members. If the source file for the class is unknown, just sort using name and descriptor. Otherwise:
* - all members in the same source file as the class come first (members may come from other source files)
* - members from the class are sorted using their position in the source file
* - members from other source files are sorted using their name and descriptor
*
* More details: Class methods and fields are currently sorted at serialization (see DescriptorSerializer.sort) and at deserialization
* (see DeserializedMemberScope.OptimizedImplementation#addMembers). Therefore, the contents of the generated stub files are sorted in
* incremental builds but not in clean builds.
* The consequence is that the contents of the generated stub files may not be consistent across a clean build and an incremental
* build, making the build non-deterministic and dependent tasks run unnecessarily (see KT-40882).
*/
class MembersPositionComparator(val classSource: KotlinPosition?, val memberData: Map<JCTree, MemberData>) :
Comparator<JCTree> {
override fun compare(o1: JCTree, o2: JCTree): Int {
val data1 = memberData.getValue(o1)
val data2 = memberData.getValue(o2)
classSource ?: return compareDescriptors(data1, data2)
val position1 = data1.position
val position2 = data2.position
return if (position1 != null && position1.path == classSource.path) {
if (position2 != null && position2.path == classSource.path) {
val positionCompare = position1.pos.compareTo(position2.pos)
if (positionCompare != 0) positionCompare
else compareDescriptors(data1, data2)
} else {
-1
}
} else if (position2 != null && position2.path == classSource.path) {
1
} else {
compareDescriptors(data1, data2)
}
}
private fun compareDescriptors(m1: MemberData, m2: MemberData): Int {
val nameComparison = m1.name.compareTo(m2.name)
if (nameComparison != 0) return nameComparison
return m1.descriptor.compareTo(m2.descriptor)
}
}
class MemberData(val name: String, val descriptor: String, val position: KotlinPosition?)
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.kapt3.util
import com.sun.tools.javac.code.Flags
import com.sun.tools.javac.tree.JCTree
import com.sun.tools.javac.tree.Pretty
import com.sun.tools.javac.tree.TreeMaker
import com.sun.tools.javac.util.Context
import org.jetbrains.kotlin.kapt3.base.util.isJava11OrLater
import java.io.StringWriter
import java.io.Writer
class PrettyWithWorkarounds(private val context: Context, val out: Writer, sourceOutput: Boolean) : Pretty(out, sourceOutput) {
companion object {
private const val ENUM = Flags.ENUM.toLong()
}
override fun print(s: Any) {
out.write(s.toString())
}
override fun visitVarDef(tree: JCTree.JCVariableDecl) {
if ((tree.mods.flags and ENUM) != 0L) {
// Pretty does not print annotations for enum values for some reason
printExpr(TreeMaker.instance(context).Modifiers(0, tree.mods.annotations))
if (isJava11OrLater()) {
// Print enums fully, there is an issue when using Pretty in JDK 11.
// See https://youtrack.jetbrains.com/issue/KT-33052.
print("/*public static final*/ ${tree.name}")
tree.init?.let { print(" /* = $it */") }
return
}
}
super.visitVarDef(tree)
}
}
fun JCTree.prettyPrint(context: Context): String {
return StringWriter().apply { PrettyWithWorkarounds(context, this, false).printStat(this@prettyPrint) }.toString()
}
@@ -10,14 +10,12 @@ import com.sun.tools.javac.util.List
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
import org.jetbrains.kotlin.kapt3.base.parseJavaFiles
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
import org.jetbrains.kotlin.kapt3.prettyPrint
import org.jetbrains.kotlin.kapt3.util.prettyPrint
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.getRealJavaFiles
import org.jetbrains.kotlin.test.services.sourceFileProvider
import org.jetbrains.kotlin.test.utils.withExtension
import org.jetbrains.kotlin.test.utils.withSuffixAndExtension
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import java.io.File
@@ -10,7 +10,7 @@ import com.sun.tools.javac.comp.CompileStates
import com.sun.tools.javac.util.JCDiagnostic
import com.sun.tools.javac.util.Log
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLogBase
import org.jetbrains.kotlin.kapt3.prettyPrint
import org.jetbrains.kotlin.kapt3.util.prettyPrint
import org.jetbrains.kotlin.kapt3.test.KaptContextBinaryArtifact
import org.jetbrains.kotlin.kapt3.test.KaptTestDirectives.EXPECTED_ERROR
import org.jetbrains.kotlin.kapt3.test.KaptTestDirectives.NON_EXISTENT_CLASS
@@ -27,8 +27,7 @@ fun Assertions.checkTxtAccordingToBackend(module: TestModule, actual: String, fi
}
}
private const val KOTLIN_METADATA_GROUP = "[a-z0-9]+ = (\\{.+?\\}|[0-9]+)"
private val KOTLIN_METADATA_REGEX = "@kotlin\\.Metadata\\(($KOTLIN_METADATA_GROUP)(, $KOTLIN_METADATA_GROUP)*\\)".toRegex()
private val KOTLIN_METADATA_REGEX = "@kotlin\\.Metadata\\(.*\\)".toRegex()
fun removeMetadataAnnotationContents(s: String): String {
return s.replace(KOTLIN_METADATA_REGEX, "@kotlin.Metadata()")
@@ -12,12 +12,11 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.kapt3.AbstractKapt3Extension
import org.jetbrains.kotlin.kapt3.KaptContextForStubGeneration
import org.jetbrains.kotlin.kapt3.base.KaptContext
import org.jetbrains.kotlin.kapt3.base.LoadedProcessors
import org.jetbrains.kotlin.kapt3.base.incremental.DeclaredProcType
import org.jetbrains.kotlin.kapt3.base.incremental.IncrementalProcessor
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
import org.jetbrains.kotlin.kapt3.prettyPrint
import org.jetbrains.kotlin.kapt3.util.prettyPrint
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
import org.jetbrains.kotlin.kapt3.test.handlers.ClassFileToSourceKaptStubHandler.Companion.FILE_SEPARATOR
import org.jetbrains.kotlin.kapt3.util.MessageCollectorBackedKaptLogger