diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerics.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerics.kt index 7fc34e21..8027f8ef 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerics.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockGenerics.kt @@ -25,11 +25,13 @@ import com.squareup.kotlinpoet.ksp.toTypeVariableName import tech.antibytes.kmock.processor.ProcessorContract.GenericDeclaration import tech.antibytes.kmock.processor.ProcessorContract.GenericResolver import tech.antibytes.kmock.processor.ProcessorContract.TemplateSource +import tech.antibytes.kmock.processor.utils.mapArgumentType internal object KMockGenerics : GenericResolver { private val any = Any::class.asTypeName() private val nullableAnys = listOf(any.copy(nullable = true)) private val nonNullableAnys = listOf(any.copy(nullable = false)) + private const val TYPE_PARAMETER = "KMockTypeParameter" private fun resolveBound(type: KSTypeParameter): List = type.bounds.toList() @@ -59,6 +61,78 @@ internal object KMockGenerics : GenericResolver { ) } + private fun mapTypes( + generics: Map>, + suffix: Int, + ): Map { + var counter = 0 + suffix + return generics.map { (typeName, _) -> + Pair(typeName, "$TYPE_PARAMETER$counter").also { counter++ } + }.toMap() + } + + private fun mapDeclaredGenericsWithSuffix( + generics: Map>, + suffix: Int, + typeResolver: TypeParameterResolver + ): List { + var counter = 0 + suffix + val mapping = mapTypes(generics, suffix) + return generics.map { (_, bounds) -> + TypeVariableName( + "$TYPE_PARAMETER$counter", + bounds = bounds.map { ksReference -> + ksReference.mapArgumentType( + typeParameterResolver = typeResolver, + mapping = mapping, + ) + } + ).also { counter++ } + } + } + + private fun resolveTypeParameter( + typeParameter: Map>?, + typeResolver: TypeParameterResolver, + suffix: Int, + ): List { + return if (typeParameter == null) { + emptyList() + } else { + mapDeclaredGenericsWithSuffix( + generics = typeParameter, + typeResolver = typeResolver, + suffix = suffix, + ) + } + } + + override fun remapTypes( + templates: List, + generics: List>?> + ): Pair, List> { + var counter = 0 + val aggregatedTypeParameter: MutableList = mutableListOf() + val parameterizedParents = templates.mapIndexed { idx, parent -> + val typeParameter = resolveTypeParameter( + typeParameter = generics[idx], + typeResolver = parent.typeParameters.toTypeParameterResolver(), + suffix = counter + ) + val raw = parent.toClassName() + counter += generics[idx]?.size ?: 0 + + if (typeParameter.isNotEmpty()) { + aggregatedTypeParameter.addAll(typeParameter) + raw.parameterizedBy(typeParameter) + } else { + raw + } + } + + return Pair(parameterizedParents, aggregatedTypeParameter) + } + private fun isNullable(type: KSType): Boolean = type.nullability == Nullability.NULLABLE private fun anys(rootNullability: Boolean): List { @@ -357,7 +431,9 @@ internal object KMockGenerics : GenericResolver { } else { template.toClassName() .parameterizedBy( - template.typeParameters.map { type -> type.toTypeVariableName(resolver) } + template.typeParameters.map { type -> + type.toTypeVariableName(resolver) + } ) } } diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessor.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessor.kt index 0d7549f3..44e9e95c 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessor.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessor.kt @@ -11,7 +11,6 @@ import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSFile -import com.squareup.kotlinpoet.ksp.KotlinPoetKspPreview import tech.antibytes.kmock.processor.ProcessorContract.Aggregated import tech.antibytes.kmock.processor.ProcessorContract.KmpCodeGenerator import tech.antibytes.kmock.processor.ProcessorContract.MockFactoryEntryPointGenerator @@ -32,6 +31,7 @@ import tech.antibytes.kmock.processor.ProcessorContract.TemplateSource */ internal class KMockProcessor( private val logger: KSPLogger, + private val isUnderCompilerTest: Boolean, // TODO - Test Concern see: https://github.com/tschuchortdev/kotlin-compile-testing/issues/263 private val isKmp: Boolean, private val codeGenerator: KmpCodeGenerator, private val interfaceGenerator: MultiInterfaceBinder, @@ -118,6 +118,18 @@ internal class KMockProcessor( commonMultiAggregated.extractedTemplates.isEmpty() // TODO - Test Concern see: https://github.com/tschuchortdev/kotlin-compile-testing/issues/263 } + // TODO - Test Concern see: https://github.com/tschuchortdev/kotlin-compile-testing/issues/263 + private fun resolveMultiSources( + aggregated: Aggregated, + stored: Aggregated, + ): List { + return if (isUnderCompilerTest) { + aggregated.extractedTemplates + } else { + stored.extractedTemplates + } + } + private fun stubCommonSources( resolver: Resolver, relaxer: Relaxer? @@ -127,7 +139,7 @@ internal class KMockProcessor( mockGenerator.writeCommonMocks( templateSources = singleCommonSources.extractedTemplates, - templateMultiSources = commonMultiAggregated, + templateMultiSources = resolveMultiSources(multiCommonSources, commonMultiAggregated), relaxer = relaxer, ) @@ -250,7 +262,6 @@ internal class KMockProcessor( return relaxer } - @OptIn(KotlinPoetKspPreview::class) override fun process(resolver: Resolver): List { val relaxer = extractRelaxer(resolver) diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessorProvider.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessorProvider.kt index 02abf6a2..81f5ff03 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessorProvider.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/KMockProcessorProvider.kt @@ -39,7 +39,9 @@ import tech.antibytes.kmock.processor.utils.SourceFilter import tech.antibytes.kmock.processor.utils.SourceSetValidator import tech.antibytes.kmock.processor.utils.SpyContainer -class KMockProcessorProvider : SymbolProcessorProvider { +class KMockProcessorProvider( + private val isUnderCompilerTest: Boolean = false +) : SymbolProcessorProvider { private fun determineFactoryGenerator( options: Options, logger: KSPLogger, @@ -73,8 +75,10 @@ class KMockProcessorProvider : SymbolProcessorProvider { genericResolver = KMockGenerics, ), multiInterfaceGenerator = KMockFactoryMultiInterfaceGenerator( + isKmp = options.isKmp, spyContainer = spyContainer, utils = factoryUtils, + genericResolver = KMockGenerics, ), spyContainer = spyContainer, spiesOnly = options.spiesOnly, @@ -155,12 +159,14 @@ class KMockProcessorProvider : SymbolProcessorProvider { return KMockProcessor( logger = logger, + isUnderCompilerTest = isUnderCompilerTest, isKmp = options.isKmp, codeGenerator = codeGenerator, interfaceGenerator = KMockMultiInterfaceBinder( logger = logger, rootPackage = options.rootPackage, - codeGenerator = codeGenerator + genericResolver = KMockGenerics, + codeGenerator = codeGenerator, ), mockGenerator = KMockGenerator( logger = logger, diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt index 5e67b99c..e92fd091 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/ProcessorContract.kt @@ -195,6 +195,11 @@ internal interface ProcessorContract { typeResolver: TypeParameterResolver ): List + fun remapTypes( + templates: List, + generics: List>?> + ): Pair, List> + fun mapProxyGenerics( generics: Map>, typeResolver: TypeParameterResolver @@ -323,6 +328,7 @@ internal interface ProcessorContract { ksFunction: KSFunctionDeclaration, typeResolver: TypeParameterResolver, enableSpy: Boolean, + inherited: Boolean, relaxer: Relaxer?, ): Pair } @@ -348,7 +354,7 @@ internal interface ProcessorContract { fun writeCommonMocks( templateSources: List, - templateMultiSources: Aggregated, + templateMultiSources: List, relaxer: Relaxer? ) } @@ -356,8 +362,8 @@ internal interface ProcessorContract { fun interface ParentFinder { fun find( templateSource: TemplateSource, - templateMultiSources: Aggregated, - ): List + templateMultiSources: List, + ): TemplateMultiSource? } interface MultiInterfaceBinder { @@ -396,8 +402,6 @@ internal interface ProcessorContract { fun resolveGenerics(templateSource: TemplateSource): List fun resolveModifier(): KModifier? - - fun toTypeNames(types: List): List } interface MockFactoryWithoutGenerics { @@ -417,6 +421,12 @@ internal interface ProcessorContract { val shared: FunSpec ) + data class FactoryMultiBundle( + val kmock: FunSpec?, + val kspy: FunSpec?, + val shared: FunSpec? + ) + interface MockFactoryWithGenerics { fun buildGenericFactories( templateSources: List, @@ -425,10 +435,10 @@ internal interface ProcessorContract { } interface MockFactoryMultiInterface { - fun buildSpyFactory( + fun buildFactories( templateMultiSources: List, relaxer: Relaxer? - ): List + ): List } interface MockFactoryGenerator { diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryEntryPointGenerator.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryEntryPointGenerator.kt index 72559514..cdbbb7fa 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryEntryPointGenerator.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryEntryPointGenerator.kt @@ -27,6 +27,7 @@ import tech.antibytes.kmock.processor.ProcessorContract.MockFactoryGeneratorUtil import tech.antibytes.kmock.processor.ProcessorContract.SpyContainer import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource import tech.antibytes.kmock.processor.ProcessorContract.TemplateSource +import tech.antibytes.kmock.processor.multi.hasGenerics internal class KMockFactoryEntryPointGenerator( private val isKmp: Boolean, @@ -150,13 +151,67 @@ internal class KMockFactoryEntryPointGenerator( ).build() } - private fun buildMultiInterfaceSpyFactory( + private fun buildMultiInterfaceGenericKMockFactory( + boundaries: List, + generics: List + ): FunSpec { + val mockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME).copy(bounds = boundaries) + + return utils.generateKmockSignature( + type = mockType, + generics = emptyList(), + hasDefault = true, + modifier = KModifier.EXPECT + ).addTypeVariables(generics).build() + } + + private fun buildMultiInterfaceGenericKSpyFactory( + boundaries: List, + generics: List + ): FunSpec { + val spyType = TypeVariableName( + KSPY_FACTORY_TYPE_NAME, + bounds = boundaries, + ) + + val mockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME, bounds = listOf(spyType)) + + return utils.generateKspySignature( + mockType = mockType, + spyType = spyType, + generics = emptyList(), + hasDefault = true, + modifier = KModifier.EXPECT + ).addTypeVariables(generics).build() + } + + private fun TemplateMultiSource.isSpyable(): Boolean { + return spyContainer.isSpyable(null, this.packageName, this.templateName) + } + + private fun resolveGenericMultiInterfaceFactories( + templateSource: TemplateMultiSource, + boundaries: List, + generics: List + ): FunSpec { + return if (templateSource.isSpyable()) { + buildMultiInterfaceGenericKSpyFactory(boundaries, generics) + } else { + buildMultiInterfaceGenericKMockFactory(boundaries, generics) + } + } + + private fun buildMultiInterfaceFactory( templateSource: TemplateMultiSource ): FunSpec? { - return if (spyContainer.isSpyable(null, templateSource.packageName, templateSource.templateName)) { - buildMultiInterfaceSpyFactory(utils.toTypeNames(templateSource.templates)) - } else { - null + val (types, generics) = genericResolver.remapTypes(templateSource.templates, templateSource.generics) + + return when { + templateSource.isSpyable() && !templateSource.hasGenerics() -> { + buildMultiInterfaceSpyFactory(types) + } + templateSource.hasGenerics() -> resolveGenericMultiInterfaceFactories(templateSource, types, generics) + else -> null } } @@ -164,7 +219,7 @@ internal class KMockFactoryEntryPointGenerator( templateSources: List ) { templateSources.forEach { source -> - val factory = buildMultiInterfaceSpyFactory(source) + val factory = buildMultiInterfaceFactory(source) if (factory != null) { this.addFunction(factory) diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGenerator.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGenerator.kt index d72ec628..04cb3f6d 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGenerator.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGenerator.kt @@ -93,13 +93,23 @@ internal class KMockFactoryGenerator( } } - val multiInterfaceMocks = multiInterfaceGenerator.buildSpyFactory( + val multiInterfaceMocks = multiInterfaceGenerator.buildFactories( templateMultiSources = templateMultiSources, relaxer = relaxer ) - multiInterfaceMocks.forEach { factory -> - file.addFunction(factory) + multiInterfaceMocks.forEach { factories -> + if (factories.shared != null) { + file.addFunction(factories.shared) + } + + if (factories.kmock != null && !spiesOnly) { + file.addFunction(factories.kmock) + } + + if (factories.kspy != null) { + file.addFunction(factories.kspy) + } } file.build().writeTo( diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGeneratorUtil.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGeneratorUtil.kt index 3432e19d..95697561 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGeneratorUtil.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryGeneratorUtil.kt @@ -6,13 +6,11 @@ package tech.antibytes.kmock.processor.factory -import com.google.devtools.ksp.symbol.KSClassDeclaration import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.TypeVariableName -import com.squareup.kotlinpoet.ksp.toClassName import com.squareup.kotlinpoet.ksp.toTypeParameterResolver import tech.antibytes.kmock.processor.ProcessorContract import tech.antibytes.kmock.processor.ProcessorContract.Companion.SHARED_MOCK_FACTORY @@ -178,13 +176,17 @@ internal class KMockFactoryGeneratorUtil( .addParameter(buildRelaxedParameter(hasDefault)) .addParameter(buildUnitRelaxedParameter(hasDefault)) .addParameter(buildFreezeParameter(hasDefault)) - .returns(type).addTypeVariable(type) + .returns(type).addTypeVariable(type.copy(reified = true)) if (modifier != null) { kmock.addModifiers(modifier) } - return kmock.amendGenericValues(type, generics) + return if (type.bounds.size > 1) { + kmock.amendMultiBounded(type) + } else { + kmock.amendGenericValues(type, generics) + } } private fun buildSpyParameter(nullable: Boolean = false): ParameterSpec { @@ -240,7 +242,11 @@ internal class KMockFactoryGeneratorUtil( .addParameter(buildUnitRelaxedParameter(false)) .addParameter(buildFreezeParameter(false)) - return mockFactory.amendGenericValues(spyType, generics) + return if (spyType.bounds.size > 1) { + mockFactory.amendMultiBounded(spyType) + } else { + mockFactory.amendGenericValues(spyType, generics) + } } override fun splitInterfacesIntoRegularAndGenerics( @@ -262,8 +268,4 @@ internal class KMockFactoryGeneratorUtil( } override fun resolveModifier(): KModifier? = modifier - - override fun toTypeNames( - types: List - ): List = types.map { source -> source.toClassName() } } diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryMultiInterfaceGenerator.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryMultiInterfaceGenerator.kt index caa13adf..ab4a28c0 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryMultiInterfaceGenerator.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryMultiInterfaceGenerator.kt @@ -9,16 +9,22 @@ package tech.antibytes.kmock.processor.factory import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.TypeVariableName +import tech.antibytes.kmock.processor.ProcessorContract import tech.antibytes.kmock.processor.ProcessorContract.Companion.KMOCK_FACTORY_TYPE_NAME import tech.antibytes.kmock.processor.ProcessorContract.Companion.KSPY_FACTORY_TYPE_NAME +import tech.antibytes.kmock.processor.ProcessorContract.FactoryMultiBundle +import tech.antibytes.kmock.processor.ProcessorContract.GenericResolver import tech.antibytes.kmock.processor.ProcessorContract.MockFactoryGeneratorUtil import tech.antibytes.kmock.processor.ProcessorContract.MockFactoryMultiInterface import tech.antibytes.kmock.processor.ProcessorContract.Relaxer import tech.antibytes.kmock.processor.ProcessorContract.SpyContainer import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource +import tech.antibytes.kmock.processor.multi.hasGenerics internal class KMockFactoryMultiInterfaceGenerator( + private val isKmp: Boolean, private val spyContainer: SpyContainer, + private val genericResolver: GenericResolver, private val utils: MockFactoryGeneratorUtil, ) : MockFactoryMultiInterface { private fun buildMockSelectorFlow( @@ -98,15 +104,19 @@ internal class KMockFactoryMultiInterfaceGenerator( private fun resolveBounds( templateMultiSource: TemplateMultiSource, - ): List = utils.toTypeNames(templateMultiSource.templates) + ): Pair, List> { + return genericResolver.remapTypes(templateMultiSource.templates, templateMultiSource.generics) + } private fun buildSpyMockFactory( templateSource: TemplateMultiSource, relaxer: Relaxer? ): FunSpec { + val (bounds, _) = resolveBounds(templateSource) + val spyType = TypeVariableName( KSPY_FACTORY_TYPE_NAME, - bounds = resolveBounds(templateSource) + bounds = bounds ) val mockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME, bounds = listOf(spyType)) @@ -120,18 +130,217 @@ internal class KMockFactoryMultiInterfaceGenerator( ).build() } - override fun buildSpyFactory( + private fun fillMockFactory( + type: TypeVariableName, + generics: List, + ): FunSpec.Builder { + val modifier = utils.resolveModifier() + + return utils.generateKmockSignature( + type = type, + generics = generics, + hasDefault = !isKmp, + modifier = modifier + ).addTypeVariables(generics) + } + + private fun fillMockFactory( + mockType: TypeVariableName, + spyType: TypeVariableName, + generics: List, + ): FunSpec.Builder { + val modifier = utils.resolveModifier() + + return utils.generateKspySignature( + mockType = mockType, + spyType = spyType, + generics = generics, + hasDefault = !isKmp, + modifier = modifier + ).addTypeVariables(generics) + } + + private fun generateTypeArgument( + bounds: List + ): String { + val typeArgumentBuilder = StringBuilder() + + bounds.forEachIndexed { idx, _ -> + typeArgumentBuilder.append("templateType$idx = templateType$idx,\n") + } + + return typeArgumentBuilder.toString().trimEnd() + } + + private fun buildGenericKmockFactory( + bounds: List, + generics: List, + ): FunSpec { + val type = TypeVariableName( + KMOCK_FACTORY_TYPE_NAME, + bounds = bounds + ) + + return fillMockFactory( + generics = generics, + type = type, + ).addCode( + factoryInvocationWithTemplate, + generateTypeArgument(bounds) + ).build() + } + + private fun buildGenericKSpyFactory( + bounds: List, + generics: List, + ): FunSpec { + val spyType = TypeVariableName( + KSPY_FACTORY_TYPE_NAME, + bounds = bounds + ) + + val mockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME, bounds = listOf(spyType)) + + return fillMockFactory( + mockType = mockType, + spyType = spyType, + generics = generics, + ).addCode( + spyFactoryInvocationWithTemplate, + generateTypeArgument(bounds) + ).build() + } + + private fun fillSharedMockFactory( + mockType: TypeVariableName, + spyType: TypeVariableName, + templateSource: TemplateMultiSource, + generics: List, + relaxer: Relaxer? + ): FunSpec.Builder { + val mockFactory = utils.generateSharedMockFactorySignature( + mockType = mockType, + spyType = spyType, + generics = generics, + ) + + mockFactory.addTypeVariables(generics) + + return buildMockSelector( + mockFactory = mockFactory, + templateSource = templateSource, + relaxer = relaxer + ) + } + + private fun buildGenericSharedMockFactory( + templateSource: TemplateMultiSource, + bounds: List, + generics: List, + relaxer: Relaxer? + ): FunSpec { + val spyType = TypeVariableName( + KSPY_FACTORY_TYPE_NAME, + bounds = bounds, + ) + + val mockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME, bounds = listOf(spyType)) + + return fillSharedMockFactory( + mockType = mockType, + spyType = spyType, + templateSource = templateSource, + generics = generics, + relaxer = relaxer + ).build() + } + + private fun TemplateMultiSource.isSpyable(): Boolean { + return spyContainer.isSpyable(null, this.packageName, this.templateName) + } + + private fun resolveGenericSpyFactory( + templateSource: TemplateMultiSource, + bounds: List, + generics: List, + ): FunSpec? { + return if (templateSource.isSpyable()) { + buildGenericKSpyFactory( + bounds = bounds, + generics = generics, + ) + } else { + null + } + } + + private fun buildGenericFactories( + templateSource: TemplateMultiSource, + relaxer: Relaxer? + ): FactoryMultiBundle { + val (bounds, generics) = resolveBounds(templateSource) + + return FactoryMultiBundle( + shared = buildGenericSharedMockFactory( + templateSource = templateSource, + bounds = bounds, + generics = generics, + relaxer = relaxer + ), + kmock = buildGenericKmockFactory( + bounds = bounds, + generics = generics, + ), + kspy = resolveGenericSpyFactory(templateSource, bounds, generics), + ) + } + + override fun buildFactories( templateMultiSources: List, relaxer: Relaxer? - ): List { - val factories: MutableList = mutableListOf() + ): List { + val factories: MutableList = mutableListOf() templateMultiSources.forEach { source -> - if (spyContainer.isSpyable(null, source.packageName, source.templateName)) { - factories.add(buildSpyMockFactory(source, relaxer)) + if (source.isSpyable() && !source.hasGenerics()) { + factories.add( + FactoryMultiBundle( + kmock = null, + shared = null, + kspy = buildSpyMockFactory(source, relaxer) + ) + ) + } + + if (source.hasGenerics()) { + factories.add(buildGenericFactories(source, relaxer)) } } return factories } + + private companion object { + private val factoryInvocationWithTemplate = """ + |return ${ProcessorContract.SHARED_MOCK_FACTORY}( + | spyOn = null, + | verifier = verifier, + | relaxed = relaxed, + | relaxUnitFun = relaxUnitFun, + | freeze = freeze, + | %L + |) + """.trimMargin() + + private val spyFactoryInvocationWithTemplate = """ + |return ${ProcessorContract.SHARED_MOCK_FACTORY}( + | spyOn = spyOn, + | verifier = verifier, + | relaxed = false, + | relaxUnitFun = false, + | freeze = freeze, + | %L + |) + """.trimMargin() + } } diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithGenerics.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithGenerics.kt index db59e44b..7535d3c8 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithGenerics.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithGenerics.kt @@ -166,7 +166,7 @@ internal class KMockFactoryWithGenerics( ) } - private fun buildMockSelector( + private fun buildSharedMockSelector( mockFactory: FunSpec.Builder, templateSource: TemplateSource, generics: List, @@ -197,7 +197,7 @@ internal class KMockFactoryWithGenerics( generics = generics, ) - return buildMockSelector( + return buildSharedMockSelector( mockFactory = mockFactory, templateSource = templateSource, generics = generics, diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithoutGenerics.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithoutGenerics.kt index bc7d883a..afc3a519 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithoutGenerics.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/factory/KMockFactoryWithoutGenerics.kt @@ -16,6 +16,7 @@ import tech.antibytes.kmock.processor.ProcessorContract.MockFactoryWithoutGeneri import tech.antibytes.kmock.processor.ProcessorContract.Relaxer import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource import tech.antibytes.kmock.processor.ProcessorContract.TemplateSource +import tech.antibytes.kmock.processor.multi.hasGenerics import tech.antibytes.kmock.processor.utils.ensureNotNullClassName internal class KMockFactoryWithoutGenerics( @@ -137,18 +138,16 @@ internal class KMockFactoryWithoutGenerics( relaxer: Relaxer? ) { buildMockSelectorFlow(this) { - if (templateSources.isNotEmpty()) { - templateSources.forEach { source -> - amendSource( - mockFactory = this, - templateSource = source, - relaxer = relaxer - ) - } + templateSources.forEach { source -> + amendSource( + mockFactory = this, + templateSource = source, + relaxer = relaxer + ) } - if (templateMultiSources.isNotEmpty()) { - templateMultiSources.forEach { source -> + templateMultiSources.forEach { source -> + if (!source.hasGenerics()) { amendMultiSource( mockFactory = this, templateSource = source, @@ -217,7 +216,7 @@ internal class KMockFactoryWithoutGenerics( override fun buildSpyFactory(): FunSpec = fillSpyFactory().build() private companion object { - private val kmockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME).copy(reified = true) + private val kmockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME) private val kspyType = TypeVariableName(KSPY_FACTORY_TYPE_NAME) private val kspyMockType = TypeVariableName(KMOCK_FACTORY_TYPE_NAME, bounds = listOf(kspyType)) diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockGenerator.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockGenerator.kt index 2df00452..bb0d1579 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockGenerator.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockGenerator.kt @@ -23,7 +23,6 @@ import com.squareup.kotlinpoet.ksp.TypeParameterResolver import com.squareup.kotlinpoet.ksp.toTypeParameterResolver import com.squareup.kotlinpoet.ksp.writeTo import tech.antibytes.kmock.processor.ProcessorContract -import tech.antibytes.kmock.processor.ProcessorContract.Aggregated import tech.antibytes.kmock.processor.ProcessorContract.BuildInMethodGenerator import tech.antibytes.kmock.processor.ProcessorContract.Companion.COLLECTOR_NAME import tech.antibytes.kmock.processor.ProcessorContract.Companion.COMMON_INDICATOR @@ -122,26 +121,27 @@ internal class KMockGenerator( private fun resolveSuperTypes( template: KSClassDeclaration, - parents: List, + parents: TemplateMultiSource?, typeResolver: TypeParameterResolver, ): List { - return if (parents.isEmpty()) { + return if (parents != null) { + val (parameterizedParent, _) = genericsResolver.remapTypes(parents.templates, parents.generics) + parameterizedParent + } else { listOf( genericsResolver.resolveMockClassType(template, typeResolver) ) - } else { - parents.map { parent -> - val resolver = parent.typeParameters.toTypeParameterResolver() - - genericsResolver.resolveMockClassType(parent, resolver) - } } } + private fun KSClassDeclaration.isInherited( + parents: TemplateMultiSource? + ): Boolean = parents != null || this.superTypes.firstOrNull() != null + private fun buildMock( mockName: String, enableSpy: Boolean, - parents: List, + parents: TemplateMultiSource?, template: KSClassDeclaration, generics: Map>?, relaxer: Relaxer? @@ -233,6 +233,7 @@ internal class KMockGenerator( ksFunction = ksFunction, typeResolver = typeResolver, enableSpy = enableSpy, + inherited = template.isInherited(parents), relaxer = relaxer, ) @@ -266,7 +267,7 @@ internal class KMockGenerator( private fun writeMock( template: KSClassDeclaration, - parents: List, + parents: TemplateMultiSource?, templateName: String, packageName: String, generics: Map>?, @@ -314,7 +315,7 @@ internal class KMockGenerator( override fun writeCommonMocks( templateSources: List, - templateMultiSources: Aggregated, + templateMultiSources: List, relaxer: Relaxer? ) { templateSources.forEach { template -> @@ -346,7 +347,7 @@ internal class KMockGenerator( writeMock( template = template.template, - parents = emptyList(), + parents = null, templateName = template.templateName, packageName = template.packageName, generics = template.generics, @@ -364,7 +365,7 @@ internal class KMockGenerator( writeMock( template = template.template, - parents = emptyList(), + parents = null, templateName = template.templateName, packageName = template.packageName, generics = template.generics, diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockMethodGenerator.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockMethodGenerator.kt index d92ac6df..6d3a2227 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockMethodGenerator.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KMockMethodGenerator.kt @@ -36,6 +36,7 @@ import tech.antibytes.kmock.processor.ProcessorContract.NonIntrusiveInvocationGe import tech.antibytes.kmock.processor.ProcessorContract.ProxyInfo import tech.antibytes.kmock.processor.ProcessorContract.ProxyNameSelector import tech.antibytes.kmock.processor.ProcessorContract.Relaxer +import tech.antibytes.kmock.processor.utils.toSecuredTypeName internal class KMockMethodGenerator( private val nameSelector: ProxyNameSelector, @@ -72,15 +73,20 @@ internal class KMockMethodGenerator( ) private fun determineArguments( + inherited: Boolean, parameters: List, - parameterTypeResolver: TypeParameterResolver + typeParameterResolver: TypeParameterResolver ): Array { return parameters.map { parameter -> val argumentName = parameter.name!!.asString() + parameter.type.modifiers MethodTypeInfo( argumentName = argumentName, - typeName = parameter.type.toTypeName(parameterTypeResolver), + typeName = parameter.type.toSecuredTypeName( + inheritedVarargArg = parameter.isVararg && inherited, + typeParameterResolver = typeParameterResolver + ), isVarArg = parameter.isVararg, ) }.toTypedArray() @@ -124,8 +130,8 @@ internal class KMockMethodGenerator( val generic = proxyGenericTypes[typeName.toString().trimEnd('?')] val actualTypeName = resolveGenericProxyType( - typeName, - generic + typeName = typeName, + generic = generic ) return MethodReturnTypeInfo( @@ -387,21 +393,26 @@ internal class KMockMethodGenerator( ksFunction: KSFunctionDeclaration, typeResolver: TypeParameterResolver, enableSpy: Boolean, + inherited: Boolean, relaxer: Relaxer? ): Pair { val methodName = ksFunction.simpleName.asString() - val parameterTypeResolver = ksFunction + val typeParameterResolver = ksFunction .typeParameters .toTypeParameterResolver(typeResolver) - val generics = genericResolver.extractGenerics(ksFunction, parameterTypeResolver) - val arguments = determineArguments(ksFunction.parameters, parameterTypeResolver) + val generics = genericResolver.extractGenerics(ksFunction, typeParameterResolver) + val arguments = determineArguments( + inherited = inherited, + parameters = ksFunction.parameters, + typeParameterResolver = typeParameterResolver + ) val proxyInfo = nameSelector.selectMethodName( qualifier = qualifier, methodName = methodName, arguments = arguments, generics = generics ?: emptyMap(), - typeResolver = parameterTypeResolver, + typeResolver = typeParameterResolver, ) val returnType = ksFunction.returnType!!.resolve() val isSuspending = ksFunction.modifiers.contains(Modifier.SUSPEND) @@ -413,7 +424,7 @@ internal class KMockMethodGenerator( generics = generics, suspending = isSuspending, returnType = returnType, - typeResolver = parameterTypeResolver, + typeResolver = typeParameterResolver, ) val method = buildMethod( @@ -425,7 +436,7 @@ internal class KMockMethodGenerator( arguments = arguments, rawReturnType = returnType, proxyReturnType = proxySignature?.returnType, - typeResolver = parameterTypeResolver, + typeResolver = typeParameterResolver, relaxer = relaxer ) diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KmockProxyNameSelector.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KmockProxyNameSelector.kt index 867f514f..9b63b193 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KmockProxyNameSelector.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/mock/KmockProxyNameSelector.kt @@ -158,7 +158,7 @@ internal class KmockProxyNameSelector( currentName = resolveGenericName(generics[currentName], typeResolver) ?: "Any" } while (currentName in generics) - return currentName + return currentName.trimEnd('?') } private fun String.resolveActualName( diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockMultiInterfaceBinder.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockMultiInterfaceBinder.kt index af9de1c7..7f0ee120 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockMultiInterfaceBinder.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockMultiInterfaceBinder.kt @@ -9,31 +9,39 @@ package tech.antibytes.kmock.processor.multi import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSFile +import com.google.devtools.ksp.symbol.KSTypeReference import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.TypeSpec -import com.squareup.kotlinpoet.ksp.toTypeName import com.squareup.kotlinpoet.ksp.writeTo import tech.antibytes.kmock.MockCommon import tech.antibytes.kmock.processor.ProcessorContract.Companion.INTERMEDIATE_INTERFACES_FILE_NAME +import tech.antibytes.kmock.processor.ProcessorContract.GenericResolver import tech.antibytes.kmock.processor.ProcessorContract.KmpCodeGenerator import tech.antibytes.kmock.processor.ProcessorContract.MultiInterfaceBinder import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource internal class KMockMultiInterfaceBinder( private val logger: KSPLogger, + private val genericResolver: GenericResolver, private val rootPackage: String, private val codeGenerator: KmpCodeGenerator, ) : MultiInterfaceBinder { private fun createInterface( interfaceName: String, - templates: List + templates: List, + generics: List>?>, ): TypeSpec { val interfaze = TypeSpec.interfaceBuilder(interfaceName) - interfaze.addSuperinterfaces( - templates.map { parent -> parent.asStarProjectedType().toTypeName() } - ) + + val (parents, typeParameter) = genericResolver.remapTypes(templates, generics) + interfaze.addSuperinterfaces(parents) + + if (typeParameter.isNotEmpty()) { + interfaze.addTypeVariables(typeParameter) + } + interfaze.addAnnotation( AnnotationSpec.builder(MockCommon::class).addMember("$interfaceName::class").build() ) @@ -54,7 +62,8 @@ internal class KMockMultiInterfaceBinder( templateSources.map { source -> val implementation = createInterface( interfaceName = source.templateName, - templates = source.templates + templates = source.templates, + generics = source.generics ) file.addType(implementation) diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockParentFinder.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockParentFinder.kt index 7b3f8c12..b7871520 100644 --- a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockParentFinder.kt +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/KMockParentFinder.kt @@ -6,8 +6,6 @@ package tech.antibytes.kmock.processor.multi -import com.google.devtools.ksp.symbol.KSClassDeclaration -import tech.antibytes.kmock.processor.ProcessorContract.Aggregated import tech.antibytes.kmock.processor.ProcessorContract.ParentFinder import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource import tech.antibytes.kmock.processor.ProcessorContract.TemplateSource @@ -15,18 +13,12 @@ import tech.antibytes.kmock.processor.ProcessorContract.TemplateSource internal object KMockParentFinder : ParentFinder { override fun find( templateSource: TemplateSource, - templateMultiSources: Aggregated, - ): List { - val parentsIdx = templateMultiSources.extractedTemplates.indexOfFirst { parent -> + templateMultiSources: List, + ): TemplateMultiSource? { + return templateMultiSources.firstOrNull { parent -> templateSource.packageName == parent.packageName && templateSource.indicator == parent.indicator && templateSource.templateName == parent.templateName } - - return if (parentsIdx == -1) { - emptyList() - } else { - templateMultiSources.extractedTemplates[parentsIdx].templates - } } } diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/TemplateMultiSource.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/TemplateMultiSource.kt new file mode 100644 index 00000000..b4fc7815 --- /dev/null +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/multi/TemplateMultiSource.kt @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package tech.antibytes.kmock.processor.multi + +import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource + +internal fun TemplateMultiSource.hasGenerics(): Boolean = this.generics.any { item -> item != null } diff --git a/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/utils/KotlinPoet.kt b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/utils/KotlinPoet.kt new file mode 100644 index 00000000..5051d393 --- /dev/null +++ b/kmock-processor/src/main/kotlin/tech/antibytes/kmock/processor/utils/KotlinPoet.kt @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package tech.antibytes.kmock.processor.utils + +import com.google.devtools.ksp.isLocal +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSDeclaration +import com.google.devtools.ksp.symbol.KSType +import com.google.devtools.ksp.symbol.KSTypeAlias +import com.google.devtools.ksp.symbol.KSTypeArgument +import com.google.devtools.ksp.symbol.KSTypeParameter +import com.google.devtools.ksp.symbol.KSTypeReference +import com.google.devtools.ksp.symbol.Variance +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.LambdaTypeName +import com.squareup.kotlinpoet.ParameterizedTypeName +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.STAR +import com.squareup.kotlinpoet.TypeName +import com.squareup.kotlinpoet.TypeVariableName +import com.squareup.kotlinpoet.WildcardTypeName +import com.squareup.kotlinpoet.ksp.TypeParameterResolver +import com.squareup.kotlinpoet.ksp.toClassName +import com.squareup.kotlinpoet.ksp.toTypeName +import com.squareup.kotlinpoet.ksp.toTypeParameterResolver +import com.squareup.kotlinpoet.tags.TypeAliasTag + +// see: https://github.com/square/kotlinpoet/blob/9af3f67bb4338f6f35fcd29cb9228227981ae1ce/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/utils.kt#L16 +private fun TypeName.rawType(): ClassName { + return findRawType() ?: throw IllegalArgumentException("Cannot get raw type from $this") +} + +private fun TypeName.findRawType(): ClassName? { + return when (this) { + is ClassName -> this + is ParameterizedTypeName -> rawType + is LambdaTypeName -> { + var count = parameters.size + if (receiver != null) { + count++ + } + val functionSimpleName = if (count >= 23) { + "FunctionN" + } else { + "Function$count" + } + ClassName("kotlin.jvm.functions", functionSimpleName) + } + else -> null + } +} + +private fun ClassName.withTypeArguments(arguments: List): TypeName { + return if (arguments.isEmpty()) { + this + } else { + this.parameterizedBy(arguments) + } +} + +private fun KSDeclaration.toClassNameInternal(): ClassName { + require(!isLocal()) { + "Local/anonymous classes are not supported!" + } + val pkgName = packageName.asString() + val typesString = checkNotNull(qualifiedName).asString().removePrefix("$pkgName.") + + val simpleNames = typesString + .split(".") + return ClassName(pkgName, simpleNames) +} + +internal fun TypeVariableName.copy(name: String): TypeVariableName { + return TypeVariableName( + name, + bounds = this.bounds, + variance = this.variance, + ).copy( + reified = this.isReified, + tags = this.tags, + nullable = this.isNullable, + annotations = this.annotations, + ) +} + +internal fun WildcardTypeName.toTypeVariableName(): TypeVariableName { + val type = this.outTypes.first() as TypeVariableName + + return TypeVariableName( + type.name, + bounds = type.bounds, + ).copy( + reified = type.isReified, + tags = type.tags, + annotations = type.annotations, + nullable = type.isNullable + ) +} + +private fun extractAliasTypeResolver( + declaration: KSTypeAlias, + typeParameterResolver: TypeParameterResolver +): TypeParameterResolver { + return if (declaration.typeParameters.isEmpty()) { + typeParameterResolver + } else { + declaration.typeParameters.toTypeParameterResolver(typeParameterResolver) + } +} + +private fun KSTypeAlias.abbreviateType( + typeParameterResolver: TypeParameterResolver, + isNullable: Boolean, + typeArguments: List +): TypeName { + return this.type.resolve() + .toTypeName(typeParameterResolver) + .copy(nullable = isNullable) + .rawType() + .withTypeArguments(typeArguments) +} + +private fun KSTypeAlias.parameterizedBy( + abbreviateType: TypeName, + typeArguments: List, +): TypeName { + return this.toClassNameInternal() + .withTypeArguments(typeArguments) + .copy(tags = mapOf(TypeAliasTag::class to TypeAliasTag(abbreviateType))) +} + +internal fun KSTypeReference.mapArgumentType( + typeParameterResolver: TypeParameterResolver = TypeParameterResolver.EMPTY, + mapping: Map, +): TypeName { + return resolve().mapArgumentType( + typeParameterResolver = typeParameterResolver, + mapping = mapping, + typeArguments = element?.typeArguments.orEmpty(), + ) +} + +private fun KSTypeArgument.mapArgumentType( + typeParameterResolver: TypeParameterResolver = TypeParameterResolver.EMPTY, + mapping: Map, +): TypeName { + val typeName = type?.mapArgumentType( + typeParameterResolver = typeParameterResolver, + mapping = mapping, + ) ?: return STAR + return when (variance) { + Variance.COVARIANT -> WildcardTypeName.producerOf(typeName) + Variance.CONTRAVARIANT -> WildcardTypeName.consumerOf(typeName) + Variance.STAR -> STAR + Variance.INVARIANT -> typeName + } +} + +// see: https://github.com/square/kotlinpoet/blob/9af3f67bb4338f6f35fcd29cb9228227981ae1ce/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/ksTypes.kt#L60 +internal fun KSType.mapArgumentType( + typeParameterResolver: TypeParameterResolver, + mapping: Map, + typeArguments: List, +): TypeName { + require(!isError) { + "Error type '$this' is not resolvable in the current round of processing." + } + + val type = when (val declaration = this.declaration) { + is KSTypeParameter -> { + val parameterType = typeParameterResolver[declaration.name.getShortName()] + + if (parameterType.name in mapping) { + parameterType.copy(mapping[parameterType.name]!!) + } else { + parameterType + } + } + is KSClassDeclaration -> { + declaration.toClassName().withTypeArguments( + arguments.map { argument -> + argument.mapArgumentType( + typeParameterResolver = typeParameterResolver, + mapping = mapping, + ) + } + ) + } + is KSTypeAlias -> { + val extraResolver = extractAliasTypeResolver(declaration, typeParameterResolver) + + val mappedArgs = arguments.map { argument -> + argument.mapArgumentType( + typeParameterResolver = typeParameterResolver, + mapping = mapping, + ) + } + + val abbreviatedType = declaration.abbreviateType( + typeParameterResolver = extraResolver, + isNullable = isMarkedNullable, + typeArguments = mappedArgs + ) + + val aliasArgs = typeArguments.map { argument -> + argument.mapArgumentType( + typeParameterResolver = typeParameterResolver, + mapping = mapping, + ) + } + + declaration.parameterizedBy(abbreviatedType, aliasArgs) + } + else -> error("Unsupported type: $declaration") + } + + return type.copy(nullable = isMarkedNullable) +} + +/* Workaround to overcome KSP misalignment on inherited types with function TypeParameter */ +// see: https://github.com/google/ksp/issues/958 +// TODO - Remove the following methods when KSP fixes this +internal fun KSTypeArgument.toSecuredTypeName( + inheritedVarargArg: Boolean, + typeParameterResolver: TypeParameterResolver, + rootTypeArguments: List, +): TypeName { + val typeName = type?.toSecuredTypeName( + inheritedVarargArg = inheritedVarargArg, + typeParameterResolver = typeParameterResolver, + rootTypeArguments = rootTypeArguments, + ) ?: return STAR + return when (variance) { + Variance.COVARIANT -> WildcardTypeName.producerOf(typeName) + Variance.CONTRAVARIANT -> WildcardTypeName.consumerOf(typeName) + Variance.STAR -> STAR + Variance.INVARIANT -> typeName + } +} + +private fun KSClassDeclaration.isMisalignedVararg( + inheritedVarargArg: Boolean, + arguments: List, + rootTypeArguments: List +): Boolean { + val resolved = rootTypeArguments.firstOrNull()?.type?.resolve()?.declaration?.simpleName?.getShortName() + val derived = arguments.firstOrNull()?.toString() + + return this.simpleName.getShortName() == "Array" && inheritedVarargArg && derived != resolved +} + +private fun KSType.toSecuredTypeName( + inheritedVarargArg: Boolean, + typeParameterResolver: TypeParameterResolver, + typeArguments: List, + rootTypeArguments: List, +): TypeName { + require(!isError) { + "Error type '$this' is not resolvable in the current round of processing." + } + + var overrideNullability = false + + val type = when (val declaration = this.declaration) { + is KSClassDeclaration -> { + val arguments = arguments.map { argument -> + argument.toSecuredTypeName( + inheritedVarargArg = inheritedVarargArg, + typeParameterResolver = typeParameterResolver, + rootTypeArguments = rootTypeArguments, + ) + } + + if (declaration.isMisalignedVararg(inheritedVarargArg, arguments, rootTypeArguments)) { + (arguments.first() as WildcardTypeName).toTypeVariableName().also { resolved -> + overrideNullability = resolved.isNullable + } + } else { + declaration.toClassName().withTypeArguments(arguments) + } + } + is KSTypeParameter -> { + typeParameterResolver[declaration.name.getShortName()] + } + is KSTypeAlias -> { + val extraResolver = extractAliasTypeResolver(declaration, typeParameterResolver) + + val mappedArgs = arguments.map { argument -> + argument.toSecuredTypeName( + inheritedVarargArg = inheritedVarargArg, + typeParameterResolver = typeParameterResolver, + rootTypeArguments = rootTypeArguments, + ) + } + + val abbreviatedType = declaration.abbreviateType( + typeParameterResolver = extraResolver, + isNullable = isMarkedNullable, + typeArguments = mappedArgs + ) + + val aliasArgs = typeArguments.map { argument -> + argument.toSecuredTypeName( + inheritedVarargArg = inheritedVarargArg, + typeParameterResolver = typeParameterResolver, + rootTypeArguments = rootTypeArguments, + ) + } + + declaration.parameterizedBy(abbreviatedType, aliasArgs) + } + else -> error("Unsupported type: $declaration") + } + + return type.copy(nullable = (isMarkedNullable || overrideNullability)) +} + +private fun KSTypeReference.toSecuredTypeName( + inheritedVarargArg: Boolean, + typeParameterResolver: TypeParameterResolver, + rootTypeArguments: List, +): TypeName { + val typeElements = element?.typeArguments.orEmpty() + + return resolve().toSecuredTypeName( + inheritedVarargArg = inheritedVarargArg, + typeParameterResolver = typeParameterResolver, + typeArguments = typeElements, + rootTypeArguments = rootTypeArguments, + ) +} + +internal fun KSTypeReference.toSecuredTypeName( + inheritedVarargArg: Boolean, + typeParameterResolver: TypeParameterResolver, +): TypeName { + val typeElements = element?.typeArguments.orEmpty() + val type = resolve() + + return type.toSecuredTypeName( + inheritedVarargArg = inheritedVarargArg, + typeParameterResolver = typeParameterResolver, + typeArguments = typeElements, + rootTypeArguments = typeElements, + ) +} diff --git a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMocksSpec.kt b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMocksSpec.kt index 4ada57d5..70b66b37 100644 --- a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMocksSpec.kt +++ b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMocksSpec.kt @@ -298,6 +298,26 @@ class KMockMocksSpec { actual!!.readText().normalizeSource() mustBe expected.normalizeSource() } + @Test + fun `Given a annotated Source for Generics for a Platform with a supertype is processed, it writes a mock`() { + // Given + val source = SourceFile.kotlin( + "Platform.kt", + loadResource("/template/generic/SuperTyped.kt") + ) + val expected = loadResource("/expected/generic/SuperTyped.kt") + + // When + val compilerResult = compile(provider, source, isKmp = false) + val actual = resolveGenerated("SuperTypedMock.kt") + + // Then + compilerResult.exitCode mustBe KotlinCompilation.ExitCode.OK + actual isNot null + + actual!!.readText().normalizeSource() mustBe expected.normalizeSource() + } + @Test fun `Given a annotated Source for Generics for Shared is processed, it writes a mock`() { // Given diff --git a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMultiInterfaceMocksSpec.kt b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMultiInterfaceMocksSpec.kt index 524c6c51..f0507a82 100644 --- a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMultiInterfaceMocksSpec.kt +++ b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/integration/KMockMultiInterfaceMocksSpec.kt @@ -37,11 +37,11 @@ class KMockMultiInterfaceMocksSpec { } // Workaround for https://github.com/tschuchortdev/kotlin-compile-testing/issues/263 - class SymbolProcessorProviderSpy : SymbolProcessorProvider { + class SymbolProcessorProviderSpy(private val useTestFlag: Boolean = false) : SymbolProcessorProvider { lateinit var lastProcessor: SymbolProcessor override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { - val processor = KMockProcessorProvider().create(environment) + val processor = KMockProcessorProvider(useTestFlag).create(environment) lastProcessor = processor return processor @@ -236,6 +236,9 @@ class KMockMultiInterfaceMocksSpec { val compilerResultRound2 = compile( provider, isKmp = true, + kspArguments = mapOf( + "${KMOCK_PREFIX}spyOn_0" to "multi.CommonMulti", + ), sourceFiles = arrayOf(multiInterfaceInterface, rootInterface, nestedInterface, scopedInterface) ) val actualMock = resolveGenerated("CommonMultiMock.kt") @@ -249,4 +252,157 @@ class KMockMultiInterfaceMocksSpec { ) mustBe true actualMock.readText().normalizeSource() mustBe expectedMock.normalizeSource() } + + @Test + fun `Given a annotated Source for generic Common with multiple Interface it writes a mock`() { + // Round1 + // Given + val spyProvider = SymbolProcessorProviderSpy(true) + val rootInterface = SourceFile.kotlin( + "Generic1.kt", + loadResource("/template/commonGeneric/Generic1.kt") + ) + val nestedInterface = SourceFile.kotlin( + "Generic2.kt", + loadResource("/template/commonGeneric/nested/Generic2.kt") + ) + val scopedInterface = SourceFile.kotlin( + "Generic3.kt", + loadResource("/template/commonGeneric/Generic3.kt") + ) + val expectedInterface = loadResource("/expected/commonGeneric/GenericInterface.kt") + val expectedActualFactory = loadResource("/expected/commonGeneric/GenericActualFactory.kt") + val expectedExpectFactory = loadResource("/expected/commonGeneric/GenericExpectFactory.kt") + + // When + val compilerResultRound1 = compile( + spyProvider, + isKmp = true, + kspArguments = mapOf( + "${KMOCK_PREFIX}allowInterfaces" to "true" + ), + sourceFiles = arrayOf(rootInterface, nestedInterface, scopedInterface) + ) + val actualIntermediateInterfaces = resolveGenerated("KMockMultiInterfaceArtifacts.kt") + val actualActualMockFactory = resolveGenerated("ksp/sources/kotlin/$rootPackage/MockFactory.kt") + val actualExpectMockFactory = resolveGenerated("kotlin/common/commonTest/kotlin/$rootPackage/MockFactory.kt") + + // Then + compilerResultRound1.exitCode mustBe KotlinCompilation.ExitCode.OK + actualIntermediateInterfaces isNot null + actualActualMockFactory isNot null + actualExpectMockFactory isNot null + + actualIntermediateInterfaces!!.absolutePath.toString().endsWith( + "ksp/sources/kotlin/$rootPackage/KMockMultiInterfaceArtifacts.kt" + ) mustBe true + actualIntermediateInterfaces.readText().normalizeSource() mustBe expectedInterface.normalizeSource() + actualActualMockFactory!!.readText().normalizeSource() mustBe expectedActualFactory.normalizeSource() + actualExpectMockFactory!!.readText().normalizeSource() mustBe expectedExpectFactory.normalizeSource() + + // Round2 + // Given + val provider = ShallowSymbolProcessorProvider(spyProvider.lastProcessor) + val multiInterfaceInterface = SourceFile.kotlin( + "KMockMultiInterfaceArtifacts.kt", + actualIntermediateInterfaces.readText() + ) + val expectedMock = loadResource("/expected/commonGeneric/GenericMock.kt") + + // When + val compilerResultRound2 = compile( + provider, + isKmp = true, + sourceFiles = arrayOf(multiInterfaceInterface, rootInterface, nestedInterface, scopedInterface) + ) + val actualMock = resolveGenerated("CommonGenericMultiMock.kt") + + // Then + compilerResultRound2.exitCode mustBe KotlinCompilation.ExitCode.OK + actualMock isNot null + + actualMock!!.absolutePath.toString().endsWith( + "ksp/sources/kotlin/common/commonTest/kotlin/multi/CommonGenericMultiMock.kt" + ) mustBe true + actualMock.readText().normalizeSource() mustBe expectedMock.normalizeSource() + } + + @Test + fun `Given a annotated Source for generic Common while spied with multiple Interface it writes a mock`() { + // Round1 + // Given + val spyProvider = SymbolProcessorProviderSpy(true) + val rootInterface = SourceFile.kotlin( + "Generic1.kt", + loadResource("/template/commonGeneric/Generic1.kt") + ) + val nestedInterface = SourceFile.kotlin( + "Generic2.kt", + loadResource("/template/commonGeneric/nested/Generic2.kt") + ) + val scopedInterface = SourceFile.kotlin( + "Generic3.kt", + loadResource("/template/commonGeneric/Generic3.kt") + ) + val expectedInterface = loadResource("/expected/commonGeneric/SpiedGenericInterface.kt") + val expectedActualFactory = loadResource("/expected/commonGeneric/SpiedGenericActualFactory.kt") + val expectedExpectFactory = loadResource("/expected/commonGeneric/SpiedGenericExpectFactory.kt") + + // When + val compilerResultRound1 = compile( + spyProvider, + isKmp = true, + kspArguments = mapOf( + "${KMOCK_PREFIX}allowInterfaces" to "true", + "${KMOCK_PREFIX}spiesOnly" to "true", + ), + sourceFiles = arrayOf(rootInterface, nestedInterface, scopedInterface) + ) + val actualIntermediateInterfaces = resolveGenerated("KMockMultiInterfaceArtifacts.kt") + val actualActualMockFactory = resolveGenerated("ksp/sources/kotlin/$rootPackage/MockFactory.kt") + val actualExpectMockFactory = resolveGenerated("kotlin/common/commonTest/kotlin/$rootPackage/MockFactory.kt") + + // Then + compilerResultRound1.exitCode mustBe KotlinCompilation.ExitCode.OK + actualIntermediateInterfaces isNot null + actualActualMockFactory isNot null + actualExpectMockFactory isNot null + + actualIntermediateInterfaces!!.absolutePath.toString().endsWith( + "ksp/sources/kotlin/$rootPackage/KMockMultiInterfaceArtifacts.kt" + ) mustBe true + actualIntermediateInterfaces.readText().normalizeSource() mustBe expectedInterface.normalizeSource() + actualActualMockFactory!!.readText().normalizeSource() mustBe expectedActualFactory.normalizeSource() + actualExpectMockFactory!!.readText().normalizeSource() mustBe expectedExpectFactory.normalizeSource() + + // Round2 + // Given + val provider = ShallowSymbolProcessorProvider(spyProvider.lastProcessor) + val multiInterfaceInterface = SourceFile.kotlin( + "KMockMultiInterfaceArtifacts.kt", + actualIntermediateInterfaces.readText() + ) + val expectedMock = loadResource("/expected/commonGeneric/SpiedGenericMock.kt") + + // When + val compilerResultRound2 = compile( + provider, + isKmp = true, + kspArguments = mapOf( + "${KMOCK_PREFIX}allowInterfaces" to "true", + "${KMOCK_PREFIX}spiesOnly" to "true", + ), + sourceFiles = arrayOf(multiInterfaceInterface, rootInterface, nestedInterface, scopedInterface) + ) + val actualMock = resolveGenerated("CommonGenericMultiMock.kt") + + // Then + compilerResultRound2.exitCode mustBe KotlinCompilation.ExitCode.OK + actualMock isNot null + + actualMock!!.absolutePath.toString().endsWith( + "ksp/sources/kotlin/common/commonTest/kotlin/multi/CommonGenericMultiMock.kt" + ) mustBe true + actualMock.readText().normalizeSource() mustBe expectedMock.normalizeSource() + } } diff --git a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/KMockProcessorSpec.kt b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/KMockProcessorSpec.kt index b2157045..8674ad14 100644 --- a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/KMockProcessorSpec.kt +++ b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/KMockProcessorSpec.kt @@ -41,6 +41,7 @@ class KMockProcessorSpec { KMockProcessor( mockk(), fixture.fixture(), + fixture.fixture(), mockk(), mockk(), mockk(), @@ -98,6 +99,7 @@ class KMockProcessorSpec { // When val actual = KMockProcessor( mockk(), + false, true, mockk(relaxed = true), mockk(relaxed = true), @@ -171,6 +173,7 @@ class KMockProcessorSpec { // When val processor = KMockProcessor( mockk(), + false, true, mockk(relaxed = true), mockk(relaxed = true), @@ -262,6 +265,7 @@ class KMockProcessorSpec { // When KMockProcessor( mockk(), + false, true, codeGenerator, mockk(relaxed = true), @@ -278,7 +282,7 @@ class KMockProcessorSpec { verify(exactly = 1) { mockGenerator.writeCommonMocks( interfacesCommon, - Aggregated(emptyList(), emptyList(), emptyList()), + emptyList(), relaxer, ) } @@ -408,6 +412,7 @@ class KMockProcessorSpec { // When val processor = KMockProcessor( mockk(), + false, true, codeGenerator, interfaceBinder, @@ -426,7 +431,7 @@ class KMockProcessorSpec { verify(exactly = 1) { mockGenerator.writeCommonMocks( interfacesCommonRound1, - Aggregated(emptyList(), emptyList(), emptyList()), + emptyList(), relaxer ) } @@ -434,7 +439,7 @@ class KMockProcessorSpec { verify(exactly = 1) { mockGenerator.writeCommonMocks( interfacesCommonRound2, - Aggregated(illegal, multiInterfacesCommon, dependenciesMultiCommon), + multiInterfacesCommon, relaxer ) } @@ -547,6 +552,7 @@ class KMockProcessorSpec { KMockProcessor( mockk(), false, + false, codeGenerator, mockk(), mockGenerator, diff --git a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/MultiInterfaceBinderSpec.kt b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/MultiInterfaceBinderSpec.kt index 988c05ba..ec1e3151 100644 --- a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/MultiInterfaceBinderSpec.kt +++ b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/MultiInterfaceBinderSpec.kt @@ -15,6 +15,7 @@ class MultiInterfaceBinderSpec { @Test fun `It fulfils MultiInterfaceBinder`() { KMockMultiInterfaceBinder( + mockk(), mockk(), "any", mockk() diff --git a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/ParentFinderSpec.kt b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/ParentFinderSpec.kt index cabd80f3..75fc31a3 100644 --- a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/ParentFinderSpec.kt +++ b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/ParentFinderSpec.kt @@ -6,11 +6,9 @@ package tech.antibytes.kmock.processor.multi -import com.google.devtools.ksp.symbol.KSFile import io.mockk.mockk import org.junit.jupiter.api.Test import tech.antibytes.kmock.processor.ProcessorContract -import tech.antibytes.kmock.processor.ProcessorContract.Aggregated import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource import tech.antibytes.kmock.processor.ProcessorContract.TemplateSource import tech.antibytes.util.test.fixture.fixture @@ -50,20 +48,14 @@ class ParentFinderSpec { dependencies = emptyList() ) - val multiDependency: KSFile = mockk() - // When val parents = KMockParentFinder.find( templateSource = templateSource, - templateMultiSources = Aggregated( - illFormed = emptyList(), - extractedTemplates = listOf(templateMultiSource), - totalDependencies = listOf(multiDependency) - ), + templateMultiSources = listOf(templateMultiSource), ) // Then - parents mustBe emptyList() + parents mustBe null } @Test @@ -90,20 +82,14 @@ class ParentFinderSpec { dependencies = emptyList() ) - val multiDependency: KSFile = mockk() - // When val parents = KMockParentFinder.find( templateSource = templateSource, - templateMultiSources = Aggregated( - illFormed = emptyList(), - extractedTemplates = listOf(templateMultiSource), - totalDependencies = listOf(multiDependency) - ), + templateMultiSources = listOf(templateMultiSource), ) // Then - parents mustBe emptyList() + parents mustBe null } @Test @@ -130,20 +116,14 @@ class ParentFinderSpec { dependencies = emptyList() ) - val multiDependency: KSFile = mockk() - // When val parents = KMockParentFinder.find( templateSource = templateSource, - templateMultiSources = Aggregated( - illFormed = emptyList(), - extractedTemplates = listOf(templateMultiSource), - totalDependencies = listOf(multiDependency) - ), + templateMultiSources = listOf(templateMultiSource), ) // Then - parents mustBe emptyList() + parents mustBe null } @Test @@ -171,19 +151,13 @@ class ParentFinderSpec { dependencies = emptyList() ) - val multiDependency: KSFile = mockk() - // When val parents = KMockParentFinder.find( templateSource = templateSource, - templateMultiSources = Aggregated( - illFormed = emptyList(), - extractedTemplates = listOf(templateMultiSource), - totalDependencies = listOf(multiDependency) - ), + templateMultiSources = listOf(templateMultiSource), ) // Then - parents mustBe templateMultiSource.templates + parents mustBe templateMultiSource } } diff --git a/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/TemplateMultiSourceSpec.kt b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/TemplateMultiSourceSpec.kt new file mode 100644 index 00000000..ceb745be --- /dev/null +++ b/kmock-processor/src/test/kotlin/tech/antibytes/kmock/processor/multi/TemplateMultiSourceSpec.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package tech.antibytes.kmock.processor.multi + +import io.mockk.mockk +import org.junit.jupiter.api.Test +import tech.antibytes.kmock.processor.ProcessorContract.TemplateMultiSource +import tech.antibytes.util.test.fixture.fixture +import tech.antibytes.util.test.fixture.kotlinFixture +import tech.antibytes.util.test.mustBe + +class TemplateMultiSourceSpec { + private val fixture = kotlinFixture() + + @Test + fun `Given hasGenerics is called, it returns false if no actual generics had been captured`() { + // Given + val source = TemplateMultiSource( + indicator = fixture.fixture(), + templateName = fixture.fixture(), + packageName = fixture.fixture(), + dependencies = emptyList(), + templates = emptyList(), + generics = listOf(null, null, null, null) + ) + + // When + val actual = source.hasGenerics() + + // Then + actual mustBe false + } + + @Test + fun `Given hasGenerics is called, it returns true if at least one actual generics had been captured`() { + // Given + val source = TemplateMultiSource( + indicator = fixture.fixture(), + templateName = fixture.fixture(), + packageName = fixture.fixture(), + dependencies = emptyList(), + templates = emptyList(), + generics = listOf(null, null, mockk(), null) + ) + + // When + val actual = source.hasGenerics() + + // Then + actual mustBe true + } +} diff --git a/kmock-processor/src/test/resources/mock/expected/generic/Platform.kt b/kmock-processor/src/test/resources/mock/expected/generic/Platform.kt index cb0114c5..fc100db6 100644 --- a/kmock-processor/src/test/resources/mock/expected/generic/Platform.kt +++ b/kmock-processor/src/test/resources/mock/expected/generic/Platform.kt @@ -48,6 +48,10 @@ internal class PlatformMock( = ProxyFactory.createSyncFunProxy("mock.template.generic.PlatformMock#_fooWithAnys", collector = verifier, freeze = freeze) + public val _lol: KMockContract.SyncFunProxy>) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("mock.template.generic.PlatformMock#_lol", + collector = verifier, freeze = freeze) + public val _blaWithVoid: KMockContract.SyncFunProxy kotlin.Int> = ProxyFactory.createSyncFunProxy("mock.template.generic.PlatformMock#_blaWithVoid", collector = verifier, freeze = freeze) @@ -340,6 +344,10 @@ internal class PlatformMock( useUnitFunRelaxerIf(relaxUnitFun || relaxed) } + public override fun lol(vararg payload: Array): Unit = _lol.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + @Suppress("UNCHECKED_CAST") public override fun bla(): T = _blaWithVoid.invoke() as T @@ -590,6 +598,7 @@ internal class PlatformMock( _fooWithVoid.clear() _fooWithAny.clear() _fooWithAnys.clear() + _lol.clear() _blaWithVoid.clear() _blaWithInt.clear() _blaWithInts.clear() diff --git a/kmock-processor/src/test/resources/mock/expected/generic/SuperTyped.kt b/kmock-processor/src/test/resources/mock/expected/generic/SuperTyped.kt new file mode 100644 index 00000000..87b200c0 --- /dev/null +++ b/kmock-processor/src/test/resources/mock/expected/generic/SuperTyped.kt @@ -0,0 +1,149 @@ +package mock.template.generic + +import kotlin.Any +import kotlin.Array +import kotlin.Boolean +import kotlin.CharSequence +import kotlin.Comparable +import kotlin.Int +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.List +import tech.antibytes.kmock.KMockContract +import tech.antibytes.kmock.KMockContract.Collector +import tech.antibytes.kmock.proxy.NoopCollector +import tech.antibytes.kmock.proxy.ProxyFactory + +internal class SuperTypedMock( + verifier: KMockContract.Collector = NoopCollector, + @Suppress("UNUSED_PARAMETER") + spyOn: SuperTyped? = null, + freeze: Boolean = true, + @Suppress("unused") + private val relaxUnitFun: Boolean = false, + @Suppress("unused") + private val relaxed: Boolean = false, +) : SuperTyped where L : Any, L : Comparable { + public val _pptWithAnys: KMockContract.SyncFunProxy) -> kotlin.Unit> + = ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_pptWithAnys", + collector = verifier, freeze = freeze) + + public val _pptWithCharSequenceComparables: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_pptWithCharSequenceComparables", + collector = verifier, freeze = freeze) + + public val _pptWithComparables: KMockContract.SyncFunProxy>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_pptWithComparables", + collector = verifier, freeze = freeze) + + public val _pptWithAny: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_pptWithAny", collector + = verifier, freeze = freeze) + + public val _pptWithCharSequenceComparable: KMockContract.SyncFunProxy + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_pptWithCharSequenceComparable", + collector = verifier, freeze = freeze) + + public val _pptWithComparable: KMockContract.SyncFunProxy) -> + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_pptWithComparable", + collector = verifier, freeze = freeze) + + public val _lolWithAnyComparables: KMockContract.SyncFunProxy>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_lolWithAnyComparables", + collector = verifier, freeze = freeze) + + public val _lolWithAnys: KMockContract.SyncFunProxy) -> kotlin.Unit> + = ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_lolWithAnys", + collector = verifier, freeze = freeze) + + public val _lolWithAnyComparable: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_lolWithAnyComparable", + collector = verifier, freeze = freeze) + + public val _lolWithAny: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_lolWithAny", collector + = verifier, freeze = freeze) + + public val _buzz: KMockContract.SyncFunProxy>?>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_buzz", collector = + verifier, freeze = freeze) + + public val _narv: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("mock.template.generic.SuperTypedMock#_narv", collector = + verifier, freeze = freeze) + + public override fun ppt(vararg x: T): Unit = _pptWithAnys.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun ppt(vararg x: T): Unit where T : CharSequence, T : Comparable = + _pptWithCharSequenceComparables.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun > ppt(vararg x: T): Unit = _pptWithComparables.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun ppt(x: T): Unit = _pptWithAny.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun ppt(x: T): Unit where T : CharSequence, T : Comparable = + _pptWithCharSequenceComparable.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun > ppt(x: T): Unit = _pptWithComparable.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun , K> lol(arg: K, vararg x: T): Unit = + _lolWithAnyComparables.invoke(arg, x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun lol(vararg x: T): Unit = _lolWithAnys.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun , K> lol(arg: K, x: T): Unit = + _lolWithAnyComparable.invoke(arg, x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun lol(x: T): Unit = _lolWithAny.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun >> buzz(vararg payload: nulled?): Unit = + _buzz.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun narv(vararg x: L): Unit = _narv.invoke(x) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public fun _clearMock(): Unit { + _pptWithAnys.clear() + _pptWithCharSequenceComparables.clear() + _pptWithComparables.clear() + _pptWithAny.clear() + _pptWithCharSequenceComparable.clear() + _pptWithComparable.clear() + _lolWithAnyComparables.clear() + _lolWithAnys.clear() + _lolWithAnyComparable.clear() + _lolWithAny.clear() + _buzz.clear() + _narv.clear() + } +} diff --git a/kmock-processor/src/test/resources/mock/template/generic/Platform.kt b/kmock-processor/src/test/resources/mock/template/generic/Platform.kt index 393ecd20..d69a2e37 100644 --- a/kmock-processor/src/test/resources/mock/template/generic/Platform.kt +++ b/kmock-processor/src/test/resources/mock/template/generic/Platform.kt @@ -19,6 +19,8 @@ interface Platform where L : Any, L : Comparable, K : Any { fun foo(payload: T) fun foo(vararg payload: T) + fun lol(vararg payload: Array) + fun bla(): T fun bla(payload: T) fun bla(vararg payload: T) diff --git a/kmock-processor/src/test/resources/mock/template/generic/SuperTyped.kt b/kmock-processor/src/test/resources/mock/template/generic/SuperTyped.kt new file mode 100644 index 00000000..85207308 --- /dev/null +++ b/kmock-processor/src/test/resources/mock/template/generic/SuperTyped.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package mock.template.generic + +import tech.antibytes.kmock.Mock + +@Mock(SuperTyped::class) +interface SuperTyped : Parent where L : Any, L : Comparable, K : Any + +interface Parent where L : Any, L : Comparable, K : Any { + fun ppt(vararg x: T) + fun ppt(vararg x: T) where T : CharSequence, T : Comparable + fun ppt(vararg x: T) where T : Comparable + fun lol(arg: K, vararg x: T) where T : Comparable + fun lol(vararg x: T) where T : K + + fun >> buzz(vararg payload: nulled?) + + fun ppt(x: T) + fun ppt(x: T) where T : CharSequence, T : Comparable + fun ppt(x: T) where T : Comparable + fun lol(arg: K, x: T) where T : Comparable + fun lol(x: T) where T : K + + fun narv(vararg x: L) +} diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericActualFactory.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericActualFactory.kt new file mode 100644 index 00000000..6acafc75 --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericActualFactory.kt @@ -0,0 +1,88 @@ +@file:Suppress("UNUSED_PARAMETER", "UNUSED_EXPRESSION") + +package multi + +import kotlin.Any +import kotlin.Boolean +import kotlin.Comparable +import kotlin.Suppress +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.KMockContract +import tech.antibytes.kmock.KMockContract.Collector + +private inline fun getMockInstance( + spyOn: SpyOn?, + verifier: KMockContract.Collector, + relaxed: Boolean, + relaxUnitFun: Boolean, + freeze: Boolean, +): Mock = when (Mock::class) { + else -> throw RuntimeException("Unknown Interface ${Mock::class.simpleName}.") +} + +internal actual inline fun kmock( + verifier: KMockContract.Collector, + relaxed: Boolean, + relaxUnitFun: Boolean, + freeze: Boolean, +): Mock = getMockInstance( + spyOn = null, + verifier = verifier, + relaxed = relaxed, + relaxUnitFun = relaxUnitFun, + freeze = freeze, +) + +private inline fun getMockInstance( + spyOn: SpyOn?, + verifier: KMockContract.Collector, + relaxed: Boolean, + relaxUnitFun: Boolean, + freeze: Boolean, + templateType0: kotlin.reflect.KClass>, + templateType1: kotlin.reflect.KClass>, + templateType2: kotlin.reflect.KClass>, +): Mock where SpyOn : Generic1, SpyOn : +Generic2, SpyOn : + GenericCommonContract.Generic3, KMockTypeParameter1 : + Any, KMockTypeParameter1 : Comparable, KMockTypeParameter3 : Any, + KMockTypeParameter3 : Comparable = if (Mock::class == + multi.CommonGenericMultiMock::class) { + multi.CommonGenericMultiMock(verifier = verifier, freeze = freeze, spyOn = spyOn as SpyOn?) as + Mock +} else { + throw RuntimeException("Unknown Interface ${Mock::class.simpleName}.")} + +internal actual inline fun kmock( + verifier: KMockContract.Collector, + relaxed: Boolean, + relaxUnitFun: Boolean, + freeze: Boolean, + templateType0: kotlin.reflect.KClass>, + templateType1: kotlin.reflect.KClass>, + templateType2: kotlin.reflect.KClass>, +): Mock where Mock : Generic1, Mock : +Generic2, Mock : + GenericCommonContract.Generic3, KMockTypeParameter1 : + Any, KMockTypeParameter1 : Comparable, KMockTypeParameter3 : Any, + KMockTypeParameter3 : Comparable = getMockInstance( + spyOn = null, + verifier = verifier, + relaxed = relaxed, + relaxUnitFun = relaxUnitFun, + freeze = freeze, + templateType0 = templateType0, + templateType1 = templateType1, + templateType2 = templateType2, +) diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericExpectFactory.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericExpectFactory.kt new file mode 100644 index 00000000..62873948 --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericExpectFactory.kt @@ -0,0 +1,39 @@ +@file:Suppress("UNUSED_PARAMETER", "UNUSED_EXPRESSION") + +package multi + +import kotlin.Any +import kotlin.Boolean +import kotlin.Comparable +import kotlin.Suppress +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.KMockContract +import tech.antibytes.kmock.KMockContract.Collector +import tech.antibytes.kmock.proxy.NoopCollector + +internal expect inline fun kmock( + verifier: KMockContract.Collector = NoopCollector, + relaxed: Boolean = false, + relaxUnitFun: Boolean = false, + freeze: Boolean = true, +): Mock + +internal expect inline fun kmock( + verifier: KMockContract.Collector = NoopCollector, + relaxed: Boolean = false, + relaxUnitFun: Boolean = false, + freeze: Boolean = true, + templateType0: kotlin.reflect.KClass>, + templateType1: kotlin.reflect.KClass>, + templateType2: kotlin.reflect.KClass>, +): Mock where Mock : Generic1, Mock : +Generic2, Mock : + GenericCommonContract.Generic3, KMockTypeParameter1 : + Any, KMockTypeParameter1 : Comparable, KMockTypeParameter3 : Any, + KMockTypeParameter3 : Comparable diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericInterface.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericInterface.kt new file mode 100644 index 00000000..941ab56e --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericInterface.kt @@ -0,0 +1,17 @@ +package multi + +import kotlin.Any +import kotlin.Comparable +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.MockCommon + +@MockCommon(CommonGenericMulti::class) +private interface CommonGenericMulti : + Generic1, + Generic2, + GenericCommonContract.Generic3 where +KMockTypeParameter1 : Any, KMockTypeParameter1 : Comparable, +KMockTypeParameter3 : Any, KMockTypeParameter3 : Comparable diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericMock.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericMock.kt new file mode 100644 index 00000000..46b37c0c --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/GenericMock.kt @@ -0,0 +1,545 @@ +package multi + +import kotlin.Any +import kotlin.Array +import kotlin.Boolean +import kotlin.Char +import kotlin.CharSequence +import kotlin.Comparable +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.sequences.Sequence +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.SomeGeneric +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.KMockContract +import tech.antibytes.kmock.KMockContract.Collector +import tech.antibytes.kmock.proxy.NoopCollector +import tech.antibytes.kmock.proxy.ProxyFactory + +internal class CommonGenericMultiMock( + verifier: KMockContract.Collector = NoopCollector, + @Suppress("UNUSED_PARAMETER") + spyOn: MultiMock? = null, + freeze: Boolean = true, + @Suppress("unused") + private val relaxUnitFun: Boolean = false, + @Suppress("unused") + private val relaxed: Boolean = false, +) : Generic1, + Generic2, + GenericCommonContract.Generic3 where +KMockTypeParameter1 : Any, KMockTypeParameter1 : Comparable, +KMockTypeParameter3 : Any, KMockTypeParameter3 : Comparable, MultiMock : +Generic1, MultiMock : +Generic2, MultiMock : +GenericCommonContract.Generic3 { + public override var template: KMockTypeParameter1 + get() = _template.onGet() + set(`value`) = _template.onSet(value) + + public val _template: KMockContract.PropertyProxy = + ProxyFactory.createPropertyProxy("multi.CommonGenericMultiMock#_template", collector = + verifier, freeze = freeze) + + public override val lol: KMockTypeParameter2 + get() = _lol.onGet() + + public val _lol: KMockContract.PropertyProxy = + ProxyFactory.createPropertyProxy("multi.CommonGenericMultiMock#_lol", collector = verifier, + freeze = freeze) + + public val _fooWithVoid: KMockContract.SyncFunProxy kotlin.Any?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_fooWithVoid", collector = + verifier, freeze = freeze) + + public val _fooWithAny: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_fooWithAny", collector = + verifier, freeze = freeze) + + public val _fooWithAnys: KMockContract.SyncFunProxy) -> kotlin.Unit> + = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_fooWithAnys", collector = + verifier, freeze = freeze) + + public val _blaWithVoid: KMockContract.SyncFunProxy kotlin.Int> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blaWithVoid", collector = + verifier, freeze = freeze) + + public val _blaWithInt: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blaWithInt", collector = + verifier, freeze = freeze) + + public val _blaWithInts: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blaWithInts", collector = + verifier, freeze = freeze) + + public val _barWithVoid: + KMockContract.SyncFunProxy>, () -> + kotlin.collections.List>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_barWithVoid", collector = + verifier, freeze = freeze) + + public val _barWithList: + KMockContract.SyncFunProxy>) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_barWithList", + collector = verifier, freeze = freeze) + + public val _barWithLists: KMockContract.SyncFunProxy>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_barWithLists", collector = + verifier, freeze = freeze) + + public val _blubbWithVoid: + KMockContract.SyncFunProxy>, () -> + kotlin.collections.List>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blubbWithVoid", collector = + verifier, freeze = freeze) + + public val _blubbWithList: + KMockContract.SyncFunProxy>) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blubbWithList", + collector = verifier, freeze = freeze) + + public val _blubbWithLists: KMockContract.SyncFunProxy>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blubbWithLists", collector = + verifier, freeze = freeze) + + public val _bussWithVoid: + KMockContract.SyncFunProxy>?, () -> + kotlin.collections.List>?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bussWithVoid", collector = + verifier, freeze = freeze) + + public val _bussWithList: + KMockContract.SyncFunProxy>?) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bussWithList", + collector = verifier, freeze = freeze) + + public val _bussWithLists: KMockContract.SyncFunProxy>?>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bussWithLists", collector = + verifier, freeze = freeze) + + public val _bossWithVoid: + KMockContract.SyncFunProxy?>, () -> + kotlin.collections.List?>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bossWithVoid", collector = + verifier, freeze = freeze) + + public val _bossWithList: + KMockContract.SyncFunProxy?>) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bossWithList", + collector = verifier, freeze = freeze) + + public val _bossWithLists: KMockContract.SyncFunProxy?>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bossWithLists", collector = + verifier, freeze = freeze) + + public val _buzzWithVoid: + KMockContract.SyncFunProxy>?, () -> + kotlin.collections.List>?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_buzzWithVoid", collector = + verifier, freeze = freeze) + + public val _buzzWithList: + KMockContract.SyncFunProxy>?) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_buzzWithList", + collector = verifier, freeze = freeze) + + public val _buzzWithLists: KMockContract.SyncFunProxy>?>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_buzzWithLists", collector = + verifier, freeze = freeze) + + public val _ozzWithVoid: KMockContract.SyncFunProxy + KMockTypeParameter1> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ozzWithVoid", collector = + verifier, freeze = freeze) + + public val _ozzWithKMockTypeParameter3: KMockContract.SyncFunProxy + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ozzWithKMockTypeParameter3", + collector = verifier, freeze = freeze) + + public val _ozzWithKMockTypeParameter3s: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ozzWithKMockTypeParameter3s", + collector = verifier, freeze = freeze) + + public val _brassWithVoid: + KMockContract.SyncFunProxy>>, () -> + kotlin.Comparable>>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_brassWithVoid", collector = + verifier, freeze = freeze) + + public val _brassWithComparable: + KMockContract.SyncFunProxy>>) -> + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_brassWithComparable", collector + = verifier, freeze = freeze) + + public val _brassWithComparables: KMockContract.SyncFunProxy>>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_brassWithComparables", + collector = verifier, freeze = freeze) + + public val _blissWithVoid: + KMockContract.SyncFunProxy>>?, () -> + kotlin.Comparable>>?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blissWithVoid", collector = + verifier, freeze = freeze) + + public val _blissWithComparable: + KMockContract.SyncFunProxy>>?) -> + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blissWithComparable", collector + = verifier, freeze = freeze) + + public val _blissWithComparables: KMockContract.SyncFunProxy>>?>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blissWithComparables", + collector = verifier, freeze = freeze) + + public val _lossWithVoid: KMockContract.SyncFunProxy, () -> kotlin.collections.Map> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lossWithVoid", collector = + verifier, freeze = freeze) + + public val _lossWithMap: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lossWithMap", collector = + verifier, freeze = freeze) + + public val _lossWithMaps: KMockContract.SyncFunProxy>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lossWithMaps", collector = + verifier, freeze = freeze) + + public val _uzz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_uzz", collector = verifier, + freeze = freeze) + + public val _lzz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lzz", collector = verifier, + freeze = freeze) + + public val _tzz: KMockContract.SyncFunProxy kotlin.Any?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_tzz", collector = verifier, + freeze = freeze) + + public val _rzz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_rzz", collector = verifier, + freeze = freeze) + + public val _izz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_izz", collector = verifier, + freeze = freeze) + + public val _ossWithAny: KMockContract.SyncFunProxy kotlin.Any?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ossWithAny", collector = + verifier, freeze = freeze) + + public val _ossWithAnyAny: KMockContract.SyncFunProxy + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ossWithAnyAny", + collector = verifier, freeze = freeze) + + public val _ossWithAnyAnys: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ossWithAnyAnys", collector = + verifier, freeze = freeze) + + public val _kss: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_kss", collector = verifier, + freeze = freeze) + + public val _iss: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_iss", collector = verifier, + freeze = freeze) + + public val _pss: + KMockContract.SyncFunProxy, (multi.template.commonGeneric.SomeGeneric) -> + multi.template.commonGeneric.SomeGeneric> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_pss", collector = verifier, + freeze = freeze) + + public val _xssWithAny: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_xssWithAny", collector = + verifier, freeze = freeze) + + public val _xssWithAnySequenceCharSequence: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_xssWithAnySequenceCharSequence", + collector = verifier, freeze = freeze) + + public val _doSomething: KMockContract.SyncFunProxy + KMockTypeParameter5> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_doSomething", collector = + verifier, freeze = freeze) + + public val _compareTo: + KMockContract.SyncFunProxy) -> kotlin.Int> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_compareTo", collector = + verifier, freeze = freeze) + + @Suppress("UNCHECKED_CAST") + public override fun foo(): T = _fooWithVoid.invoke() as T + + public override fun foo(payload: T): Unit = _fooWithAny.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun foo(vararg payload: T): Unit = _fooWithAnys.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun bla(): T = _blaWithVoid.invoke() as T + + public override fun bla(payload: T): Unit = _blaWithInt.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun bla(vararg payload: T): Unit = _blaWithInts.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun >> bar(): T = _barWithVoid.invoke() as T + + public override fun >> bar(payload: T): Unit = _barWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun >> bar(vararg payload: T): Unit = + _barWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun >> blubb(): T = _blubbWithVoid.invoke() as T + + public override fun >> blubb(payload: T): Unit = + _blubbWithList.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun >> blubb(vararg payload: T): Unit = + _blubbWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun >?> buss(): T = _bussWithVoid.invoke() as T + + public override fun >?> buss(payload: T): Unit = _bussWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun >?> buss(vararg payload: T): Unit = + _bussWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun ?>> boss(): T = _bossWithVoid.invoke() as T + + public override fun ?>> boss(payload: T): Unit = _bossWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun ?>> boss(vararg payload: T): Unit = + _bossWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun >> buzz(): T? = _buzzWithVoid.invoke() as T? + + public override fun >> buzz(payload: T?): Unit = _buzzWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun >> buzz(vararg payload: T?): Unit = + _buzzWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun ozz(): T = _ozzWithVoid.invoke() as T + + public override fun ozz(payload: T): Unit = + _ozzWithKMockTypeParameter3.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun ozz(vararg payload: T): Unit = + _ozzWithKMockTypeParameter3s.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun >>> brass(): T = _brassWithVoid.invoke() as T + + public override fun >>> brass(payload: T): Unit = + _brassWithComparable.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun >>> brass(vararg payload: T): Unit = + _brassWithComparables.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun >>?> bliss(): T = _blissWithVoid.invoke() as T + + public override fun >>?> bliss(payload: T): Unit = + _blissWithComparable.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun >>?> bliss(vararg payload: T): Unit = + _blissWithComparables.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun > loss(): T = _lossWithVoid.invoke() as T + + public override fun > loss(payload: T): Unit = + _lossWithMap.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun > loss(vararg payload: T): Unit = + _lossWithMaps.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun uzz(): T where T : SomeGeneric, T : List = _uzz.invoke() + as T + + @Suppress("UNCHECKED_CAST") + public override fun lzz(): T where T : SomeGeneric, T : List? = _lzz.invoke() + as T + + @Suppress("UNCHECKED_CAST") + public override fun tzz(): T where T : SomeGeneric?, T : List? = _tzz.invoke() + as T + + @Suppress("UNCHECKED_CAST") + public override fun rzz(): T where T : SomeGeneric, T : Map = + _rzz.invoke() as T + + @Suppress("UNCHECKED_CAST") + public override fun izz(): T where T : SomeGeneric, T : Comparable>> = + _izz.invoke() as T + + @Suppress("UNCHECKED_CAST") + public override fun oss(arg0: T): R = _ossWithAny.invoke(arg0) as R + + public override fun oss(arg0: T, arg1: R): Unit = _ossWithAnyAny.invoke(arg0, arg1) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun oss(arg0: R, vararg arg1: T): Unit = _ossWithAnyAnys.invoke(arg0, + arg1) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + @Suppress("UNCHECKED_CAST") + public override fun kss(arg0: T): R where R : SomeGeneric, R : + Comparable>> = _kss.invoke(arg0) as R + + @Suppress("UNCHECKED_CAST") + public override fun iss(arg0: T): R where R : SomeGeneric, R : + Comparable>> = _iss.invoke(arg0) as R + + @Suppress("UNCHECKED_CAST") + public override fun > pss(arg0: T): R = _pss.invoke(arg0) as + R + + @Suppress("UNCHECKED_CAST") + public override fun xss(arg0: T): R where R : Sequence, R : CharSequence = + _xssWithAny.invoke(arg0) as R + + public override fun xss(arg0: T, arg1: R): Unit where R : Sequence, R : CharSequence + = _xssWithAnySequenceCharSequence.invoke(arg0, arg1) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + } + + public override fun doSomething(arg: KMockTypeParameter4): KMockTypeParameter5 = + _doSomething.invoke(arg) + + public override + fun compareTo(other: GenericCommonContract.Generic3): + Int = _compareTo.invoke(other) + + public fun _clearMock(): Unit { + _template.clear() + _lol.clear() + _fooWithVoid.clear() + _fooWithAny.clear() + _fooWithAnys.clear() + _blaWithVoid.clear() + _blaWithInt.clear() + _blaWithInts.clear() + _barWithVoid.clear() + _barWithList.clear() + _barWithLists.clear() + _blubbWithVoid.clear() + _blubbWithList.clear() + _blubbWithLists.clear() + _bussWithVoid.clear() + _bussWithList.clear() + _bussWithLists.clear() + _bossWithVoid.clear() + _bossWithList.clear() + _bossWithLists.clear() + _buzzWithVoid.clear() + _buzzWithList.clear() + _buzzWithLists.clear() + _ozzWithVoid.clear() + _ozzWithKMockTypeParameter3.clear() + _ozzWithKMockTypeParameter3s.clear() + _brassWithVoid.clear() + _brassWithComparable.clear() + _brassWithComparables.clear() + _blissWithVoid.clear() + _blissWithComparable.clear() + _blissWithComparables.clear() + _lossWithVoid.clear() + _lossWithMap.clear() + _lossWithMaps.clear() + _uzz.clear() + _lzz.clear() + _tzz.clear() + _rzz.clear() + _izz.clear() + _ossWithAny.clear() + _ossWithAnyAny.clear() + _ossWithAnyAnys.clear() + _kss.clear() + _iss.clear() + _pss.clear() + _xssWithAny.clear() + _xssWithAnySequenceCharSequence.clear() + _doSomething.clear() + _compareTo.clear() + } +} diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericActualFactory.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericActualFactory.kt new file mode 100644 index 00000000..40c23101 --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericActualFactory.kt @@ -0,0 +1,87 @@ +@file:Suppress("UNUSED_PARAMETER", "UNUSED_EXPRESSION") + +package multi + +import kotlin.Any +import kotlin.Boolean +import kotlin.Comparable +import kotlin.Suppress +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.KMockContract +import tech.antibytes.kmock.KMockContract.Collector + +private inline fun getMockInstance( + spyOn: SpyOn?, + verifier: KMockContract.Collector, + relaxed: Boolean, + relaxUnitFun: Boolean, + freeze: Boolean, +): Mock = when (Mock::class) { + else -> throw RuntimeException("Unknown Interface ${Mock::class.simpleName}.") +} + +internal actual inline fun kspy( + spyOn: SpyOn, + verifier: KMockContract.Collector, + freeze: Boolean, +): Mock = getMockInstance( + spyOn = spyOn, + verifier = verifier, + relaxed = false, + relaxUnitFun = false, + freeze = freeze, +) + +private inline fun getMockInstance( + spyOn: SpyOn?, + verifier: KMockContract.Collector, + relaxed: Boolean, + relaxUnitFun: Boolean, + freeze: Boolean, + templateType0: kotlin.reflect.KClass>, + templateType1: kotlin.reflect.KClass>, + templateType2: kotlin.reflect.KClass>, +): Mock where SpyOn : Generic1, SpyOn : +Generic2, SpyOn : + GenericCommonContract.Generic3, KMockTypeParameter1 : + Any, KMockTypeParameter1 : Comparable, KMockTypeParameter3 : Any, + KMockTypeParameter3 : Comparable = if (Mock::class == + multi.CommonGenericMultiMock::class) { + multi.CommonGenericMultiMock(verifier = verifier, freeze = freeze, spyOn = spyOn as SpyOn?) as + Mock +} else { + throw RuntimeException("Unknown Interface ${Mock::class.simpleName}.")} + +internal actual inline fun kspy( + spyOn: SpyOn, + verifier: KMockContract.Collector, + freeze: Boolean, + templateType0: kotlin.reflect.KClass>, + templateType1: kotlin.reflect.KClass>, + templateType2: kotlin.reflect.KClass>, +): Mock where SpyOn : Generic1, SpyOn : +Generic2, SpyOn : + GenericCommonContract.Generic3, KMockTypeParameter1 : + Any, KMockTypeParameter1 : Comparable, KMockTypeParameter3 : Any, + KMockTypeParameter3 : Comparable = getMockInstance( + spyOn = spyOn, + verifier = verifier, + relaxed = false, + relaxUnitFun = false, + freeze = freeze, + templateType0 = templateType0, + templateType1 = templateType1, + templateType2 = templateType2, +) diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericExpectFactory.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericExpectFactory.kt new file mode 100644 index 00000000..039c75c7 --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericExpectFactory.kt @@ -0,0 +1,38 @@ +@file:Suppress("UNUSED_PARAMETER", "UNUSED_EXPRESSION") + +package multi + +import kotlin.Any +import kotlin.Boolean +import kotlin.Comparable +import kotlin.Suppress +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.KMockContract +import tech.antibytes.kmock.KMockContract.Collector +import tech.antibytes.kmock.proxy.NoopCollector + +internal expect inline fun kspy( + spyOn: SpyOn, + verifier: KMockContract.Collector = NoopCollector, + freeze: Boolean = true, +): Mock + +internal expect inline fun kspy( + spyOn: SpyOn, + verifier: KMockContract.Collector = NoopCollector, + freeze: Boolean = true, + templateType0: kotlin.reflect.KClass>, + templateType1: kotlin.reflect.KClass>, + templateType2: kotlin.reflect.KClass>, +): Mock where SpyOn : Generic1, SpyOn : +Generic2, SpyOn : + GenericCommonContract.Generic3, KMockTypeParameter1 : + Any, KMockTypeParameter1 : Comparable, KMockTypeParameter3 : Any, + KMockTypeParameter3 : Comparable diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericInterface.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericInterface.kt new file mode 100644 index 00000000..941ab56e --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericInterface.kt @@ -0,0 +1,17 @@ +package multi + +import kotlin.Any +import kotlin.Comparable +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.MockCommon + +@MockCommon(CommonGenericMulti::class) +private interface CommonGenericMulti : + Generic1, + Generic2, + GenericCommonContract.Generic3 where +KMockTypeParameter1 : Any, KMockTypeParameter1 : Comparable, +KMockTypeParameter3 : Any, KMockTypeParameter3 : Comparable diff --git a/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericMock.kt b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericMock.kt new file mode 100644 index 00000000..1703ab38 --- /dev/null +++ b/kmock-processor/src/test/resources/multi/expected/commonGeneric/SpiedGenericMock.kt @@ -0,0 +1,657 @@ +package multi + +import kotlin.Any +import kotlin.Array +import kotlin.Boolean +import kotlin.Char +import kotlin.CharSequence +import kotlin.Comparable +import kotlin.Int +import kotlin.String +import kotlin.Suppress +import kotlin.Unit +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.sequences.Sequence +import multi.template.commonGeneric.Generic1 +import multi.template.commonGeneric.GenericCommonContract +import multi.template.commonGeneric.SomeGeneric +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.KMockContract +import tech.antibytes.kmock.KMockContract.Collector +import tech.antibytes.kmock.proxy.NoopCollector +import tech.antibytes.kmock.proxy.ProxyFactory + +internal class CommonGenericMultiMock( + verifier: KMockContract.Collector = NoopCollector, + @Suppress("UNUSED_PARAMETER") + spyOn: MultiMock? = null, + freeze: Boolean = true, + @Suppress("unused") + private val relaxUnitFun: Boolean = false, + @Suppress("unused") + private val relaxed: Boolean = false, +) : Generic1, + Generic2, + GenericCommonContract.Generic3 where +KMockTypeParameter1 : Any, KMockTypeParameter1 : Comparable, +KMockTypeParameter3 : Any, KMockTypeParameter3 : Comparable, MultiMock : +Generic1, MultiMock : +Generic2, MultiMock : +GenericCommonContract.Generic3 { + private val __spyOn: MultiMock? = spyOn + + public override var template: KMockTypeParameter1 + get() = _template.onGet { + useSpyIf(__spyOn) { __spyOn!!.template } + } + set(`value`) = _template.onSet(value) { + useSpyIf(__spyOn) { __spyOn!!.template = value } + } + + public val _template: KMockContract.PropertyProxy = + ProxyFactory.createPropertyProxy("multi.CommonGenericMultiMock#_template", collector = + verifier, freeze = freeze) + + public override val lol: KMockTypeParameter2 + get() = _lol.onGet { + useSpyIf(__spyOn) { __spyOn!!.lol } + } + + public val _lol: KMockContract.PropertyProxy = + ProxyFactory.createPropertyProxy("multi.CommonGenericMultiMock#_lol", collector = verifier, + freeze = freeze) + + public val _fooWithVoid: KMockContract.SyncFunProxy kotlin.Any?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_fooWithVoid", collector = + verifier, freeze = freeze) + + public val _fooWithAny: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_fooWithAny", collector = + verifier, freeze = freeze) + + public val _fooWithAnys: KMockContract.SyncFunProxy) -> kotlin.Unit> + = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_fooWithAnys", collector = + verifier, freeze = freeze) + + public val _blaWithVoid: KMockContract.SyncFunProxy kotlin.Int> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blaWithVoid", collector = + verifier, freeze = freeze) + + public val _blaWithInt: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blaWithInt", collector = + verifier, freeze = freeze) + + public val _blaWithInts: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blaWithInts", collector = + verifier, freeze = freeze) + + public val _barWithVoid: + KMockContract.SyncFunProxy>, () -> + kotlin.collections.List>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_barWithVoid", collector = + verifier, freeze = freeze) + + public val _barWithList: + KMockContract.SyncFunProxy>) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_barWithList", + collector = verifier, freeze = freeze) + + public val _barWithLists: KMockContract.SyncFunProxy>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_barWithLists", collector = + verifier, freeze = freeze) + + public val _blubbWithVoid: + KMockContract.SyncFunProxy>, () -> + kotlin.collections.List>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blubbWithVoid", collector = + verifier, freeze = freeze) + + public val _blubbWithList: + KMockContract.SyncFunProxy>) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blubbWithList", + collector = verifier, freeze = freeze) + + public val _blubbWithLists: KMockContract.SyncFunProxy>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blubbWithLists", collector = + verifier, freeze = freeze) + + public val _bussWithVoid: + KMockContract.SyncFunProxy>?, () -> + kotlin.collections.List>?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bussWithVoid", collector = + verifier, freeze = freeze) + + public val _bussWithList: + KMockContract.SyncFunProxy>?) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bussWithList", + collector = verifier, freeze = freeze) + + public val _bussWithLists: KMockContract.SyncFunProxy>?>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bussWithLists", collector = + verifier, freeze = freeze) + + public val _bossWithVoid: + KMockContract.SyncFunProxy?>, () -> + kotlin.collections.List?>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bossWithVoid", collector = + verifier, freeze = freeze) + + public val _bossWithList: + KMockContract.SyncFunProxy?>) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bossWithList", + collector = verifier, freeze = freeze) + + public val _bossWithLists: KMockContract.SyncFunProxy?>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_bossWithLists", collector = + verifier, freeze = freeze) + + public val _buzzWithVoid: + KMockContract.SyncFunProxy>?, () -> + kotlin.collections.List>?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_buzzWithVoid", collector = + verifier, freeze = freeze) + + public val _buzzWithList: + KMockContract.SyncFunProxy>?) -> + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_buzzWithList", + collector = verifier, freeze = freeze) + + public val _buzzWithLists: KMockContract.SyncFunProxy>?>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_buzzWithLists", collector = + verifier, freeze = freeze) + + public val _ozzWithVoid: KMockContract.SyncFunProxy + KMockTypeParameter1> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ozzWithVoid", collector = + verifier, freeze = freeze) + + public val _ozzWithKMockTypeParameter3: KMockContract.SyncFunProxy + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ozzWithKMockTypeParameter3", + collector = verifier, freeze = freeze) + + public val _ozzWithKMockTypeParameter3s: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ozzWithKMockTypeParameter3s", + collector = verifier, freeze = freeze) + + public val _brassWithVoid: + KMockContract.SyncFunProxy>>, () -> + kotlin.Comparable>>> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_brassWithVoid", collector = + verifier, freeze = freeze) + + public val _brassWithComparable: + KMockContract.SyncFunProxy>>) -> + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_brassWithComparable", collector + = verifier, freeze = freeze) + + public val _brassWithComparables: KMockContract.SyncFunProxy>>>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_brassWithComparables", + collector = verifier, freeze = freeze) + + public val _blissWithVoid: + KMockContract.SyncFunProxy>>?, () -> + kotlin.Comparable>>?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blissWithVoid", collector = + verifier, freeze = freeze) + + public val _blissWithComparable: + KMockContract.SyncFunProxy>>?) -> + kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blissWithComparable", collector + = verifier, freeze = freeze) + + public val _blissWithComparables: KMockContract.SyncFunProxy>>?>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_blissWithComparables", + collector = verifier, freeze = freeze) + + public val _lossWithVoid: KMockContract.SyncFunProxy, () -> kotlin.collections.Map> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lossWithVoid", collector = + verifier, freeze = freeze) + + public val _lossWithMap: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lossWithMap", collector = + verifier, freeze = freeze) + + public val _lossWithMaps: KMockContract.SyncFunProxy>) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lossWithMaps", collector = + verifier, freeze = freeze) + + public val _uzz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_uzz", collector = verifier, + freeze = freeze) + + public val _lzz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_lzz", collector = verifier, + freeze = freeze) + + public val _tzz: KMockContract.SyncFunProxy kotlin.Any?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_tzz", collector = verifier, + freeze = freeze) + + public val _rzz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_rzz", collector = verifier, + freeze = freeze) + + public val _izz: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_izz", collector = verifier, + freeze = freeze) + + public val _ossWithAny: KMockContract.SyncFunProxy kotlin.Any?> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ossWithAny", collector = + verifier, freeze = freeze) + + public val _ossWithAnyAny: KMockContract.SyncFunProxy + kotlin.Unit> = ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ossWithAnyAny", + collector = verifier, freeze = freeze) + + public val _ossWithAnyAnys: KMockContract.SyncFunProxy) -> kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_ossWithAnyAnys", collector = + verifier, freeze = freeze) + + public val _kss: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_kss", collector = verifier, + freeze = freeze) + + public val _iss: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_iss", collector = verifier, + freeze = freeze) + + public val _pss: + KMockContract.SyncFunProxy, (multi.template.commonGeneric.SomeGeneric) -> + multi.template.commonGeneric.SomeGeneric> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_pss", collector = verifier, + freeze = freeze) + + public val _xssWithAny: KMockContract.SyncFunProxy kotlin.Any> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_xssWithAny", collector = + verifier, freeze = freeze) + + public val _xssWithAnySequenceCharSequence: KMockContract.SyncFunProxy kotlin.Unit> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_xssWithAnySequenceCharSequence", + collector = verifier, freeze = freeze) + + public val _doSomething: KMockContract.SyncFunProxy + KMockTypeParameter5> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_doSomething", collector = + verifier, freeze = freeze) + + public val _compareTo: + KMockContract.SyncFunProxy) -> kotlin.Int> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_compareTo", collector = + verifier, freeze = freeze) + + public val _toString: KMockContract.SyncFunProxy kotlin.String> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_toString", collector = + verifier, freeze = freeze, ignorableForVerification = true) + + public val _equals: KMockContract.SyncFunProxy kotlin.Boolean> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_equals", collector = verifier, + freeze = freeze, ignorableForVerification = true) + + public val _hashCode: KMockContract.SyncFunProxy kotlin.Int> = + ProxyFactory.createSyncFunProxy("multi.CommonGenericMultiMock#_hashCode", collector = + verifier, freeze = freeze, ignorableForVerification = true) + + @Suppress("UNCHECKED_CAST") + public override fun foo(): T = _fooWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.foo() } + } as T + + public override fun foo(payload: T): Unit = _fooWithAny.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.foo(payload) } + } + + public override fun foo(vararg payload: T): Unit = _fooWithAnys.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.foo(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun bla(): T = _blaWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.bla() } + } as T + + public override fun bla(payload: T): Unit = _blaWithInt.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.bla(payload) } + } + + public override fun bla(vararg payload: T): Unit = _blaWithInts.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.bla(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun >> bar(): T = _barWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.bar() } + } as T + + public override fun >> bar(payload: T): Unit = _barWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.bar(payload) } + } + + public override fun >> bar(vararg payload: T): Unit = + _barWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.bar(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun >> blubb(): T = _blubbWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.blubb() } + } as T + + public override fun >> blubb(payload: T): Unit = + _blubbWithList.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.blubb(payload) } + } + + public override fun >> blubb(vararg payload: T): Unit = + _blubbWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.blubb(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun >?> buss(): T = _bussWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.buss() } + } as T + + public override fun >?> buss(payload: T): Unit = _bussWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.buss(payload) } + } + + public override fun >?> buss(vararg payload: T): Unit = + _bussWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.buss(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun ?>> boss(): T = _bossWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.boss() } + } as T + + public override fun ?>> boss(payload: T): Unit = _bossWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.boss(payload) } + } + + public override fun ?>> boss(vararg payload: T): Unit = + _bossWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.boss(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun >> buzz(): T? = _buzzWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.buzz() } + } as T? + + public override fun >> buzz(payload: T?): Unit = _buzzWithList.invoke(payload) + { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.buzz(payload) } + } + + public override fun >> buzz(vararg payload: T?): Unit = + _buzzWithLists.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.buzz(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun ozz(): T = _ozzWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.ozz() } + } as T + + public override fun ozz(payload: T): Unit = + _ozzWithKMockTypeParameter3.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.ozz(payload) } + } + + public override fun ozz(vararg payload: T): Unit = + _ozzWithKMockTypeParameter3s.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.ozz(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun >>> brass(): T = _brassWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.brass() } + } as T + + public override fun >>> brass(payload: T): Unit = + _brassWithComparable.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.brass(payload) } + } + + public override fun >>> brass(vararg payload: T): Unit = + _brassWithComparables.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.brass(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun >>?> bliss(): T = _blissWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.bliss() } + } as T + + public override fun >>?> bliss(payload: T): Unit = + _blissWithComparable.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.bliss(payload) } + } + + public override fun >>?> bliss(vararg payload: T): Unit = + _blissWithComparables.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.bliss(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun > loss(): T = _lossWithVoid.invoke() { + useSpyIf(__spyOn) { __spyOn!!.loss() } + } as T + + public override fun > loss(payload: T): Unit = + _lossWithMap.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.loss(payload) } + } + + public override fun > loss(vararg payload: T): Unit = + _lossWithMaps.invoke(payload) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.loss(*payload) } + } + + @Suppress("UNCHECKED_CAST") + public override fun uzz(): T where T : SomeGeneric, T : List = _uzz.invoke() { + useSpyIf(__spyOn) { __spyOn!!.uzz() } + } as T + + @Suppress("UNCHECKED_CAST") + public override fun lzz(): T where T : SomeGeneric, T : List? = _lzz.invoke() + { + useSpyIf(__spyOn) { __spyOn!!.lzz() } + } as T + + @Suppress("UNCHECKED_CAST") + public override fun tzz(): T where T : SomeGeneric?, T : List? = _tzz.invoke() + { + useSpyIf(__spyOn) { __spyOn!!.tzz() } + } as T + + @Suppress("UNCHECKED_CAST") + public override fun rzz(): T where T : SomeGeneric, T : Map = + _rzz.invoke() { + useSpyIf(__spyOn) { __spyOn!!.rzz() } + } as T + + @Suppress("UNCHECKED_CAST") + public override fun izz(): T where T : SomeGeneric, T : Comparable>> = + _izz.invoke() { + useSpyIf(__spyOn) { __spyOn!!.izz() } + } as T + + @Suppress("UNCHECKED_CAST") + public override fun oss(arg0: T): R = _ossWithAny.invoke(arg0) { + useSpyIf(__spyOn) { __spyOn!!.oss(arg0) } + } as R + + public override fun oss(arg0: T, arg1: R): Unit = _ossWithAnyAny.invoke(arg0, arg1) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.oss(arg0, arg1) } + } + + public override fun oss(arg0: R, vararg arg1: T): Unit = _ossWithAnyAnys.invoke(arg0, + arg1) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.oss(arg0, *arg1) } + } + + @Suppress("UNCHECKED_CAST") + public override fun kss(arg0: T): R where R : SomeGeneric, R : + Comparable>> = _kss.invoke(arg0) { + useSpyIf(__spyOn) { __spyOn!!.kss(arg0) } + } as R + + @Suppress("UNCHECKED_CAST") + public override fun iss(arg0: T): R where R : SomeGeneric, R : + Comparable>> = _iss.invoke(arg0) { + useSpyIf(__spyOn) { __spyOn!!.iss(arg0) } + } as R + + @Suppress("UNCHECKED_CAST") + public override fun > pss(arg0: T): R = _pss.invoke(arg0) { + useSpyIf(__spyOn) { __spyOn!!.pss(arg0) } + } as R + + @Suppress("UNCHECKED_CAST") + public override fun xss(arg0: T): R where R : Sequence, R : CharSequence = + _xssWithAny.invoke(arg0) { + useSpyIf(__spyOn) { __spyOn!!.xss(arg0) } + } as R + + public override fun xss(arg0: T, arg1: R): Unit where R : Sequence, R : CharSequence + = _xssWithAnySequenceCharSequence.invoke(arg0, arg1) { + useUnitFunRelaxerIf(relaxUnitFun || relaxed) + useSpyIf(__spyOn) { __spyOn!!.xss(arg0, arg1) } + } + + public override fun doSomething(arg: KMockTypeParameter4): KMockTypeParameter5 = + _doSomething.invoke(arg) { + useSpyIf(__spyOn) { __spyOn!!.doSomething(arg) } + } + + public override + fun compareTo(other: GenericCommonContract.Generic3): + Int = _compareTo.invoke(other) { + useSpyIf(__spyOn) { __spyOn!!.compareTo(other) } + } + + public override fun toString(): String = _toString.invoke() { + useRelaxerIf(true) { super.toString() } + useSpyIf(__spyOn) { __spyOn!!.toString() } + } + + public override fun equals(other: Any?): Boolean = _equals.invoke(other) { + useRelaxerIf(true) { super.equals(other) } + useSpyOnEqualsIf( + spyTarget = __spyOn, + other = other, + spyOn = { super.equals(other) }, + mockKlass = CommonGenericMultiMock::class + ) + } + + public override fun hashCode(): Int = _hashCode.invoke() { + useRelaxerIf(true) { super.hashCode() } + useSpyIf(__spyOn) { __spyOn!!.hashCode() } + } + + public fun _clearMock(): Unit { + _template.clear() + _lol.clear() + _fooWithVoid.clear() + _fooWithAny.clear() + _fooWithAnys.clear() + _blaWithVoid.clear() + _blaWithInt.clear() + _blaWithInts.clear() + _barWithVoid.clear() + _barWithList.clear() + _barWithLists.clear() + _blubbWithVoid.clear() + _blubbWithList.clear() + _blubbWithLists.clear() + _bussWithVoid.clear() + _bussWithList.clear() + _bussWithLists.clear() + _bossWithVoid.clear() + _bossWithList.clear() + _bossWithLists.clear() + _buzzWithVoid.clear() + _buzzWithList.clear() + _buzzWithLists.clear() + _ozzWithVoid.clear() + _ozzWithKMockTypeParameter3.clear() + _ozzWithKMockTypeParameter3s.clear() + _brassWithVoid.clear() + _brassWithComparable.clear() + _brassWithComparables.clear() + _blissWithVoid.clear() + _blissWithComparable.clear() + _blissWithComparables.clear() + _lossWithVoid.clear() + _lossWithMap.clear() + _lossWithMaps.clear() + _uzz.clear() + _lzz.clear() + _tzz.clear() + _rzz.clear() + _izz.clear() + _ossWithAny.clear() + _ossWithAnyAny.clear() + _ossWithAnyAnys.clear() + _kss.clear() + _iss.clear() + _pss.clear() + _xssWithAny.clear() + _xssWithAnySequenceCharSequence.clear() + _doSomething.clear() + _compareTo.clear() + _toString.clear() + _equals.clear() + _hashCode.clear() + } +} diff --git a/kmock-processor/src/test/resources/multi/template/commonGeneric/Generic1.kt b/kmock-processor/src/test/resources/multi/template/commonGeneric/Generic1.kt new file mode 100644 index 00000000..c2edc075 --- /dev/null +++ b/kmock-processor/src/test/resources/multi/template/commonGeneric/Generic1.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package multi.template.commonGeneric + +import multi.template.commonGeneric.nested.Generic2 +import tech.antibytes.kmock.MultiMockCommon + +interface SomeGeneric + +@MultiMockCommon( + "CommonGenericMulti", + Generic1::class, + Generic2::class, + GenericCommonContract.Generic3::class +) +interface Generic1 where L : Any, L : Comparable, K : Any { + var template: L + + fun foo(): T + + fun bla(): T + + fun >> bar(): T + + fun >> blubb(): T + + fun >?> buss(): T + + fun ?>> boss(): T + + fun >> buzz(): T? + + fun ozz(): T + + fun brass(): T where T : Comparable>> + + fun bliss(): T where T : Comparable>>? + + fun loss(): T where T : Map + + fun uzz(): T where T : SomeGeneric, T : List + + fun lzz(): T where T : SomeGeneric, T : List? + + fun tzz(): T where T : SomeGeneric?, T : List? + + fun rzz(): T where T : SomeGeneric, T : Map + + fun izz(): T where T : SomeGeneric, T : Comparable>> + + fun oss(arg0: T): R + + fun kss(arg0: T): R where R : SomeGeneric, R : Comparable>> + + fun iss(arg0: T): R where R : SomeGeneric, R : Comparable>> + + fun > pss(arg0: T): R where R : T + + fun xss(arg0: T): R where R : Sequence, R : CharSequence +} diff --git a/kmock-processor/src/test/resources/multi/template/commonGeneric/Generic3.kt b/kmock-processor/src/test/resources/multi/template/commonGeneric/Generic3.kt new file mode 100644 index 00000000..3843324b --- /dev/null +++ b/kmock-processor/src/test/resources/multi/template/commonGeneric/Generic3.kt @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package multi.template.commonGeneric + +interface GenericCommonContract { + interface Generic3 : Comparable> { + fun doSomething(arg: K): L + } +} diff --git a/kmock-processor/src/test/resources/multi/template/commonGeneric/nested/Generic2.kt b/kmock-processor/src/test/resources/multi/template/commonGeneric/nested/Generic2.kt new file mode 100644 index 00000000..7965edf5 --- /dev/null +++ b/kmock-processor/src/test/resources/multi/template/commonGeneric/nested/Generic2.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 Matthias Geisler (bitPogo) / All rights reserved. + * + * Use of this source code is governed by Apache v2.0 + */ + +package multi.template.commonGeneric.nested + +interface Generic2 where L : Any, L : Comparable, K : Any { + val lol: K + + fun foo(payload: T) + fun foo(vararg payload: T) + + fun bla(payload: T) + fun bla(vararg payload: T) + + fun >> bar(payload: T) + fun >> bar(vararg payload: T) + + fun >> blubb(payload: T) + fun >> blubb(vararg payload: T) + + fun >?> buss(payload: T) + fun >?> buss(vararg payload: T) + + fun ?>> boss(payload: T) + fun ?>> boss(vararg payload: T) + + fun >> buzz(payload: T?) + fun >> buzz(vararg payload: T?) + + fun ozz(payload: T) + fun ozz(vararg payload: T) + + fun brass(payload: T) where T : Comparable>> + fun brass(vararg payload: T) where T : Comparable>> + + fun bliss(payload: T) where T : Comparable>>? + fun bliss(vararg payload: T) where T : Comparable>>? + + fun loss(payload: T) where T : Map + fun loss(vararg payload: T) where T : Map + + fun oss(arg0: T, arg1: R) + fun oss(arg0: R, vararg arg1: T) + + fun xss(arg0: T, arg1: R) where R : Sequence, R : CharSequence +}