From ae6f84de31833dc9090d4f8e5614f0677ca705c6 Mon Sep 17 00:00:00 2001 From: Ivan Volkov Date: Fri, 9 Dec 2022 13:10:50 +0300 Subject: [PATCH] Use containingClass along with signature to match psi methods and KFunctions --- .../plugin/api/MethodDescriptionUtil.kt | 25 +++ .../framework/plugin/api/SignatureUtil.kt | 18 -- .../framework/process/EngineProcessMain.kt | 14 +- .../generated/EngineProcessModel.Generated.kt | 179 +++++++++--------- .../intellij/plugin/process/EngineProcess.kt | 12 +- ...esHelper.kt => MethodDescriptionHelper.kt} | 10 +- .../org/utbot/rd/models/EngineProcessModel.kt | 5 +- 7 files changed, 141 insertions(+), 122 deletions(-) create mode 100644 utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/MethodDescriptionUtil.kt delete mode 100644 utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/SignatureUtil.kt rename utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/{SignaturesHelper.kt => MethodDescriptionHelper.kt} (57%) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/MethodDescriptionUtil.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/MethodDescriptionUtil.kt new file mode 100644 index 0000000000..33d5b1142c --- /dev/null +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/MethodDescriptionUtil.kt @@ -0,0 +1,25 @@ +package org.utbot.framework.plugin.api + +import org.utbot.framework.plugin.api.util.declaringClazz +import kotlin.reflect.KFunction +import kotlin.reflect.KParameter +import kotlin.reflect.jvm.javaType + +// Note that rules for obtaining signature here should correlate with PsiMethod.signature() +fun KFunction<*>.methodDescription() = + MethodDescription( + this.name, + this.declaringClazz.name, + this.parameters.filter { it.kind != KParameter.Kind.INSTANCE }.map { it.type.javaType.typeName } + ) + +// Similar to MethodId, but significantly simplified -- used only to match methods from psi and their reflections +data class MethodDescription(val name: String, val containingClass: String?, val parameterTypes: List) { + + fun normalized() = this.copy( + containingClass = containingClass?.replace("$", "."), // normalize names of nested classes + parameterTypes = parameterTypes.map { + it?.replace("$", ".") + } + ) +} \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/SignatureUtil.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/SignatureUtil.kt deleted file mode 100644 index 437da7add4..0000000000 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/plugin/api/SignatureUtil.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.utbot.framework.plugin.api - -import kotlin.reflect.KFunction -import kotlin.reflect.KParameter -import kotlin.reflect.jvm.javaType - -// Note that rules for obtaining signature here should correlate with PsiMethod.signature() -fun KFunction<*>.signature() = - Signature(this.name, this.parameters.filter { it.kind != KParameter.Kind.INSTANCE }.map { it.type.javaType.typeName }) - -data class Signature(val name: String, val parameterTypes: List) { - - fun normalized() = this.copy( - parameterTypes = parameterTypes.map { - it?.replace("$", ".") // normalize names of nested classes - } - ) -} \ No newline at end of file diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt index fb252c3915..74b66be154 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/EngineProcessMain.kt @@ -21,7 +21,7 @@ import org.utbot.framework.codegen.domain.RuntimeExceptionTestsBehaviour import org.utbot.framework.codegen.domain.testFrameworkByName import org.utbot.framework.codegen.reports.TestsGenerationReport import org.utbot.framework.plugin.api.* -import org.utbot.framework.plugin.api.Signature +import org.utbot.framework.plugin.api.MethodDescription import org.utbot.framework.plugin.api.util.UtContext import org.utbot.framework.plugin.api.util.executableId import org.utbot.framework.plugin.api.util.id @@ -159,19 +159,21 @@ private fun EngineProcessModel.setup(kryoHelper: KryoHelper, watchdog: IdleWatch } watchdog.wrapActiveCall(findMethodsInClassMatchingSelected) { params -> val classId = kryoHelper.readObject(params.classId) - val selectedSignatures = params.signatures.map { Signature(it.name, it.parametersTypes) } + val selectedMethodDescriptions = + params.methodDescriptions.map { MethodDescription(it.name, it.containingClass, it.parametersTypes) } FindMethodsInClassMatchingSelectedResult(kryoHelper.writeObject(classId.jClass.allNestedClasses.flatMap { clazz -> - clazz.id.allMethods.mapNotNull { it.method.kotlinFunction }.sortedWith(compareBy { selectedSignatures.indexOf(it.signature()) }) - .filter { it.signature().normalized() in selectedSignatures } + clazz.id.allMethods.mapNotNull { it.method.kotlinFunction } + .sortedWith(compareBy { selectedMethodDescriptions.indexOf(it.methodDescription()) }) + .filter { it.methodDescription().normalized() in selectedMethodDescriptions } .map { it.executableId } })) } watchdog.wrapActiveCall(findMethodParamNames) { params -> val classId = kryoHelper.readObject(params.classId) - val bySignature = kryoHelper.readObject>>(params.bySignature) + val byMethodDescription = kryoHelper.readObject>>(params.bySignature) FindMethodParamNamesResult(kryoHelper.writeObject( classId.jClass.allNestedClasses.flatMap { clazz -> clazz.id.allMethods.mapNotNull { it.method.kotlinFunction } } - .mapNotNull { method -> bySignature[method.signature()]?.let { params -> method.executableId to params } } + .mapNotNull { method -> byMethodDescription[method.methodDescription()]?.let { params -> method.executableId to params } } .toMap() )) } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt index 5861c06060..dc49b4d12e 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/process/generated/EngineProcessModel.Generated.kt @@ -42,7 +42,7 @@ class EngineProcessModel private constructor( serializers.register(RenderParams) serializers.register(RenderResult) serializers.register(SetupContextParams) - serializers.register(Signature) + serializers.register(MethodDescription) serializers.register(FindMethodsInClassMatchingSelectedArguments) serializers.register(FindMethodsInClassMatchingSelectedResult) serializers.register(FindMethodParamNamesArguments) @@ -71,9 +71,9 @@ class EngineProcessModel private constructor( bind(lifetime, protocol, "EngineProcessModel") } } - - - const val serializationHash = -621732450296355904L + + + const val serializationHash = -6219345436129699239L } override val serializersOwner: ISerializersOwner get() = EngineProcessModel @@ -180,7 +180,7 @@ val IProtocol.engineProcessModel get() = getOrCreateExtension(EngineProcessModel /** - * #### Generated from [EngineProcessModel.kt:99] + * #### Generated from [EngineProcessModel.kt:100] */ data class FindMethodParamNamesArguments ( val classId: ByteArray, @@ -243,7 +243,7 @@ data class FindMethodParamNamesArguments ( /** - * #### Generated from [EngineProcessModel.kt:103] + * #### Generated from [EngineProcessModel.kt:104] */ data class FindMethodParamNamesResult ( val paramNames: ByteArray @@ -300,11 +300,11 @@ data class FindMethodParamNamesResult ( /** - * #### Generated from [EngineProcessModel.kt:92] + * #### Generated from [EngineProcessModel.kt:93] */ data class FindMethodsInClassMatchingSelectedArguments ( val classId: ByteArray, - val signatures: List + val methodDescriptions: List ) : IPrintable { //companion @@ -312,15 +312,15 @@ data class FindMethodsInClassMatchingSelectedArguments ( override val _type: KClass = FindMethodsInClassMatchingSelectedArguments::class @Suppress("UNCHECKED_CAST") - override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): FindMethodsInClassMatchingSelectedArguments { + override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): FindMethodsInClassMatchingSelectedArguments { val classId = buffer.readByteArray() - val signatures = buffer.readList { Signature.read(ctx, buffer) } - return FindMethodsInClassMatchingSelectedArguments(classId, signatures) + val methodDescriptions = buffer.readList { MethodDescription.read(ctx, buffer) } + return FindMethodsInClassMatchingSelectedArguments(classId, methodDescriptions) } override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: FindMethodsInClassMatchingSelectedArguments) { buffer.writeByteArray(value.classId) - buffer.writeList(value.signatures) { v -> Signature.write(ctx, buffer, v) } + buffer.writeList(value.methodDescriptions) { v -> MethodDescription.write(ctx, buffer, v) } } @@ -335,17 +335,17 @@ data class FindMethodsInClassMatchingSelectedArguments ( if (other == null || other::class != this::class) return false other as FindMethodsInClassMatchingSelectedArguments - + if (!(classId contentEquals other.classId)) return false - if (signatures != other.signatures) return false + if (methodDescriptions != other.methodDescriptions) return false return true } //hash code trait override fun hashCode(): Int { var __r = 0 - __r = __r*31 + classId.contentHashCode() - __r = __r*31 + signatures.hashCode() + __r = __r * 31 + classId.contentHashCode() + __r = __r * 31 + methodDescriptions.hashCode() return __r } //pretty print @@ -353,7 +353,7 @@ data class FindMethodsInClassMatchingSelectedArguments ( printer.println("FindMethodsInClassMatchingSelectedArguments (") printer.indent { print("classId = "); classId.print(printer); println() - print("signatures = "); signatures.print(printer); println() + print("methodDescriptions = "); methodDescriptions.print(printer); println() } printer.print(")") } @@ -363,7 +363,7 @@ data class FindMethodsInClassMatchingSelectedArguments ( /** - * #### Generated from [EngineProcessModel.kt:96] + * #### Generated from [EngineProcessModel.kt:97] */ data class FindMethodsInClassMatchingSelectedResult ( val executableIds: ByteArray @@ -606,7 +606,7 @@ data class GenerateResult ( /** - * #### Generated from [EngineProcessModel.kt:111] + * #### Generated from [EngineProcessModel.kt:112] */ data class GenerateTestReportArgs ( val eventLogMessage: String?, @@ -699,7 +699,7 @@ data class GenerateTestReportArgs ( /** - * #### Generated from [EngineProcessModel.kt:120] + * #### Generated from [EngineProcessModel.kt:121] */ data class GenerateTestReportResult ( val notifyMessage: String, @@ -830,10 +830,82 @@ data class JdkInfo ( } +/** + * #### Generated from [EngineProcessModel.kt:88] + */ +data class MethodDescription( + val name: String, + val containingClass: String?, + val parametersTypes: List +) : IPrintable { + //companion + + companion object : IMarshaller { + override val _type: KClass = MethodDescription::class + + @Suppress("UNCHECKED_CAST") + override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): MethodDescription { + val name = buffer.readString() + val containingClass = buffer.readNullable { buffer.readString() } + val parametersTypes = buffer.readList { buffer.readNullable { buffer.readString() } } + return MethodDescription(name, containingClass, parametersTypes) + } + + override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: MethodDescription) { + buffer.writeString(value.name) + buffer.writeNullable(value.containingClass) { buffer.writeString(it) } + buffer.writeList(value.parametersTypes) { v -> buffer.writeNullable(v) { buffer.writeString(it) } } + } + + + } + + //fields + //methods + //initializer + //secondary constructor + //equals trait + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || other::class != this::class) return false + + other as MethodDescription + + if (name != other.name) return false + if (containingClass != other.containingClass) return false + if (parametersTypes != other.parametersTypes) return false + + return true + } + + //hash code trait + override fun hashCode(): Int { + var __r = 0 + __r = __r * 31 + name.hashCode() + __r = __r * 31 + if (containingClass != null) containingClass.hashCode() else 0 + __r = __r * 31 + parametersTypes.hashCode() + return __r + } + + //pretty print + override fun print(printer: PrettyPrinter) { + printer.println("MethodDescription (") + printer.indent { + print("name = "); name.print(printer); println() + print("containingClass = "); containingClass.print(printer); println() + print("parametersTypes = "); parametersTypes.print(printer); println() + } + printer.print(")") + } + //deepClone + //contexts +} + + /** * #### Generated from [EngineProcessModel.kt:64] */ -data class RenderParams ( +data class RenderParams( val testSetsId: Long, val classUnderTest: ByteArray, val paramNames: ByteArray, @@ -1091,69 +1163,6 @@ data class SetupContextParams ( } -/** - * #### Generated from [EngineProcessModel.kt:88] - */ -data class Signature ( - val name: String, - val parametersTypes: List -) : IPrintable { - //companion - - companion object : IMarshaller { - override val _type: KClass = Signature::class - - @Suppress("UNCHECKED_CAST") - override fun read(ctx: SerializationCtx, buffer: AbstractBuffer): Signature { - val name = buffer.readString() - val parametersTypes = buffer.readList { buffer.readNullable { buffer.readString() } } - return Signature(name, parametersTypes) - } - - override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: Signature) { - buffer.writeString(value.name) - buffer.writeList(value.parametersTypes) { v -> buffer.writeNullable(v) { buffer.writeString(it) } } - } - - - } - //fields - //methods - //initializer - //secondary constructor - //equals trait - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || other::class != this::class) return false - - other as Signature - - if (name != other.name) return false - if (parametersTypes != other.parametersTypes) return false - - return true - } - //hash code trait - override fun hashCode(): Int { - var __r = 0 - __r = __r*31 + name.hashCode() - __r = __r*31 + parametersTypes.hashCode() - return __r - } - //pretty print - override fun print(printer: PrettyPrinter) { - printer.println("Signature (") - printer.indent { - print("name = "); name.print(printer); println() - print("parametersTypes = "); parametersTypes.print(printer); println() - } - printer.print(")") - } - //deepClone - //contexts -} - - /** * #### Generated from [EngineProcessModel.kt:36] */ @@ -1230,7 +1239,7 @@ data class TestGeneratorParams ( /** - * #### Generated from [EngineProcessModel.kt:106] + * #### Generated from [EngineProcessModel.kt:107] */ data class WriteSarifReportArguments ( val testSetsId: Long, diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt index c27a022bfc..0fa7d119b8 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/process/EngineProcess.kt @@ -23,7 +23,7 @@ import org.utbot.framework.plugin.services.JdkInfoService import org.utbot.framework.plugin.services.WorkingDirService import org.utbot.framework.process.OpenModulesContainer import org.utbot.framework.process.generated.* -import org.utbot.framework.process.generated.Signature +import org.utbot.framework.process.generated.MethodDescription import org.utbot.framework.util.Conflict import org.utbot.framework.util.ConflictTriggers import org.utbot.instrumentation.util.KryoHelper @@ -32,7 +32,7 @@ import org.utbot.intellij.plugin.models.GenerateTestsModel import org.utbot.intellij.plugin.ui.TestReportUrlOpeningListener import org.utbot.intellij.plugin.util.assertIsNonDispatchThread import org.utbot.intellij.plugin.util.assertIsReadAccessAllowed -import org.utbot.intellij.plugin.util.signature +import org.utbot.intellij.plugin.util.methodDescription import org.utbot.rd.* import org.utbot.rd.exceptions.InstantProcessDeathException import org.utbot.rd.generated.SettingForResult @@ -205,10 +205,10 @@ class EngineProcess private constructor(val project: Project, rdProcess: Process assertIsNonDispatchThread() assertIsReadAccessAllowed() - val srcSignatures = srcMethods.map { it.signature() } - val rdSignatures = srcSignatures.map { Signature(it.name, it.parameterTypes) } + val srcDescriptions = srcMethods.map { it.methodDescription() } + val rdDescriptions = srcDescriptions.map { MethodDescription(it.name, it.containingClass, it.parameterTypes) } val binaryClassId = kryoHelper.writeObject(clazzId) - val arguments = FindMethodsInClassMatchingSelectedArguments(binaryClassId, rdSignatures) + val arguments = FindMethodsInClassMatchingSelectedArguments(binaryClassId, rdDescriptions) val result = engineModel.findMethodsInClassMatchingSelected.startBlocking(arguments) return kryoHelper.readObject(result.executableIds) @@ -218,7 +218,7 @@ class EngineProcess private constructor(val project: Project, rdProcess: Process assertIsNonDispatchThread() assertIsReadAccessAllowed() - val bySignature = methods.associate { it.signature() to it.paramNames() } + val bySignature = methods.associate { it.methodDescription() to it.paramNames() } val arguments = FindMethodParamNamesArguments( kryoHelper.writeObject(classId), kryoHelper.writeObject(bySignature) diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/SignaturesHelper.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/MethodDescriptionHelper.kt similarity index 57% rename from utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/SignaturesHelper.kt rename to utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/MethodDescriptionHelper.kt index f3e9d07f39..9110efe995 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/SignaturesHelper.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/util/MethodDescriptionHelper.kt @@ -2,14 +2,14 @@ package org.utbot.intellij.plugin.util import com.intellij.psi.PsiMethod import com.intellij.refactoring.util.classMembers.MemberInfo -import org.utbot.framework.plugin.api.Signature +import org.utbot.framework.plugin.api.MethodDescription -fun MemberInfo.signature(): Signature = - (this.member as PsiMethod).signature() +fun MemberInfo.methodDescription(): MethodDescription = + (this.member as PsiMethod).methodDescription() // Note that rules for obtaining signature here should correlate with KFunction<*>.signature() -private fun PsiMethod.signature() = - Signature(this.name, this.parameterList.parameters.map { +private fun PsiMethod.methodDescription() = + MethodDescription(this.name, this.containingClass?.qualifiedName, this.parameterList.parameters.map { it.type.canonicalText .replace("...", "[]") //for PsiEllipsisType .replace(",", ", ") // to fix cases like Pair -> Pair diff --git a/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt b/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt index 34ae7df186..1c89ef0312 100644 --- a/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt +++ b/utbot-rd/src/main/rdgen/org/utbot/rd/models/EngineProcessModel.kt @@ -86,13 +86,14 @@ object EngineProcessModel : Ext(EngineProcessRoot) { val setupContextParams = structdef { field("classpathForUrlsClassloader", immutableList(PredefinedType.string)) } - val signature = structdef { + val methodDescription = structdef { field("name", PredefinedType.string) + field("containingClass", PredefinedType.string.nullable) field("parametersTypes", immutableList(PredefinedType.string.nullable)) } val findMethodsInClassMatchingSelectedArguments = structdef { field("classId", array(PredefinedType.byte)) - field("signatures", immutableList(signature)) + field("methodDescriptions", immutableList(methodDescription)) } val findMethodsInClassMatchingSelectedResult = structdef { field("executableIds", array(PredefinedType.byte))