diff --git a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/KaptOptions.kt b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/KaptOptions.kt index 3e59bb3edc2..74224d5e94a 100644 --- a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/KaptOptions.kt +++ b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/KaptOptions.kt @@ -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}") diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt index 3f2e6e2bc3b..5497a2a9004 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Extension.kt @@ -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 measureTimeMillis(block: () -> T): Pair { val start = System.currentTimeMillis() diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt index c9321de55a6..ffac676d6a0 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt @@ -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() diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KDocCommentKeeper.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/AbstractKDocCommentKeeper.kt similarity index 77% rename from plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KDocCommentKeeper.kt rename to plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/AbstractKDocCommentKeeper.kt index a937c409577..4918af41baf 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KDocCommentKeeper.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/AbstractKDocCommentKeeper.kt @@ -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(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 () - 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 { diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index 14aaf57d389..25db1dd6e88 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -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) : - Comparator { - 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) private fun calculateSuperTypes(clazz: ClassNode, genericType: SignatureParser.ClassGenericSignature): ClassSupertypes { diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/Kapt3DocCommentKeeper.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/Kapt3DocCommentKeeper.kt new file mode 100644 index 00000000000..ec161bade2a --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/Kapt3DocCommentKeeper.kt @@ -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(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 () + 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) + } +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KaptLineMappingCollector.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KaptLineMappingCollector.kt index e1b4e5ce3ae..ca15a48a8a3 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KaptLineMappingCollector.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KaptLineMappingCollector.kt @@ -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() - - private val filePaths = mutableMapOf>() +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 { - 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() - } } \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KaptLineMappingCollectorBase.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KaptLineMappingCollectorBase.kt new file mode 100644 index 00000000000..fbeb347a7cc --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/KaptLineMappingCollectorBase.kt @@ -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() + private val filePaths = mutableMapOf>() + + 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 { + 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() + } +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/MembersPositionComparator.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/MembersPositionComparator.kt new file mode 100644 index 00000000000..b385d922da3 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/MembersPositionComparator.kt @@ -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) : + Comparator { + 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?) \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/util/PrettyWithWorkarounds.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/util/PrettyWithWorkarounds.kt new file mode 100644 index 00000000000..837cffacdfd --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/util/PrettyWithWorkarounds.kt @@ -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() +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/BaseKaptHandler.kt b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/BaseKaptHandler.kt index a09ea1e071b..d0fb33e9fa6 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/BaseKaptHandler.kt +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/BaseKaptHandler.kt @@ -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 diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/ClassFileToSourceKaptStubHandler.kt b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/ClassFileToSourceKaptStubHandler.kt index d4be6cee892..5432eb62333 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/ClassFileToSourceKaptStubHandler.kt +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/ClassFileToSourceKaptStubHandler.kt @@ -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 diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/utils.kt b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/utils.kt index b7a5ea4a372..bc91499ee49 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/utils.kt +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/handlers/utils.kt @@ -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()") diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/integration/Kapt3ExtensionProvider.kt b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/integration/Kapt3ExtensionProvider.kt index 3979046206a..765e5db7ab9 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/integration/Kapt3ExtensionProvider.kt +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/integration/Kapt3ExtensionProvider.kt @@ -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