[IR] Rename MFVC tests + Add test for get-field optimization
#KT-1179
This commit is contained in:
committed by
teamcity
parent
ec3c0af09d
commit
70293fab60
+2
-2
@@ -50202,9 +50202,9 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("MfvcFieldInitializationOrder.kt")
|
||||
@TestMetadata("mfvcFieldInitializationOrder.kt")
|
||||
public void testMfvcFieldInitializationOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/MfvcFieldInitializationOrder.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcFieldInitializationOrder.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+6
-6
@@ -5796,15 +5796,15 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("MFVCDeclaration.kt")
|
||||
public void testMFVCDeclaration() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/MFVCDeclaration.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("mfvcDeclaration.kt")
|
||||
public void testMfvcDeclaration() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/mfvcDeclaration.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("MFVCReassignments.kt")
|
||||
public void testMFVCReassignments() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/MFVCReassignments.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("mfvcReassignments.kt")
|
||||
public void testMfvcReassignments() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/mfvcReassignments.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -692,7 +692,7 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass
|
||||
val instance = targetRemappedParameter.rootMfvcNode.createInstanceFromBox(
|
||||
this@irBlock,
|
||||
irCastIfNeeded(irGet(bridgeParameter), targetParameterType),
|
||||
hasAccessToPrivateMembersOf(target, targetRemappedParameter.rootMfvcNode.mfvc)
|
||||
getOptimizedPublicAccess(target, targetRemappedParameter.rootMfvcNode.mfvc)
|
||||
) { error("Not applicable") }
|
||||
val newArguments = instance.makeFlattenedGetterExpressions()
|
||||
for (newArgument in newArguments) {
|
||||
|
||||
+16
-12
@@ -131,7 +131,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
val typeArguments = makeTypeArgumentsFromField(expression)
|
||||
var instance: ReceiverBasedMfvcNodeInstance? = null
|
||||
return scope.irBlock {
|
||||
instance = node.createInstanceFromBox(this, typeArguments, expression.receiver, true, ::variablesSaver)
|
||||
instance = node.createInstanceFromBox(this, typeArguments, expression.receiver, AccessType.AlwaysPrivate, ::variablesSaver)
|
||||
+instance!!.makeGetterExpression()
|
||||
}.also { expression2MfvcNodeInstanceAccessor[it] = MfvcNodeInstanceAccessor.Getter(instance!!) }
|
||||
}
|
||||
@@ -144,7 +144,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
var instance: ReceiverBasedMfvcNodeInstance? = null
|
||||
var values: List<IrExpression>? = null
|
||||
return scope.irBlock {
|
||||
instance = node.createInstanceFromBox(this, typeArguments, expression.receiver, true, ::variablesSaver)
|
||||
instance = node.createInstanceFromBox(this, typeArguments, expression.receiver, AccessType.AlwaysPrivate, ::variablesSaver)
|
||||
values = makeFlattenedExpressionsWithGivenSafety(node, safe, expression.value)
|
||||
instance!!.addSetterStatements(this, values!!)
|
||||
}.also { expression2MfvcNodeInstanceAccessor[it] = MfvcNodeInstanceAccessor.Setter(instance!!, values!!) }
|
||||
@@ -153,12 +153,19 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
fun makeReplacement(scope: IrBuilderWithScope, expression: IrCall): IrExpression? {
|
||||
val function = expression.symbol.owner
|
||||
val property = function.property?.takeIf { function.isGetter } ?: return null
|
||||
expression.dispatchReceiver?.get(property.name)?.let { return it }
|
||||
val dispatchReceiver = expression.dispatchReceiver
|
||||
dispatchReceiver?.get(property.name)?.let { return it }
|
||||
val node = replacements.getMfvcPropertyNode(property) ?: return null
|
||||
val typeArguments = makeTypeArgumentsFromFunction(expression)
|
||||
var instance: ReceiverBasedMfvcNodeInstance? = null
|
||||
return scope.irBlock {
|
||||
instance = node.createInstanceFromBox(this, typeArguments, expression.dispatchReceiver, false, ::variablesSaver)
|
||||
// Optimization: pure function access to leaf can be replaced with field access if the field itself is accessible
|
||||
val accessType = when {
|
||||
!node.hasPureUnboxMethod -> AccessType.AlwaysPublic
|
||||
dispatchReceiver == null -> AccessType.PrivateWhenNoBox
|
||||
else -> getOptimizedPublicAccess(dispatchReceiver.type.erasedUpperBound)
|
||||
}
|
||||
instance = node.createInstanceFromBox(this, typeArguments, dispatchReceiver, accessType, ::variablesSaver)
|
||||
+instance!!.makeGetterExpression()
|
||||
}.also { expression2MfvcNodeInstanceAccessor[it] = MfvcNodeInstanceAccessor.Getter(instance!!) }
|
||||
}
|
||||
@@ -502,7 +509,7 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
val receiver = sourceExplicitParameters[flattenedSourceIndex++]
|
||||
val rootNode = remappedTargetParameter.rootMfvcNode
|
||||
val instance = rootNode.createInstanceFromBox(
|
||||
this@irBlock, irGet(receiver), hasAccessToPrivateMembersOf(rootNode.mfvc), ::variablesSaver
|
||||
this@irBlock, irGet(receiver), getOptimizedPublicAccess(rootNode.mfvc), ::variablesSaver,
|
||||
)
|
||||
val flattenedExpressions = instance.makeFlattenedGetterExpressions()
|
||||
for (expression in flattenedExpressions) {
|
||||
@@ -982,17 +989,14 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
}
|
||||
}
|
||||
val expressionInstance = flattenedExpressionInstance ?: rootNode.createInstanceFromBox(
|
||||
this,
|
||||
transformedExpression,
|
||||
hasAccessToPrivateMembersOf(rootNode.mfvc),
|
||||
::variablesSaver,
|
||||
this, transformedExpression, getOptimizedPublicAccess(rootNode.mfvc), ::variablesSaver,
|
||||
)
|
||||
require(expressionInstance.size == instance.size) { "Incompatible assignment sizes: ${expressionInstance.size}, ${instance.size}" }
|
||||
instance.addSetterStatements(this, expressionInstance.makeFlattenedGetterExpressions())
|
||||
}
|
||||
|
||||
private fun hasAccessToPrivateMembersOf(parent: IrClass): Boolean =
|
||||
currentScope?.irElement?.let { hasAccessToPrivateMembersOf(it, parent) } == true
|
||||
private fun getOptimizedPublicAccess(parent: IrClass): AccessType =
|
||||
currentScope?.irElement?.let { getOptimizedPublicAccess(it, parent) } ?: AccessType.AlwaysPublic
|
||||
|
||||
/**
|
||||
* Removes boxing when the result is not used
|
||||
@@ -1123,7 +1127,7 @@ private fun IrStatement.containsUsagesOf(variablesSet: Set<IrVariable>): Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds declrations of the variables to the most narrow possible block or body.
|
||||
* Adds declarations of the variables to the most narrow possible block or body.
|
||||
* It adds them before the first usage within the block and inlines initialization of them when possible.
|
||||
*/
|
||||
fun IrBody.makeBodyWithAddedVariables(
|
||||
|
||||
@@ -33,7 +33,7 @@ sealed interface MfvcNode {
|
||||
scope: IrBlockBuilder,
|
||||
typeArguments: TypeArguments,
|
||||
receiver: IrExpression?,
|
||||
isPrivateAccess: Boolean,
|
||||
accessType: AccessType,
|
||||
saveVariable: (IrVariable) -> Unit,
|
||||
): ReceiverBasedMfvcNodeInstance
|
||||
}
|
||||
@@ -41,10 +41,10 @@ sealed interface MfvcNode {
|
||||
fun MfvcNode.createInstanceFromBox(
|
||||
scope: IrBlockBuilder,
|
||||
receiver: IrExpression,
|
||||
isPrivateAccess: Boolean,
|
||||
accessType: AccessType,
|
||||
saveVariable: (IrVariable) -> Unit
|
||||
) =
|
||||
createInstanceFromBox(scope, makeTypeArgumentsFromType(receiver.type as IrSimpleType), receiver, isPrivateAccess, saveVariable)
|
||||
createInstanceFromBox(scope, makeTypeArgumentsFromType(receiver.type as IrSimpleType), receiver, accessType, saveVariable)
|
||||
|
||||
fun MfvcNode.createInstanceFromValueDeclarationsAndBoxType(
|
||||
scope: IrBuilderWithScope, type: IrSimpleType, name: Name, saveVariable: (IrVariable) -> Unit,
|
||||
@@ -314,10 +314,10 @@ class LeafMfvcNode(
|
||||
scope: IrBlockBuilder,
|
||||
typeArguments: TypeArguments,
|
||||
receiver: IrExpression?,
|
||||
isPrivateAccess: Boolean,
|
||||
accessType: AccessType,
|
||||
saveVariable: (IrVariable) -> Unit,
|
||||
) = ReceiverBasedMfvcNodeInstance(
|
||||
scope, this, typeArguments, receiver, field?.let(::listOf), unboxMethod, isPrivateAccess, saveVariable
|
||||
scope, this, typeArguments, receiver, field?.let(::listOf), unboxMethod, accessType, saveVariable
|
||||
)
|
||||
|
||||
override fun toString(): String = "$fullFieldName: ${type.render()}"
|
||||
@@ -364,10 +364,10 @@ class IntermediateMfvcNode(
|
||||
scope: IrBlockBuilder,
|
||||
typeArguments: TypeArguments,
|
||||
receiver: IrExpression?,
|
||||
isPrivateAccess: Boolean,
|
||||
accessType: AccessType,
|
||||
saveVariable: (IrVariable) -> Unit,
|
||||
) = ReceiverBasedMfvcNodeInstance(
|
||||
scope, this, typeArguments, receiver, fields, unboxMethod, isPrivateAccess, saveVariable
|
||||
scope, this, typeArguments, receiver, fields, unboxMethod, accessType, saveVariable
|
||||
)
|
||||
|
||||
override fun toString(): String =
|
||||
@@ -460,9 +460,9 @@ class RootMfvcNode internal constructor(
|
||||
scope: IrBlockBuilder,
|
||||
typeArguments: TypeArguments,
|
||||
receiver: IrExpression?,
|
||||
isPrivateAccess: Boolean,
|
||||
accessType: AccessType,
|
||||
saveVariable: (IrVariable) -> Unit,
|
||||
) = ReceiverBasedMfvcNodeInstance(scope, this, typeArguments, receiver, fields, null, isPrivateAccess, saveVariable)
|
||||
) = ReceiverBasedMfvcNodeInstance(scope, this, typeArguments, receiver, fields, null, accessType, saveVariable)
|
||||
|
||||
override fun toString(): String =
|
||||
"${type.render()}\n${subnodes.joinToString("\n").prependIndent(" ")}"
|
||||
|
||||
@@ -471,16 +471,17 @@ private fun getOverriddenNode(replacements: MemoizedMultiFieldValueClassReplacem
|
||||
.firstOrNull { !it.owner.isFakeOverride }
|
||||
?.let { replacements.getMfvcPropertyNode(it.owner.correspondingPropertySymbol!!.owner) }
|
||||
|
||||
fun hasAccessToPrivateMembersOf(currentElement: IrElement?, parent: IrClass): Boolean {
|
||||
val declaration = currentElement as? IrDeclaration ?: return false
|
||||
fun getOptimizedPublicAccess(currentElement: IrElement?, parent: IrClass): AccessType {
|
||||
val declaration = currentElement as? IrDeclaration ?: return AccessType.AlwaysPublic
|
||||
for (cur in declaration.parents.filterIsInstance<IrClass>()) {
|
||||
return when {
|
||||
cur == parent -> true
|
||||
cur == parent -> AccessType.PrivateWhenNoBox
|
||||
cur.isInner -> continue
|
||||
else -> false
|
||||
cur.isCompanion -> continue
|
||||
else -> AccessType.AlwaysPublic
|
||||
}
|
||||
}
|
||||
return false
|
||||
return AccessType.AlwaysPublic
|
||||
}
|
||||
|
||||
private fun IrProperty.getterIfDeclared(parent: IrDeclarationContainer): IrSimpleFunction? = getter?.takeIf { it in parent.declarations }
|
||||
|
||||
@@ -142,6 +142,8 @@ fun IrExpression?.isRepeatableSetter(): Boolean = when (this) {
|
||||
|
||||
fun IrExpression?.isRepeatableAccessor(): Boolean = isRepeatableGetter() || isRepeatableSetter()
|
||||
|
||||
enum class AccessType { AlwaysPublic, PrivateWhenNoBox, AlwaysPrivate }
|
||||
|
||||
class ReceiverBasedMfvcNodeInstance(
|
||||
override val scope: IrBlockBuilder,
|
||||
override val node: MfvcNode,
|
||||
@@ -149,7 +151,7 @@ class ReceiverBasedMfvcNodeInstance(
|
||||
receiver: IrExpression?,
|
||||
val fields: List<IrField>?,
|
||||
val unboxMethod: IrSimpleFunction?,
|
||||
val isPrivateAccess: Boolean,
|
||||
val accessType: AccessType,
|
||||
private val saveVariable: (IrVariable) -> Unit,
|
||||
) : MfvcNodeInstance {
|
||||
override val type: IrSimpleType = makeTypeFromMfvcNodeAndTypeArguments(node, typeArguments)
|
||||
@@ -169,7 +171,9 @@ class ReceiverBasedMfvcNodeInstance(
|
||||
override fun makeFlattenedGetterExpressions(): List<IrExpression> = when (node) {
|
||||
is LeafMfvcNode -> listOf(makeGetterExpression())
|
||||
is MfvcNodeWithSubnodes -> when {
|
||||
node is IntermediateMfvcNode && isPrivateAccess && fields != null -> fields.map { scope.irGetField(makeReceiverCopy(), it) }
|
||||
node is IntermediateMfvcNode && canUsePrivateAccessFor(node) && fields != null ->
|
||||
fields.map { scope.irGetField(makeReceiverCopy(), it) }
|
||||
|
||||
node is IntermediateMfvcNode && !node.hasPureUnboxMethod -> {
|
||||
val value = makeGetterExpression()
|
||||
val asVariable = scope.savableStandaloneVariableWithSetter(
|
||||
@@ -180,7 +184,7 @@ class ReceiverBasedMfvcNodeInstance(
|
||||
)
|
||||
val root = node.rootNode
|
||||
val variableInstance =
|
||||
root.createInstanceFromBox(scope, typeArguments, scope.irGet(asVariable), isPrivateAccess = false, saveVariable)
|
||||
root.createInstanceFromBox(scope, typeArguments, scope.irGet(asVariable), accessType, saveVariable)
|
||||
variableInstance.makeFlattenedGetterExpressions()
|
||||
}
|
||||
|
||||
@@ -190,8 +194,8 @@ class ReceiverBasedMfvcNodeInstance(
|
||||
|
||||
override fun makeGetterExpression(): IrExpression = with(scope) {
|
||||
when {
|
||||
node is LeafMfvcNode && isPrivateAccess && fields != null -> irGetField(makeReceiverCopy(), fields.single())
|
||||
node is IntermediateMfvcNode && isPrivateAccess && fields != null -> node.makeBoxedExpression(
|
||||
node is LeafMfvcNode && canUsePrivateAccessFor(node) && fields != null -> irGetField(makeReceiverCopy(), fields.single())
|
||||
node is IntermediateMfvcNode && accessType == AccessType.AlwaysPrivate && fields != null -> node.makeBoxedExpression(
|
||||
this, typeArguments, fields.map { irGetField(makeReceiverCopy(), it) }
|
||||
)
|
||||
unboxMethod != null -> irCall(unboxMethod).apply {
|
||||
@@ -210,9 +214,12 @@ class ReceiverBasedMfvcNodeInstance(
|
||||
}
|
||||
}
|
||||
|
||||
private fun canUsePrivateAccessFor(node: NameableMfvcNode) =
|
||||
node.hasPureUnboxMethod && accessType == AccessType.PrivateWhenNoBox || accessType == AccessType.AlwaysPrivate
|
||||
|
||||
override fun get(name: Name): ReceiverBasedMfvcNodeInstance? {
|
||||
val (newNode, _) = node.getSubnodeAndIndices(name) ?: return null
|
||||
return newNode.createInstanceFromBox(scope, typeArguments, makeReceiverCopy(), isPrivateAccess, saveVariable)
|
||||
return newNode.createInstanceFromBox(scope, typeArguments, makeReceiverCopy(), accessType, saveVariable)
|
||||
}
|
||||
|
||||
override fun makeStatements(values: List<IrExpression>): List<IrStatement> {
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
@kotlin.Metadata
|
||||
public final class A {
|
||||
// source: 'MfvcFieldInitializationOrder.kt'
|
||||
// source: 'mfvcFieldInitializationOrder.kt'
|
||||
private field x-0: double
|
||||
private field x-1: double
|
||||
public method <init>(p0: double, p1: double): void
|
||||
@@ -12,7 +12,7 @@ public final class A {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class B {
|
||||
// source: 'MfvcFieldInitializationOrder.kt'
|
||||
// source: 'mfvcFieldInitializationOrder.kt'
|
||||
private field a-0: double
|
||||
private field a-1: double
|
||||
private final field b-0: double
|
||||
@@ -35,7 +35,7 @@ public final class B {
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class DPoint {
|
||||
// source: 'MfvcFieldInitializationOrder.kt'
|
||||
// source: 'mfvcFieldInitializationOrder.kt'
|
||||
private final field field-0: double
|
||||
private final field field-1: double
|
||||
private synthetic method <init>(p0: double, p1: double): void
|
||||
@@ -56,6 +56,6 @@ public final class DPoint {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class MfvcFieldInitializationOrderKt {
|
||||
// source: 'MfvcFieldInitializationOrder.kt'
|
||||
// source: 'mfvcFieldInitializationOrder.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
}
|
||||
+11
-2
@@ -22,6 +22,14 @@ value class D(val x: C) {
|
||||
}
|
||||
}
|
||||
|
||||
class Regular(private val x: D) {
|
||||
fun privateAccess() {
|
||||
listOf(x.x.x)
|
||||
listOf(x.x)
|
||||
listOf(x)
|
||||
}
|
||||
}
|
||||
|
||||
fun functionWithoutBoxes(x: D, y: D) {
|
||||
var z: D = x
|
||||
val t: D = D(C(1, B(3U), "4"))
|
||||
@@ -61,7 +69,8 @@ fun functionWithoutBoxes(x: D, y: D) {
|
||||
// 1 private final Ljava/lang/String; field-2\n
|
||||
// 1 INVOKESPECIAL C.<init> \(IILjava/lang/String;\)V
|
||||
// 1 INVOKESPECIAL D.<init> \(IILjava/lang/String;\)V
|
||||
// 1 INVOKESTATIC D.box-impl \(IILjava/lang/String;\)LD;
|
||||
// 2 INVOKESTATIC C.box-impl \(IILjava/lang/String;\)LC;
|
||||
// 2 INVOKESTATIC D.box-impl \(IILjava/lang/String;\)LD;
|
||||
// 3 INVOKESTATIC C.box-impl \(IILjava/lang/String;\)LC;
|
||||
// 1 public final static functionWithoutBoxes-GPBa7dw\(IILjava/lang/String;IILjava/lang/String;\)V
|
||||
// 0 functionWithoutBoxes.*(\n {3}.*)*(\n {4}(NEW [ABCD]|.*(box|[ABCD]\.<init>|LA;|LB;|LC;|LD;)))
|
||||
// 1 privateAccess.*(\n .+)*(\n GETFIELD Regular\.x-0-0 : I)(\n .+)*(\n INVOKEVIRTUAL Regular\.getX-0 \(\)LC;)(\n .+)*(\n INVOKESPECIAL Regular\.getX \(\)LD;)
|
||||
+2
-2
@@ -50202,9 +50202,9 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("MfvcFieldInitializationOrder.kt")
|
||||
@TestMetadata("mfvcFieldInitializationOrder.kt")
|
||||
public void testMfvcFieldInitializationOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/MfvcFieldInitializationOrder.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
runTest("compiler/testData/codegen/box/valueClasses/mfvcFieldInitializationOrder.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+6
-6
@@ -5796,15 +5796,15 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("MFVCDeclaration.kt")
|
||||
public void testMFVCDeclaration() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/MFVCDeclaration.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("mfvcDeclaration.kt")
|
||||
public void testMfvcDeclaration() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/mfvcDeclaration.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("MFVCReassignments.kt")
|
||||
public void testMFVCReassignments() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/MFVCReassignments.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
@TestMetadata("mfvcReassignments.kt")
|
||||
public void testMfvcReassignments() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/valueClasses/mfvcReassignments.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user