[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:
committed by
Space Team
parent
c702f00399
commit
7ecd7b8e61
@@ -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()
|
||||
|
||||
+4
-34
@@ -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 {
|
||||
+1
-47
@@ -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 {
|
||||
|
||||
+48
@@ -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)
|
||||
}
|
||||
}
|
||||
+1
-65
@@ -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()
|
||||
}
|
||||
}
|
||||
+75
@@ -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()
|
||||
}
|
||||
}
|
||||
+54
@@ -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?)
|
||||
+45
@@ -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()
|
||||
}
|
||||
+1
-3
@@ -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
|
||||
|
||||
|
||||
+1
-1
@@ -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()")
|
||||
|
||||
+1
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user