[KAPT] KT-44706 Support @JvmRecord-annotated classes
Don't parse Java stubs in tests if no validation is needed Merge-request: KT-MR-14308 Merged-by: Pavel Mikhailovskii <Pavel.Mikhailovskii@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
6288bdbd3f
commit
12552e4e04
@@ -0,0 +1,122 @@
|
|||||||
|
/**
|
||||||
|
* public final annotation class A : kotlin/Annotation {
|
||||||
|
*
|
||||||
|
* // signature: <init>()V
|
||||||
|
* public constructor()
|
||||||
|
*
|
||||||
|
* // module name: main
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
@kotlin.Metadata()
|
||||||
|
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||||
|
public abstract @interface A {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* public abstract interface I : kotlin/Any {
|
||||||
|
*
|
||||||
|
* // signature: foo()I
|
||||||
|
* public abstract fun foo(): kotlin/Int
|
||||||
|
*
|
||||||
|
* // module name: main
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
@kotlin.Metadata()
|
||||||
|
public abstract interface I {
|
||||||
|
|
||||||
|
public abstract int foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* public final data class R<T#0 (* T *)> : I, java/lang/Record {
|
||||||
|
*
|
||||||
|
* // signature: <init>(ILjava/lang/Object;)V
|
||||||
|
* public constructor(x: kotlin/Int, y: T#0)
|
||||||
|
*
|
||||||
|
* // signature: <init>(Ljava/lang/Object;)V
|
||||||
|
* public (* secondary *) constructor(y: T#0)
|
||||||
|
*
|
||||||
|
* // signature: component1()I
|
||||||
|
* public final (* synthesized *) operator fun component1(): kotlin/Int
|
||||||
|
*
|
||||||
|
* // signature: equals(Ljava/lang/Object;)Z
|
||||||
|
* public open (* synthesized *) operator fun equals(other: kotlin/Any?): kotlin/Boolean
|
||||||
|
*
|
||||||
|
* // signature: foo()I
|
||||||
|
* public open fun foo(): kotlin/Int
|
||||||
|
*
|
||||||
|
* // signature: hashCode()I
|
||||||
|
* public open (* synthesized *) fun hashCode(): kotlin/Int
|
||||||
|
*
|
||||||
|
* public final (* synthesized *) operator fun component2(): T#0
|
||||||
|
*
|
||||||
|
* public final (* synthesized *) fun copy(x: kotlin/Int (* = ... *), y: T#0 (* = ... *)): R<T#0>
|
||||||
|
*
|
||||||
|
* // signature: toString()Ljava/lang/String;
|
||||||
|
* public open (* synthesized *) fun toString(): kotlin/String
|
||||||
|
*
|
||||||
|
* // field: x:I
|
||||||
|
* public final val x: kotlin/Int
|
||||||
|
* public final get
|
||||||
|
*
|
||||||
|
* // field: y:Ljava/lang/Object;
|
||||||
|
* public final val y: T#0
|
||||||
|
* public final get
|
||||||
|
*
|
||||||
|
* // module name: main
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
@kotlin.Metadata()
|
||||||
|
@A()
|
||||||
|
@kotlin.jvm.JvmRecord()
|
||||||
|
public record R<T extends java.lang.Object>(@A() int x, T y) implements I {
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final R<T> copy(@A() int x, T y) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(@org.jetbrains.annotations.Nullable() java.lang.Object other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public java.lang.String toString() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int component1() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int x() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T component2() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T y() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public R(T y) {
|
||||||
|
this(0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public int foo() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// JDK_KIND: FULL_JDK_21
|
||||||
|
// NO_VALIDATION
|
||||||
|
annotation class A
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
fun foo(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
@A
|
||||||
|
@JvmRecord
|
||||||
|
data class R<T>(@A val x: Int, val y: T): I {
|
||||||
|
constructor(y: T) : this(0, y)
|
||||||
|
|
||||||
|
override fun foo(): Int = 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
|
||||||
|
/**
|
||||||
|
* public final annotation class A : kotlin/Annotation {
|
||||||
|
*
|
||||||
|
* // signature: <init>()V
|
||||||
|
* public constructor()
|
||||||
|
*
|
||||||
|
* // module name: main
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
@kotlin.Metadata()
|
||||||
|
public abstract @interface A {
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* public abstract interface I : kotlin/Any {
|
||||||
|
*
|
||||||
|
* // signature: foo()I
|
||||||
|
* public abstract fun foo(): kotlin/Int
|
||||||
|
*
|
||||||
|
* // module name: main
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
@kotlin.Metadata()
|
||||||
|
public abstract interface I {
|
||||||
|
|
||||||
|
public abstract int foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
@A()
|
||||||
|
/**
|
||||||
|
* public final data class R<T#0 (* T *)> : I, java/lang/Record {
|
||||||
|
*
|
||||||
|
* // signature: <init>(ILjava/lang/Object;)V
|
||||||
|
* public constructor(x: kotlin/Int, y: T#0)
|
||||||
|
*
|
||||||
|
* // signature: <init>(Ljava/lang/Object;)V
|
||||||
|
* public (* secondary *) constructor(y: T#0)
|
||||||
|
*
|
||||||
|
* // signature: component1()I
|
||||||
|
* public final (* synthesized *) operator fun component1(): kotlin/Int
|
||||||
|
*
|
||||||
|
* // signature: component2()Ljava/lang/Object;
|
||||||
|
* public final (* synthesized *) operator fun component2(): T#0
|
||||||
|
*
|
||||||
|
* // signature: copy(ILjava/lang/Object;)LR;
|
||||||
|
* public final (* synthesized *) fun copy(x: kotlin/Int (* = ... *), y: T#0 (* = ... *)): R<T#0>
|
||||||
|
*
|
||||||
|
* // signature: equals(Ljava/lang/Object;)Z
|
||||||
|
* public open (* synthesized *) operator fun equals(other: kotlin/Any?): kotlin/Boolean
|
||||||
|
*
|
||||||
|
* // signature: foo()I
|
||||||
|
* public open fun foo(): kotlin/Int
|
||||||
|
*
|
||||||
|
* // signature: hashCode()I
|
||||||
|
* public open (* synthesized *) fun hashCode(): kotlin/Int
|
||||||
|
*
|
||||||
|
* // signature: toString()Ljava/lang/String;
|
||||||
|
* public open (* synthesized *) fun toString(): kotlin/String
|
||||||
|
*
|
||||||
|
* // field: x:I
|
||||||
|
* // getter: x()I
|
||||||
|
* public final val x: kotlin/Int
|
||||||
|
* public final get
|
||||||
|
*
|
||||||
|
* // field: y:Ljava/lang/Object;
|
||||||
|
* // getter: y()Ljava/lang/Object;
|
||||||
|
* public final val y: T#0
|
||||||
|
* public final get
|
||||||
|
*
|
||||||
|
* // module name: main
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
@kotlin.Metadata()
|
||||||
|
@kotlin.jvm.JvmRecord()
|
||||||
|
public final class R<T extends java.lang.Object> extends java.lang.Record implements I {
|
||||||
|
private final int x = 0;
|
||||||
|
private final T y = null;
|
||||||
|
|
||||||
|
public R(@A()
|
||||||
|
int x, T y) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int x() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T y() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public R(T y) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public int foo() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int component1() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final T component2() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public final R<T> copy(@A()
|
||||||
|
int x, T y) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public boolean equals(@org.jetbrains.annotations.Nullable()
|
||||||
|
java.lang.Object other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public int hashCode() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public java.lang.String toString() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -389,6 +389,12 @@ public class IrClassFileToSourceStubConverterTestGenerated extends AbstractIrCla
|
|||||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/jvmOverloads.kt");
|
runTest("plugins/kapt3/kapt3-compiler/testData/converter/jvmOverloads.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jvmRecord.kt")
|
||||||
|
public void testJvmRecord() {
|
||||||
|
runTest("plugins/kapt3/kapt3-compiler/testData/converter/jvmRecord.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("jvmRepeatableAnnotation.kt")
|
@TestMetadata("jvmRepeatableAnnotation.kt")
|
||||||
public void testJvmRepeatableAnnotation() {
|
public void testJvmRepeatableAnnotation() {
|
||||||
|
|||||||
@@ -218,33 +218,40 @@ private class StubGenerator(
|
|||||||
|
|
||||||
printComment(psiClass)
|
printComment(psiClass)
|
||||||
|
|
||||||
|
calculateMetadata(psiClass)?.let { printMetadata(it) }
|
||||||
|
printModifiers(psiClass)
|
||||||
val classWord = when {
|
val classWord = when {
|
||||||
psiClass.isAnnotationType -> "@interface"
|
psiClass.isAnnotationType -> "@interface"
|
||||||
psiClass.isInterface -> "interface"
|
psiClass.isInterface -> "interface"
|
||||||
psiClass.isEnum -> "enum"
|
psiClass.isEnum -> "enum"
|
||||||
|
psiClass.isRecord -> "record"
|
||||||
else -> "class"
|
else -> "class"
|
||||||
}
|
}
|
||||||
calculateMetadata(psiClass)?.let { printMetadata(it) }
|
|
||||||
printModifiers(psiClass)
|
|
||||||
printWithNoIndent(classWord, " ", simpleName)
|
printWithNoIndent(classWord, " ", simpleName)
|
||||||
printTypeParams(psiClass.typeParameters)
|
printTypeParams(psiClass.typeParameters)
|
||||||
|
|
||||||
psiClass.extendsList
|
if (psiClass.isRecord) {
|
||||||
?.referencedTypes
|
printParameters(psiClass.constructors.first())
|
||||||
?.asList()
|
}
|
||||||
?.let { if (!psiClass.isInterface) it.take(1) else it }
|
|
||||||
?.takeIf { it.isNotEmpty() }
|
if (!psiClass.isRecord) {
|
||||||
?.let { superClasses ->
|
psiClass.extendsList
|
||||||
printWithNoIndent(" extends ")
|
?.referencedTypes
|
||||||
superClasses.forEachIndexed { index, type ->
|
?.asList()
|
||||||
if (index > 0) printWithNoIndent(", ")
|
?.let { if (!psiClass.isInterface) it.take(1) else it }
|
||||||
printType(type)
|
?.takeIf { it.isNotEmpty() }
|
||||||
|
?.let { superClasses ->
|
||||||
|
printWithNoIndent(" extends ")
|
||||||
|
superClasses.forEachIndexed { index, type ->
|
||||||
|
if (index > 0) printWithNoIndent(", ")
|
||||||
|
printType(type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
psiClass.implementsList
|
psiClass.implementsList
|
||||||
?.referencedTypes
|
?.referencedTypes
|
||||||
?.filterNot { it.canonicalText.startsWith("kotlin.collections.") }
|
?.filterNot { it.qualifiedName.startsWith("kotlin.collections.") || it.qualifiedName == "java.lang.Record" }
|
||||||
?.takeIf { it.isNotEmpty() }
|
?.takeIf { it.isNotEmpty() }
|
||||||
?.let { interfaces ->
|
?.let { interfaces ->
|
||||||
printWithNoIndent(" implements ")
|
printWithNoIndent(" implements ")
|
||||||
@@ -253,6 +260,7 @@ private class StubGenerator(
|
|||||||
printType(type)
|
printType(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printlnWithNoIndent(" {")
|
printlnWithNoIndent(" {")
|
||||||
pushIndent()
|
pushIndent()
|
||||||
|
|
||||||
@@ -278,9 +286,12 @@ private class StubGenerator(
|
|||||||
.onEach { lineMappings.registerField(psiClass, it) }
|
.onEach { lineMappings.registerField(psiClass, it) }
|
||||||
.associateWith { MemberData(it.name, it.signature, lineMappings.getPosition(psiClass, it)) }
|
.associateWith { MemberData(it.name, it.signature, lineMappings.getPosition(psiClass, it)) }
|
||||||
|
|
||||||
fieldsPositions.keys.sortedWith(MembersPositionComparator(classPosition, fieldsPositions)).forEachIndexed { index, field ->
|
if (!psiClass.isRecord) {
|
||||||
if (index > 0) printlnWithNoIndent()
|
fieldsPositions.keys.sortedWith(MembersPositionComparator(classPosition, fieldsPositions))
|
||||||
printField(field)
|
.forEachIndexed { index, field ->
|
||||||
|
if (index > 0) printlnWithNoIndent()
|
||||||
|
printField(field)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val methodsPositions = psiClass.methods
|
val methodsPositions = psiClass.methods
|
||||||
@@ -292,12 +303,13 @@ private class StubGenerator(
|
|||||||
.onEach { lineMappings.registerMethod(psiClass, it) }
|
.onEach { lineMappings.registerMethod(psiClass, it) }
|
||||||
.associateWith { MemberData(it.name, it.signature, lineMappings.getPosition(psiClass, it)) }
|
.associateWith { MemberData(it.name, it.signature, lineMappings.getPosition(psiClass, it)) }
|
||||||
|
|
||||||
if (methodsPositions.isNotEmpty()) printlnWithNoIndent()
|
|
||||||
methodsPositions.keys.sortedWith(MembersPositionComparator(classPosition, methodsPositions))
|
methodsPositions.keys.sortedWith(MembersPositionComparator(classPosition, methodsPositions))
|
||||||
.forEachIndexed { index, method ->
|
.forEach { method ->
|
||||||
lineMappings.registerSignature(javacSignature(method), method)
|
lineMappings.registerSignature(javacSignature(method), method)
|
||||||
if (index > 0) printlnWithNoIndent()
|
if (!psiClass.isRecord || method != psiClass.constructors.firstOrNull()) {
|
||||||
printMethod(method)
|
printlnWithNoIndent()
|
||||||
|
printMethod(method)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psiClass.innerClasses.isNotEmpty() && (fieldsPositions.isNotEmpty() || methodsPositions.isNotEmpty())) println()
|
if (psiClass.innerClasses.isNotEmpty() && (fieldsPositions.isNotEmpty() || methodsPositions.isNotEmpty())) println()
|
||||||
@@ -350,14 +362,8 @@ private class StubGenerator(
|
|||||||
printType(it)
|
printType(it)
|
||||||
printWithNoIndent(" ")
|
printWithNoIndent(" ")
|
||||||
}
|
}
|
||||||
printWithNoIndent(method.name, "(")
|
printWithNoIndent(method.name)
|
||||||
method.parameterList.parameters.filter { isValidIdentifier(paramName(it)) }.forEachIndexed { index, param ->
|
printParameters(method)
|
||||||
if (index > 0) printWithNoIndent(", ")
|
|
||||||
printModifiers(param)
|
|
||||||
printType(param.type)
|
|
||||||
printWithNoIndent(" ", paramName(param))
|
|
||||||
}
|
|
||||||
printWithNoIndent(")")
|
|
||||||
(method as? PsiAnnotationMethod)?.defaultValue?.let {
|
(method as? PsiAnnotationMethod)?.defaultValue?.let {
|
||||||
printWithNoIndent(" default ")
|
printWithNoIndent(" default ")
|
||||||
printAnnotationMemberValue(it)
|
printAnnotationMemberValue(it)
|
||||||
@@ -378,10 +384,10 @@ private class StubGenerator(
|
|||||||
pushIndent()
|
pushIndent()
|
||||||
|
|
||||||
if (method.isConstructor && !psiClass.isEnum) {
|
if (method.isConstructor && !psiClass.isEnum) {
|
||||||
val superConstructor = method.containingClass?.superClass?.constructors?.firstOrNull { !it.isPrivate }
|
val delegateTo = (if (psiClass.isRecord) psiClass else psiClass.superClass)?.constructors?.firstOrNull { !it.isPrivate }
|
||||||
if (superConstructor != null) {
|
if (delegateTo != null) {
|
||||||
print("super(")
|
print(if (psiClass.isRecord) "this(" else "super(")
|
||||||
val args = superConstructor.parameterList.parameters.map { defaultValue(it.type) }
|
val args = delegateTo.parameterList.parameters.map { defaultValue(it.type) }
|
||||||
args.forEachIndexed { index, arg ->
|
args.forEachIndexed { index, arg ->
|
||||||
if (index > 0) printWithNoIndent(", ")
|
if (index > 0) printWithNoIndent(", ")
|
||||||
printWithNoIndent(arg)
|
printWithNoIndent(arg)
|
||||||
@@ -396,6 +402,17 @@ private class StubGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Printer.printParameters(method: PsiMethod) {
|
||||||
|
printWithNoIndent("(")
|
||||||
|
method.parameterList.parameters.filter { isValidIdentifier(paramName(it)) }.forEachIndexed { index, param ->
|
||||||
|
if (index > 0) printWithNoIndent(", ")
|
||||||
|
printModifiers(param)
|
||||||
|
printType(param.type)
|
||||||
|
printWithNoIndent(" ", paramName(param))
|
||||||
|
}
|
||||||
|
printWithNoIndent(")")
|
||||||
|
}
|
||||||
|
|
||||||
private fun javacSignature(method: PsiMethod) = printToString {
|
private fun javacSignature(method: PsiMethod) = printToString {
|
||||||
print(method.name, "(")
|
print(method.name, "(")
|
||||||
method.parameterList.parameters.forEachIndexed{ index, parameter ->
|
method.parameterList.parameters.forEachIndexed{ index, parameter ->
|
||||||
@@ -525,6 +542,7 @@ private class StubGenerator(
|
|||||||
onError("Support for interface methods with bodies in Kapt requires -Xjvm-default=all or -Xjvm-default=all-compatibility compiler option")
|
onError("Support for interface methods with bodies in Kapt requires -Xjvm-default=all or -Xjvm-default=all-compatibility compiler option")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (modifier == PsiModifier.FINAL && modifierListOwner is PsiClass && modifierListOwner.isRecord) continue
|
||||||
if ((modifier != PsiModifier.FINAL && modifier != PsiModifier.ABSTRACT) || !(modifierListOwner is PsiClass && modifierListOwner.isEnum)) {
|
if ((modifier != PsiModifier.FINAL && modifier != PsiModifier.ABSTRACT) || !(modifierListOwner is PsiClass && modifierListOwner.isEnum)) {
|
||||||
printWithNoIndent(modifier, " ")
|
printWithNoIndent(modifier, " ")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
|||||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenProvider
|
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenProvider
|
||||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementLifetimeTokenProvider
|
import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementLifetimeTokenProvider
|
||||||
import org.jetbrains.kotlin.analysis.api.standalone.buildStandaloneAnalysisAPISession
|
import org.jetbrains.kotlin.analysis.api.standalone.buildStandaloneAnalysisAPISession
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
|
||||||
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
|
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
||||||
@@ -47,12 +46,12 @@ internal class Kapt4Facade(private val testServices: TestServices) :
|
|||||||
val configuration = configurationProvider.getCompilerConfiguration(module)
|
val configuration = configurationProvider.getCompilerConfiguration(module)
|
||||||
configuration.addKotlinSourceRoots(module.files.filter { it.isKtFile }.map { it.realFile().absolutePath })
|
configuration.addKotlinSourceRoots(module.files.filter { it.isKtFile }.map { it.realFile().absolutePath })
|
||||||
val options = testServices.kaptOptionsProvider[module]
|
val options = testServices.kaptOptionsProvider[module]
|
||||||
val (context, stubMap) = run(
|
val (context, stubs) = run(
|
||||||
configuration,
|
configuration,
|
||||||
options,
|
options,
|
||||||
configurationProvider.testRootDisposable
|
configurationProvider.testRootDisposable
|
||||||
)
|
)
|
||||||
return Kapt4ContextBinaryArtifact(context, stubMap.values.filterNotNull())
|
return Kapt4ContextBinaryArtifact(context, stubs)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TestFile.realFile(): File {
|
private fun TestFile.realFile(): File {
|
||||||
@@ -69,7 +68,7 @@ private fun run(
|
|||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
options: KaptOptions,
|
options: KaptOptions,
|
||||||
projectDisposable: Disposable,
|
projectDisposable: Disposable,
|
||||||
): Pair<KaptContext, Map<KtLightClass, KaptStub?>> {
|
): Pair<KaptContext, List<KaptStub>> {
|
||||||
val standaloneAnalysisAPISession = buildStandaloneAnalysisAPISession(projectDisposable) {
|
val standaloneAnalysisAPISession = buildStandaloneAnalysisAPISession(projectDisposable) {
|
||||||
(project as MockProject).registerService(
|
(project as MockProject).registerService(
|
||||||
KtLifetimeTokenProvider::class.java,
|
KtLifetimeTokenProvider::class.java,
|
||||||
@@ -111,7 +110,8 @@ private fun run(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return context to generateStubs(module, files, options, logger, metadataRenderer = { renderMetadata(it) })
|
val stubsMap = generateStubs(module, files, options, logger, metadataRenderer = { renderMetadata(it) })
|
||||||
|
return context to stubsMap.entries.sortedBy { it.key.qualifiedName }.mapNotNull { it.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal data class Kapt4ContextBinaryArtifact(
|
internal data class Kapt4ContextBinaryArtifact(
|
||||||
|
|||||||
@@ -41,26 +41,24 @@ internal class Kapt4Handler(testServices: TestServices) : AnalysisHandler<Kapt4C
|
|||||||
get() = Kapt4ContextBinaryArtifact.Kind
|
get() = Kapt4ContextBinaryArtifact.Kind
|
||||||
|
|
||||||
override fun processModule(module: TestModule, info: Kapt4ContextBinaryArtifact) {
|
override fun processModule(module: TestModule, info: Kapt4ContextBinaryArtifact) {
|
||||||
val validate = KaptTestDirectives.NO_VALIDATION !in module.directives
|
val stubs = info.kaptStubs.map { it.source }
|
||||||
|
val actualRaw = stubs.joinToString(ClassFileToSourceKaptStubHandler.FILE_SEPARATOR)
|
||||||
val (kaptContext) = info
|
|
||||||
val convertedFiles = getJavaFiles(info)
|
|
||||||
kaptContext.javaLog.interceptorData.files = convertedFiles.associateBy { it.sourceFile }
|
|
||||||
if (validate) kaptContext.compiler.enterTrees(convertedFiles)
|
|
||||||
|
|
||||||
val actualRaw = convertedFiles
|
|
||||||
.sortedBy { it.sourceFile.name }
|
|
||||||
.joinToString(ClassFileToSourceKaptStubHandler.FILE_SEPARATOR) { (it.sourceFile as KaptJavaFileObject).file!!.readText() }
|
|
||||||
|
|
||||||
val actual = StringUtil.convertLineSeparators(actualRaw.trim { it <= ' ' })
|
val actual = StringUtil.convertLineSeparators(actualRaw.trim { it <= ' ' })
|
||||||
.trimTrailingWhitespacesAndAddNewlineAtEOF()
|
.trimTrailingWhitespacesAndAddNewlineAtEOF()
|
||||||
.let { removeMetadataAnnotationContents(it) }
|
.let { removeMetadataAnnotationContents(it) }
|
||||||
|
|
||||||
|
val validate = KaptTestDirectives.NO_VALIDATION !in module.directives
|
||||||
|
if (validate) {
|
||||||
|
val (kaptContext) = info
|
||||||
|
val convertedFiles = getJavaFiles(info)
|
||||||
|
kaptContext.javaLog.interceptorData.files = convertedFiles.associateBy { it.sourceFile }
|
||||||
|
kaptContext.compiler.enterTrees(convertedFiles)
|
||||||
|
}
|
||||||
assertions.assertAll(
|
assertions.assertAll(
|
||||||
{ assertions.checkTxt(module, actual) },
|
{ assertions.checkTxt(module, actual) },
|
||||||
{
|
{
|
||||||
if (kaptContext.compiler.shouldStop(CompileStates.CompileState.ENTER)) {
|
if (info.kaptContext.compiler.shouldStop(CompileStates.CompileState.ENTER)) {
|
||||||
checkJavaCompilerErrors(module, kaptContext, actual)
|
checkJavaCompilerErrors(module, info.kaptContext, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
+6
@@ -389,6 +389,12 @@ public class KotlinKapt4ContextTestGenerated extends AbstractKotlinKapt4ContextT
|
|||||||
runTest("plugins/kapt4/../kapt3/kapt3-compiler/testData/converter/jvmOverloads.kt");
|
runTest("plugins/kapt4/../kapt3/kapt3-compiler/testData/converter/jvmOverloads.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jvmRecord.kt")
|
||||||
|
public void testJvmRecord() {
|
||||||
|
runTest("plugins/kapt4/../kapt3/kapt3-compiler/testData/converter/jvmRecord.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("jvmRepeatableAnnotation.kt")
|
@TestMetadata("jvmRepeatableAnnotation.kt")
|
||||||
public void testJvmRepeatableAnnotation() {
|
public void testJvmRepeatableAnnotation() {
|
||||||
|
|||||||
Reference in New Issue
Block a user