From 47f0eef4d8b4ce9a13baf4d61ff2fd9366c5dabe Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Thu, 20 Oct 2022 15:38:15 +0300 Subject: [PATCH 1/4] Remove name field from BuiltinClassId --- .../org/utbot/framework/plugin/api/Api.kt | 3 +-- .../org/utbot/framework/codegen/Domain.kt | 27 ------------------- .../constructor/builtin/MockitoBuiltins.kt | 5 ---- .../constructor/builtin/UtilMethodBuiltins.kt | 2 -- .../model/constructor/context/CgContext.kt | 2 -- .../constructor/tree/CgMethodConstructor.kt | 1 - .../constructor/util/ConstructorUtils.kt | 2 -- .../framework/codegen/model/tree/CgElement.kt | 1 - 8 files changed, 1 insertion(+), 42 deletions(-) diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt index b50e0ff4fd..e38acb6bec 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt @@ -875,7 +875,6 @@ open class ClassId @JvmOverloads constructor( * (it is important because name for nested classes contains $ as a delimiter between nested and outer classes) */ class BuiltinClassId( - name: String, elementClassId: ClassId? = null, override val canonicalName: String, override val simpleName: String, @@ -906,7 +905,7 @@ class BuiltinClassId( -1, 0 -> "" else -> canonicalName.substring(0, index) }, -) : ClassId(name = name, isNullable = isNullable, elementClassId = elementClassId) { +) : ClassId(name = "", isNullable = isNullable, elementClassId = elementClassId) { init { BUILTIN_CLASSES_BY_NAMES[name] = this } diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt index b57d9e0cd9..88d25e6746 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt @@ -128,13 +128,11 @@ object NoStaticMocking : StaticsMocking( object MockitoStaticMocking : StaticsMocking(id = "Mockito static mocking", displayName = "Mockito static mocking") { val mockedStaticClassId = BuiltinClassId( - name = "org.mockito.MockedStatic", canonicalName = "org.mockito.MockedStatic", simpleName = "MockedStatic" ) val mockedConstructionClassId = BuiltinClassId( - name = "org.mockito.MockedConstruction", canonicalName = "org.mockito.MockedConstruction", simpleName = "MockedConstruction" ) @@ -264,13 +262,11 @@ object TestNg : TestFramework(id = "TestNG",displayName = "TestNG") { internal const val testXmlName: String = "testng.xml" override val assertionsClass: ClassId = BuiltinClassId( - name = TEST_NG_ASSERTIONS, canonicalName = TEST_NG_ASSERTIONS, simpleName = "Assert" ) override val arraysAssertionsClass: ClassId = BuiltinClassId( - name = TEST_NG_ARRAYS_ASSERTIONS, canonicalName = TEST_NG_ARRAYS_ASSERTIONS, simpleName = "ArrayAsserts" ) @@ -278,7 +274,6 @@ object TestNg : TestFramework(id = "TestNG",displayName = "TestNG") { override val assertBooleanArrayEquals by lazy { assertionId("assertEquals", booleanArrayClassId, booleanArrayClassId) } val throwingRunnableClassId = BuiltinClassId( - name = "${assertionsClass.name}\$ThrowingRunnable", canonicalName = "${assertionsClass.canonicalName}.ThrowingRunnable", simpleName = "ThrowingRunnable" ) @@ -295,19 +290,16 @@ object TestNg : TestFramework(id = "TestNG",displayName = "TestNG") { ) override val testAnnotationId: ClassId = BuiltinClassId( - name = "$mainPackage.annotations.Test", canonicalName = "$mainPackage.annotations.Test", simpleName = "Test" ) override val parameterizedTestAnnotationId: ClassId = BuiltinClassId( - name = "$mainPackage.annotations.Test", canonicalName = "$mainPackage.annotations.Test", simpleName = "Test" ) override val methodSourceAnnotationId: ClassId = BuiltinClassId( - name = "$mainPackage.annotations.DataProvider", canonicalName = "$mainPackage.annotations.DataProvider", simpleName = "DataProvider" ) @@ -318,7 +310,6 @@ object TestNg : TestFramework(id = "TestNG",displayName = "TestNG") { get() { val outerArrayId = Array?>::class.id val innerArrayId = BuiltinClassId( - name = objectArrayClassId.name, simpleName = objectArrayClassId.simpleName, canonicalName = objectArrayClassId.canonicalName, packageName = objectArrayClassId.packageName, @@ -327,7 +318,6 @@ object TestNg : TestFramework(id = "TestNG",displayName = "TestNG") { ) return BuiltinClassId( - name = outerArrayId.name, simpleName = outerArrayId.simpleName, canonicalName = outerArrayId.canonicalName, packageName = outerArrayId.packageName, @@ -398,7 +388,6 @@ object Junit4 : TestFramework(id = "JUnit4",displayName = "JUnit 4") { get() = parametrizedTestsNotSupportedError override val testAnnotationId = BuiltinClassId( - name = "$JUNIT4_PACKAGE.Test", canonicalName = "$JUNIT4_PACKAGE.Test", simpleName = "Test" ) @@ -407,13 +396,11 @@ object Junit4 : TestFramework(id = "JUnit4",displayName = "JUnit 4") { override val methodSourceAnnotationId = voidClassId val runWithAnnotationClassId = BuiltinClassId( - name = "$JUNIT4_PACKAGE.runner.RunWith", canonicalName = "$JUNIT4_PACKAGE.runner.RunWith", simpleName = "RunWith" ) override val assertionsClass = BuiltinClassId( - name = JUNIT4_ASSERTIONS, canonicalName = JUNIT4_ASSERTIONS, simpleName = "Assert" ) @@ -421,14 +408,12 @@ object Junit4 : TestFramework(id = "JUnit4",displayName = "JUnit 4") { val ignoreAnnotationClassId = with("$JUNIT4_PACKAGE.Ignore") { BuiltinClassId( - name = this, canonicalName = this, simpleName = "Ignore" ) } val enclosedClassId = BuiltinClassId( - name = "org.junit.experimental.runners.Enclosed", canonicalName = "org.junit.experimental.runners.Enclosed", simpleName = "Enclosed" ) @@ -463,25 +448,21 @@ object Junit5 : TestFramework(id = "JUnit5", displayName = "JUnit 5") { override val methodSourceAnnotationFqn: String = "$JUNIT5_PARAMETERIZED_PACKAGE.provider.MethodSource" val executableClassId = BuiltinClassId( - name = "$JUNIT5_PACKAGE.function.Executable", canonicalName = "$JUNIT5_PACKAGE.function.Executable", simpleName = "Executable" ) val timeoutClassId = BuiltinClassId( - name = "$JUNIT5_PACKAGE.Timeout", canonicalName = "$JUNIT5_PACKAGE.Timeout", simpleName = "Timeout" ) val timeunitClassId = BuiltinClassId( - name = "TimeUnit", canonicalName = "java.util.concurrent.TimeUnit", simpleName = "TimeUnit" ) val durationClassId = BuiltinClassId( - name = "Duration", canonicalName = "java.time.Duration", simpleName = "Duration" ) @@ -494,31 +475,26 @@ object Junit5 : TestFramework(id = "JUnit5", displayName = "JUnit 5") { ) val nestedTestClassAnnotationId = BuiltinClassId( - name = "$JUNIT5_PACKAGE.Nested", canonicalName = "$JUNIT5_PACKAGE.Nested", simpleName = "Nested" ) override val testAnnotationId = BuiltinClassId( - name = "$JUNIT5_PACKAGE.Test", canonicalName = "$JUNIT5_PACKAGE.Test", simpleName = "Test" ) override val parameterizedTestAnnotationId = BuiltinClassId( - name = "$JUNIT5_PARAMETERIZED_PACKAGE.ParameterizedTest", canonicalName = "$JUNIT5_PARAMETERIZED_PACKAGE.ParameterizedTest", simpleName = "ParameterizedTest" ) override val methodSourceAnnotationId: ClassId = BuiltinClassId( - name = "$JUNIT5_PARAMETERIZED_PACKAGE.provider.MethodSource", canonicalName = "$JUNIT5_PARAMETERIZED_PACKAGE.provider.MethodSource", simpleName = "MethodSource" ) override val assertionsClass = BuiltinClassId( - name = JUNIT5_ASSERTIONS, canonicalName = JUNIT5_ASSERTIONS, simpleName = "Assertions" ) @@ -547,14 +523,12 @@ object Junit5 : TestFramework(id = "JUnit5", displayName = "JUnit 5") { ) val displayNameClassId = BuiltinClassId( - name = "$JUNIT5_PACKAGE.DisplayName", canonicalName = "$JUNIT5_PACKAGE.DisplayName", simpleName = "DisplayName" ) val disabledAnnotationClassId = with("$JUNIT5_PACKAGE.Disabled") { BuiltinClassId( - name = this, canonicalName = this, simpleName = "Disabled" ) @@ -566,7 +540,6 @@ object Junit5 : TestFramework(id = "JUnit5", displayName = "JUnit 5") { get() { val arrayListId = java.util.ArrayList::class.id return BuiltinClassId( - name = arrayListId.name, simpleName = arrayListId.simpleName, canonicalName = arrayListId.canonicalName, packageName = arrayListId.packageName, diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt index 1a2805b615..087a33fe87 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt @@ -24,31 +24,26 @@ internal val mockitoBuiltins: Set ) internal val mockitoClassId = BuiltinClassId( - name = "org.mockito.Mockito", canonicalName = "org.mockito.Mockito", simpleName = "Mockito", ) internal val ongoingStubbingClassId = BuiltinClassId( - name = "org.mockito.stubbing.OngoingStubbing", canonicalName = "org.mockito.stubbing.OngoingStubbing", simpleName = "OngoingStubbing", ) internal val answerClassId = BuiltinClassId( - name = "org.mockito.stubbing.Answer", canonicalName = "org.mockito.stubbing.Answer", simpleName = "Answer", ) internal val argumentMatchersClassId = BuiltinClassId( - name = "org.mockito.ArgumentMatchers", canonicalName = "org.mockito.ArgumentMatchers", simpleName = "ArgumentMatchers", ) internal val mockedConstructionContextClassId = BuiltinClassId( - name = "org.mockito.MockedConstruction.Context", canonicalName = "org.mockito.MockedConstruction.Context", // TODO use $ as a delimiter of outer and nested classes? simpleName = "Context", isNested = true diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt index 87ee5c48f5..9ded301468 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt @@ -234,7 +234,6 @@ internal abstract class UtilMethodProvider(val utilClassId: ClassId) { val capturedArgumentClassId: BuiltinClassId get() = BuiltinClassId( - name = "${utilClassId.name}\$CapturedArgument", canonicalName = "${utilClassId.name}.CapturedArgument", simpleName = "CapturedArgument" ) @@ -269,7 +268,6 @@ internal class TestClassUtilMethodProvider(testClassId: ClassId) : UtilMethodPro internal val utUtilsClassId: ClassId get() = BuiltinClassId( - name = "org.utbot.runtime.utils.UtUtils", canonicalName = "org.utbot.runtime.utils.UtUtils", simpleName = "UtUtils", isFinal = true diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt index 308bab95bc..fb1d621e6a 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/context/CgContext.kt @@ -491,7 +491,6 @@ internal data class CgContext( val simpleName = testClassCustomName ?: "${classUnderTest.simpleName}Test" val name = "$packagePrefix$simpleName" BuiltinClassId( - name = name, canonicalName = name, simpleName = simpleName ) @@ -548,7 +547,6 @@ internal data class CgContext( private fun createClassIdForNestedClass(testClassModel: TestClassModel): ClassId { val simpleName = "${testClassModel.classUnderTest.simpleName}Test" return BuiltinClassId( - name = currentTestClass.name + "$" + simpleName, canonicalName = currentTestClass.canonicalName + "." + simpleName, simpleName = simpleName ) diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt index f2844b0309..92aeaf3b66 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/tree/CgMethodConstructor.kt @@ -1493,7 +1493,6 @@ internal class CgMethodConstructor(val context: CgContext) : CgContextOwner by c val expectedException = CgParameterDeclaration( parameter = declareParameter( type = BuiltinClassId( - name = classClassId.name, simpleName = classClassId.simpleName, canonicalName = classClassId.canonicalName, packageName = classClassId.packageName, diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/util/ConstructorUtils.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/util/ConstructorUtils.kt index d25567d86b..c5b937f05d 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/util/ConstructorUtils.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/util/ConstructorUtils.kt @@ -154,7 +154,6 @@ internal val addToListMethodId: MethodId */ internal val argumentsClassId: BuiltinClassId get() = BuiltinClassId( - name = "org.junit.jupiter.params.provider.Arguments", simpleName = "Arguments", canonicalName = "org.junit.jupiter.params.provider.Arguments", packageName = "org.junit.jupiter.params.provider" @@ -314,7 +313,6 @@ fun arrayTypeOf(elementType: ClassId, isNullable: Boolean = false): ClassId { val arrayIdName = "[${elementType.arrayLikeName}" return when (elementType) { is BuiltinClassId -> BuiltinClassId( - name = arrayIdName, canonicalName = "${elementType.canonicalName}[]", simpleName = "${elementType.simpleName}[]", elementClassId = elementType, diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/tree/CgElement.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/tree/CgElement.kt index ce2de69bcb..41fbfcde6c 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/tree/CgElement.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/tree/CgElement.kt @@ -709,7 +709,6 @@ class CgNotNullAssertion(val expression: CgExpression) : CgValue { override val type: ClassId get() = when (val expressionType = expression.type) { is BuiltinClassId -> BuiltinClassId( - name = expressionType.name, canonicalName = expressionType.canonicalName, simpleName = expressionType.simpleName, isNullable = false, From 52eb8ca2b7fb1f92325c7f7c46cd190744cd26c2 Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Thu, 20 Oct 2022 15:53:27 +0300 Subject: [PATCH 2/4] Little correction --- .../src/main/kotlin/org/utbot/framework/plugin/api/Api.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt index e38acb6bec..94cff4f466 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt @@ -905,7 +905,7 @@ class BuiltinClassId( -1, 0 -> "" else -> canonicalName.substring(0, index) }, -) : ClassId(name = "", isNullable = isNullable, elementClassId = elementClassId) { +) : ClassId(name = canonicalName, isNullable = isNullable, elementClassId = elementClassId) { init { BUILTIN_CLASSES_BY_NAMES[name] = this } From 66661cc94b831f0a9b2f832c435a693b1f751ec8 Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Thu, 20 Oct 2022 22:28:48 +0300 Subject: [PATCH 3/4] Apply corrections --- .../kotlin/org/utbot/framework/plugin/api/Api.kt | 8 ++++++-- .../kotlin/org/utbot/framework/codegen/Domain.kt | 2 +- .../model/constructor/builtin/MockitoBuiltins.kt | 12 +++--------- .../model/constructor/builtin/UtilMethodBuiltins.kt | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt index 94cff4f466..74aaf3fa16 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt @@ -878,6 +878,8 @@ class BuiltinClassId( elementClassId: ClassId? = null, override val canonicalName: String, override val simpleName: String, + // set name manually only if it differs from canonical (e.g. for nested classes) + name: String = canonicalName, // by default, we assume that the class is not a member class override val simpleNameWithEnclosings: String = simpleName, override val isNullable: Boolean = false, @@ -905,7 +907,10 @@ class BuiltinClassId( -1, 0 -> "" else -> canonicalName.substring(0, index) }, -) : ClassId(name = canonicalName, isNullable = isNullable, elementClassId = elementClassId) { +) : ClassId( + name = name, + elementClassId = elementClassId +) { init { BUILTIN_CLASSES_BY_NAMES[name] = this } @@ -923,7 +928,6 @@ class BuiltinClassId( fun getBuiltinClassByNameOrNull(name: String): BuiltinClassId? = BUILTIN_CLASSES_BY_NAMES[name] } } - enum class FieldIdStrategyValues { Reflection, Soot diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt index 88d25e6746..43c85062c4 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/Domain.kt @@ -296,7 +296,7 @@ object TestNg : TestFramework(id = "TestNG",displayName = "TestNG") { override val parameterizedTestAnnotationId: ClassId = BuiltinClassId( canonicalName = "$mainPackage.annotations.Test", - simpleName = "Test" + simpleName = "Test", ) override val methodSourceAnnotationId: ClassId = BuiltinClassId( diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt index 087a33fe87..27e128d210 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/MockitoBuiltins.kt @@ -16,13 +16,6 @@ import org.utbot.framework.plugin.api.util.objectClassId import org.utbot.framework.plugin.api.util.shortClassId import org.utbot.framework.plugin.api.util.stringClassId -internal val mockitoBuiltins: Set - get() = setOf( - mockMethodId, whenMethodId, thenMethodId, thenReturnMethodId, - any, anyOfClass, anyByte, anyChar, anyShort, anyInt, anyLong, - anyFloat, anyDouble, anyBoolean, anyString - ) - internal val mockitoClassId = BuiltinClassId( canonicalName = "org.mockito.Mockito", simpleName = "Mockito", @@ -44,9 +37,10 @@ internal val argumentMatchersClassId = BuiltinClassId( ) internal val mockedConstructionContextClassId = BuiltinClassId( - canonicalName = "org.mockito.MockedConstruction.Context", // TODO use $ as a delimiter of outer and nested classes? + canonicalName = "org.mockito.MockedConstruction.Context", simpleName = "Context", - isNested = true + name = "org.mockito.MockedConstruction\$Context", + isNested = true, ) internal val mockMethodId = builtinStaticMethodId( diff --git a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt index 9ded301468..19d1237d98 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/framework/codegen/model/constructor/builtin/UtilMethodBuiltins.kt @@ -270,7 +270,7 @@ internal val utUtilsClassId: ClassId get() = BuiltinClassId( canonicalName = "org.utbot.runtime.utils.UtUtils", simpleName = "UtUtils", - isFinal = true + isFinal = true, ) /** From 902e98d0061a348d0516528f00720b0df17023f1 Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Thu, 20 Oct 2022 22:42:46 +0300 Subject: [PATCH 4/4] Fix missed field --- .../src/main/kotlin/org/utbot/framework/plugin/api/Api.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt index 74aaf3fa16..723467a634 100644 --- a/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt +++ b/utbot-framework-api/src/main/kotlin/org/utbot/framework/plugin/api/Api.kt @@ -909,7 +909,8 @@ class BuiltinClassId( }, ) : ClassId( name = name, - elementClassId = elementClassId + elementClassId = elementClassId, + isNullable = isNullable, ) { init { BUILTIN_CLASSES_BY_NAMES[name] = this