From cb52b748e628bd98df4c21366abdbf71c9a74442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Segovia=20C=C3=B3rdoba?= Date: Tue, 26 Dec 2023 20:39:47 +0100 Subject: [PATCH] Comment checker --- gradle/libs.versions.toml | 13 +- gradle/wrapper/gradle-wrapper.properties | 2 +- kopy-compiler/build.gradle.kts | 6 +- .../kopy/compiler/fir/FirKopyExtension.kt | 7 +- .../fir/checker/FirKopyCheckerExtension.kt | 192 ++++++++++++-- .../kopy/compiler/fir/errors/FirKopyError.kt | 44 +++ .../FirKopyDeclarationGenerationExtension.kt | 204 ++++++++++++++ .../FirKopySupertypeGenerationExtension.kt | 45 ---- .../compiler/ir/IrKopyGenerationExtension.kt | 26 +- .../ir/_internal/InvokeCallTransformer.kt | 176 ------------ .../InvokeOrKopyFunctionTransformer.kt | 117 ++++++++ .../_internal/SetOrUpdateCallTransformer.kt | 172 ++++++++++++ .../SetOrUpdateFunctionTransformer.kt | 36 +++ .../ir/_internal/UpdateCallTransformer.kt | 220 --------------- .../kopy/compiler/ir/_internal/isKopy.kt | 13 - .../ir/_internal/{ => utils}/irTree.kt | 2 +- .../compiler/ir/_internal/utils/isKopy.kt | 25 ++ .../box/no-nest-copy-update-no-it.fir.ir.txt | 246 ----------------- .../box/no-nest-copy-update-no-it.fir.txt | 49 ---- ... => no-nest-copy-update-no-it.kt.disabled} | 0 .../no-nest-invoke-update-no-it.fir.ir.txt | 246 ----------------- .../box/no-nest-invoke-update-no-it.fir.txt | 49 ---- ...> no-nest-invoke-update-no-it.kt.disabled} | 0 .../no-nest-invoke-update-with-it.fir.ir.txt | 250 ------------------ .../box/no-nest-invoke-update-with-it.fir.txt | 49 ---- ...no-nest-invoke-update-with-it.kt.disabled} | 0 ...py-complex-tree-set-calculated.kt.disabled | 21 ++ .../no-nest-kopy-set-calculated.kt.disabled | 17 ++ .../box/no-nest-kopy-set.kt.disabled | 35 +++ .../test-data/box/no-nest-kopy.kt.disabled | 30 +++ kopy-compiler/test-data/diagnostics/.empty | 0 .../invalid-call-chain/complex-1.fir.txt | 122 +++++++++ .../invalid-call-chain/complex-1.kt | 24 ++ .../missing-data-class/complex-1.fir.txt | 167 ++++++++++++ .../missing-data-class/complex-1.kt | 45 ++++ .../missing-data-class/simple-1.fir.txt | 101 +++++++ .../missing-data-class/simple-1.kt | 22 ++ .../missing-data-class/simple-2.fir.txt | 98 +++++++ .../missing-data-class/simple-2.kt | 22 ++ .../missing-data-class/simple-3.fir.txt | 98 +++++++ .../missing-data-class/simple-3.kt | 20 ++ .../missing-data-class/simple-4.fir.txt | 99 +++++++ .../missing-data-class/simple-4.kt | 23 ++ .../diagnostics/valid/complex-1.fir.txt | 173 ++++++++++++ .../test-data/diagnostics/valid/complex-1.kt | 45 ++++ .../kopy/compiler/BoxTestGenerated.java | 18 -- .../compiler/DiagnosticTestGenerated.java | 72 +++++ kopy-gradle-plugin/build.gradle.kts | 3 +- kopy-runtime/build.gradle.kts | 1 + .../kotlin/com/javiersc/kotlin/kopy/Kopy.kt | 7 + .../javiersc/kotlin/kopy/runtime/Kopyable.kt | 38 ++- .../kotlin/kopy/runtime/delete/Delete.kt | 45 ++-- .../kotlin/kopy/runtime/delete/Delete2.kt | 43 +-- settings.gradle.kts | 11 +- 54 files changed, 2121 insertions(+), 1468 deletions(-) create mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/errors/FirKopyError.kt create mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopyDeclarationGenerationExtension.kt delete mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopySupertypeGenerationExtension.kt delete mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeCallTransformer.kt create mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeOrKopyFunctionTransformer.kt create mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateCallTransformer.kt create mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateFunctionTransformer.kt delete mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/UpdateCallTransformer.kt delete mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/isKopy.kt rename kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/{ => utils}/irTree.kt (93%) create mode 100644 kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/utils/isKopy.kt delete mode 100644 kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.ir.txt delete mode 100644 kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.txt rename kopy-compiler/test-data/box/{no-nest-copy-update-no-it.kt => no-nest-copy-update-no-it.kt.disabled} (100%) delete mode 100644 kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.ir.txt delete mode 100644 kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.txt rename kopy-compiler/test-data/box/{no-nest-invoke-update-no-it.kt => no-nest-invoke-update-no-it.kt.disabled} (100%) delete mode 100644 kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.ir.txt delete mode 100644 kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.txt rename kopy-compiler/test-data/box/{no-nest-invoke-update-with-it.kt => no-nest-invoke-update-with-it.kt.disabled} (100%) create mode 100644 kopy-compiler/test-data/box/no-nest-kopy-complex-tree-set-calculated.kt.disabled create mode 100644 kopy-compiler/test-data/box/no-nest-kopy-set-calculated.kt.disabled create mode 100644 kopy-compiler/test-data/box/no-nest-kopy-set.kt.disabled create mode 100644 kopy-compiler/test-data/box/no-nest-kopy.kt.disabled delete mode 100644 kopy-compiler/test-data/diagnostics/.empty create mode 100644 kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.fir.txt create mode 100644 kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.kt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.fir.txt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.kt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.fir.txt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.kt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.fir.txt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.kt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.fir.txt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.kt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.fir.txt create mode 100644 kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.kt create mode 100644 kopy-compiler/test-data/diagnostics/valid/complex-1.fir.txt create mode 100644 kopy-compiler/test-data/diagnostics/valid/complex-1.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dbb03d1..386c3fb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,14 @@ [versions] -hubdle = "0.5.0+2.0.0-dev-10501-SNAPSHOT" -hubdleCatalog = "0.1.18+2.0.0-dev-10501-SNAPSHOT" -javiersc-kotlin-kotlinCompilerExtensions = "0.1.1+2.0.0-dev-10501-SNAPSHOT" -javiersc-kotlin-kotlinStdlibAndTest = "0.1.0-SNAPSHOT" +hubdle = "0.6.4+2.0.0-dev-15455-SNAPSHOT" +hubdleCatalog = "0.2.5+2.0.0-dev-15455-SNAPSHOT" +javiersc-kotlin-compiler-extensions = "0.1.1+2.0.0-dev-15455-SNAPSHOT" +javiersc-kotlin = "0.1.0-SNAPSHOT" [libraries] hubdle-catalog = { module = "com.javiersc.hubdle:hubdle-version-catalog", version.ref = "hubdleCatalog" } -javiersc-kotlinCompilerExtensions = { module = "com.javiersc.kotlin:kotlin-compiler-extensions", version.ref = "javiersc-kotlin-kotlinCompilerExtensions" } -javiersc-kotlinStdlib = { module = "com.javiersc.kotlin:kotlin-stdlib", version.ref = "javiersc-kotlin-kotlinStdlibAndTest" } +javiersc-kotlin-compiler-extensions = { module = "com.javiersc.kotlin:kotlin-compiler-extensions", version.ref = "javiersc-kotlin-compiler-extensions" } +javiersc-kotlin-compiler-test-extensions = { module = "com.javiersc.kotlin:kotlin-compiler-test-extensions", version.ref = "javiersc-kotlin-compiler-extensions" } +javiersc-kotlin-stdlib = { module = "com.javiersc.kotlin:kotlin-stdlib", version.ref = "javiersc-kotlin" } [plugins] javiersc-hubdle = { id = "com.javiersc.hubdle", version.ref = "hubdle" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e09..a80b22c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/kopy-compiler/build.gradle.kts b/kopy-compiler/build.gradle.kts index 543455c..b817760 100644 --- a/kopy-compiler/build.gradle.kts +++ b/kopy-compiler/build.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.dsl.KotlinVersion hubdle { @@ -8,6 +9,7 @@ hubdle { api() } explicitApi() + format.isEnabled = false languageSettings { // experimentalContracts() } @@ -23,7 +25,7 @@ hubdle { compiler { mainClass.set("com.javiersc.kotlin.kopy.compiler.GenerateKotlinCompilerTestsKt") generateTestOnSync(false) - testDependencies(hubdle.javiersc.kotlin.kotlinStdlib) + testDependencies(hubdle.javiersc.kotlin.stdlib) testProjects(projects.kopyRuntime) } contextReceivers() @@ -31,7 +33,7 @@ hubdle { } main { // dependencies { // - implementation(hubdle.javiersc.kotlin.kotlinCompilerExtensions) + implementation(hubdle.javiersc.kotlin.compiler.extensions) implementation(projects.kopyRuntime) } } diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/FirKopyExtension.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/FirKopyExtension.kt index 2eefb20..41e43c9 100644 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/FirKopyExtension.kt +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/FirKopyExtension.kt @@ -1,7 +1,8 @@ package com.javiersc.kotlin.kopy.compiler.fir import com.javiersc.kotlin.kopy.compiler.fir.checker.FirKopyCheckerExtension -import com.javiersc.kotlin.kopy.compiler.fir.generation.FirKopySupertypeGenerationExtension +import com.javiersc.kotlin.kopy.compiler.fir.generation.FirKopyDeclarationGenerationExtension +import org.jetbrains.kotlin.GeneratedDeclarationKey import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar @@ -19,6 +20,8 @@ internal class FirKopyExtension( } private fun ExtensionRegistrarContext.registerGenerators() { - +::FirKopySupertypeGenerationExtension + +::FirKopyDeclarationGenerationExtension } } + +internal object Key : GeneratedDeclarationKey() diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/checker/FirKopyCheckerExtension.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/checker/FirKopyCheckerExtension.kt index c7f9472..227871c 100644 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/checker/FirKopyCheckerExtension.kt +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/checker/FirKopyCheckerExtension.kt @@ -1,48 +1,182 @@ package com.javiersc.kotlin.kopy.compiler.fir.checker -import com.javiersc.kotlin.compiler.extensions.common.fqName -import com.javiersc.kotlin.kopy.KopyFunctionInvoke +import com.javiersc.kotlin.compiler.extensions.common.classId +import com.javiersc.kotlin.compiler.extensions.fir.asFirOrNull +import com.javiersc.kotlin.kopy.Kopy +import com.javiersc.kotlin.kopy.KopyFunctionSet +import com.javiersc.kotlin.kopy.KopyFunctionUpdate +import com.javiersc.kotlin.kopy.compiler.fir.checker.BreakingCallsChecker.CheckerResult.Failure +import com.javiersc.kotlin.kopy.compiler.fir.checker.BreakingCallsChecker.CheckerResult.Ignore +import com.javiersc.kotlin.kopy.compiler.fir.checker.BreakingCallsChecker.CheckerResult.Success +import com.javiersc.kotlin.kopy.compiler.fir.errors.FirKopyError +import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.DEFAULT +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirCallChecker import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension +import org.jetbrains.kotlin.fir.declarations.utils.isData import org.jetbrains.kotlin.fir.expressions.FirCall -import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar -import org.jetbrains.kotlin.fir.resolve.fqName +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirFunctionCall +import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression +import org.jetbrains.kotlin.fir.expressions.FirResolvable +import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression +import org.jetbrains.kotlin.fir.getOwnerLookupTag +import org.jetbrains.kotlin.fir.references.symbol +import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.resolve.dfa.symbol +import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.types.resolvedType +import org.jetbrains.kotlin.fir.types.toRegularClassSymbol +import org.jetbrains.kotlin.name.ClassId internal class FirKopyCheckerExtension( session: FirSession, ) : FirAdditionalCheckersExtension(session) { - override val expressionCheckers: ExpressionCheckers = - object : ExpressionCheckers() { - override val callCheckers: Set = - setOf( - object : FirCallChecker() { - override fun check( - expression: FirCall, - context: CheckerContext, - reporter: DiagnosticReporter - ) { - if ( - expression.annotations.any { - it.fqName(session) == fqName() - } - ) - println() - } - } + override val expressionCheckers: ExpressionCheckers = FirKopyExpressionCheckers +} + +private object FirKopyExpressionCheckers : ExpressionCheckers() { + override val callCheckers: Set = + setOf( + BreakingCallsChecker, + ) +} + +private object BreakingCallsChecker : FirCallChecker(MppCheckerKind.Common) { + + override fun check(expression: FirCall, context: CheckerContext, reporter: DiagnosticReporter) { + when (val checkerResult: CheckerResult = expression.isBreakingCallsChain(context)) { + is Ignore -> return + is Success -> return + is Failure.BrokenChain -> { + reporter.reportOn( + source = checkerResult.source, + factory = FirKopyError.INVALID_CALL_CHAIN, + a = checkerResult.element.render(), + context = context, + positioningStrategy = DEFAULT, ) + } + is Failure.MissingDataClass -> { + reporter.reportOn( + source = checkerResult.source, + factory = FirKopyError.MISSING_DATA_CLASS, + a = checkerResult.element.render(), + context = context, + positioningStrategy = DEFAULT, + ) + } + is Failure.MissingKopyAnnotation -> { + reporter.reportOn( + source = checkerResult.source, + factory = FirKopyError.MISSING_KOPY_ANNOTATION, + a = checkerResult.element.render(), + context = context, + positioningStrategy = DEFAULT, + ) + } } + } + + private val FirCall.isKopyFunctionSetOrUpdateCall: Boolean + get() = + asFirOrNull() + ?.calleeReference + ?.symbol + ?.resolvedAnnotationClassIds + ?.firstOrNull() + .let { it == classId() || it == classId() } + + private fun FirCall.isBreakingCallsChain(context: CheckerContext): CheckerResult { + if (!isKopyFunctionSetOrUpdateCall) return Ignore + + val session: FirSession = context.session + val setOrUpdateCall: FirFunctionCall = asFirOrNull() ?: return Failure.BrokenChain(this) + val extensionReceiver: FirPropertyAccessExpression = + setOrUpdateCall.extensionReceiver?.asFirOrNull() + ?: return Failure.BrokenChain(setOrUpdateCall) + val extensionReceiverOwnerAnnotations: List = + extensionReceiver.symbol + ?.getOwnerLookupTag() + ?.toFirRegularClassSymbol(session) + ?.resolvedAnnotationClassIds + .orEmpty() + if (!extensionReceiverOwnerAnnotations.any { it == classId() }) { + return Failure.MissingKopyAnnotation(extensionReceiver) + } + val updateOrSetThisBoundSymbol: FirBasedSymbol<*> = + setOrUpdateCall.dispatchReceiver + ?.asFirOrNull() + ?.calleeReference + ?.boundSymbol ?: return Failure.BrokenChain(setOrUpdateCall) + + val extensionDispatchReceiver: FirExpression = + extensionReceiver.dispatchReceiver + ?: return Failure.BrokenChain(extensionReceiver.calleeReference) + + val checkerResult: CheckerResult = + extensionDispatchReceiver.isBreakingChainCall(session, updateOrSetThisBoundSymbol) + return checkerResult + } + + private fun FirExpression.isBreakingChainCall( + session: FirSession, + updateOrSetThisBoundSymbol: FirBasedSymbol<*> + ): CheckerResult { + val thisBoundSymbol: FirBasedSymbol<*>? = + this.asFirOrNull()?.calleeReference?.boundSymbol + if (updateOrSetThisBoundSymbol == thisBoundSymbol) return Success + + if (this !is FirPropertyAccessExpression) return Failure.BrokenChain(this) - override fun FirDeclarationPredicateRegistrar.registerPredicates() { - // DeclarationPredicate.create { - // // metaAnnotated(fqName(), includeItself = true) - // // parentAnnotated(fqName()) - // // annotated(fqName()) - // // ancestorAnnotated(fqName()) - // } + val isDataClass: Boolean = this.resolvedType.toRegularClassSymbol(session)?.isData ?: false + + val receiver: FirExpression? = this.dispatchReceiver + + val dispatcherBoundSymbol: FirBasedSymbol<*>? = + receiver?.asFirOrNull()?.calleeReference?.boundSymbol + + val hasSameBoundSymbol: Boolean = dispatcherBoundSymbol == updateOrSetThisBoundSymbol + + return when { + hasSameBoundSymbol -> Success + receiver == null -> Failure.BrokenChain(this) + receiver !is FirPropertyAccessExpression -> { + val element = receiver.asFirOrNull()?.calleeReference ?: receiver + Failure.BrokenChain(element) + } + !isDataClass -> Failure.MissingDataClass(this.calleeReference) + else -> receiver.isBreakingChainCall(session, updateOrSetThisBoundSymbol) + } + } + + sealed interface CheckerResult { + + data object Ignore : CheckerResult + + data object Success : CheckerResult + + sealed interface Failure : CheckerResult { + + val element: FirElement + + val source: KtSourceElement + get() = element.source ?: error("No source for $this") + + data class BrokenChain(override val element: FirElement) : Failure + + data class MissingDataClass(override val element: FirElement) : Failure + + data class MissingKopyAnnotation(override val element: FirElement) : Failure + } } } diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/errors/FirKopyError.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/errors/FirKopyError.kt new file mode 100644 index 0000000..04382c1 --- /dev/null +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/errors/FirKopyError.kt @@ -0,0 +1,44 @@ +package com.javiersc.kotlin.kopy.compiler.fir.errors + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory1 +import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap +import org.jetbrains.kotlin.diagnostics.error1 +import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory +import org.jetbrains.kotlin.diagnostics.rendering.Renderer +import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory + +internal object FirKopyError : BaseDiagnosticRendererFactory() { + + init { + RootDiagnosticRendererFactory.registerFactory(FirKopyError) + } + + val INVALID_CALL_CHAIN: KtDiagnosticFactory1 by error1() + + val MISSING_DATA_CLASS: KtDiagnosticFactory1 by error1() + + val MISSING_KOPY_ANNOTATION: KtDiagnosticFactory1 by error1() + + override val MAP: KtDiagnosticFactoryToRendererMap = rendererMap { map -> + map.put( + factory = INVALID_CALL_CHAIN, + message = "Call chain broken at `{0}`", + rendererA = Renderer { t: String -> t }, + ) + map.put( + factory = MISSING_DATA_CLASS, + message = "The property `{0}` does not belong to a data class", + rendererA = Renderer { t: String -> t }, + ) + map.put( + factory = MISSING_KOPY_ANNOTATION, + message = "The property `{0}` does not belong to a data class annotated with `@Kopy`", + rendererA = Renderer { t: String -> t }, + ) + } + + private fun rendererMap( + block: (KtDiagnosticFactoryToRendererMap) -> Unit + ): KtDiagnosticFactoryToRendererMap = KtDiagnosticFactoryToRendererMap("FirKopy").also(block) +} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopyDeclarationGenerationExtension.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopyDeclarationGenerationExtension.kt new file mode 100644 index 0000000..d8e741a --- /dev/null +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopyDeclarationGenerationExtension.kt @@ -0,0 +1,204 @@ +package com.javiersc.kotlin.kopy.compiler.fir.generation + +import com.javiersc.kotlin.compiler.extensions.common.classId +import com.javiersc.kotlin.compiler.extensions.common.fqName +import com.javiersc.kotlin.compiler.extensions.common.toClassId +import com.javiersc.kotlin.compiler.extensions.common.toName +import com.javiersc.kotlin.compiler.extensions.fir.coneKotlinType +import com.javiersc.kotlin.compiler.extensions.fir.createFirAnnotation +import com.javiersc.kotlin.compiler.extensions.fir.toFirTypeParameter +import com.javiersc.kotlin.compiler.extensions.fir.toFirTypeRef +import com.javiersc.kotlin.kopy.Kopy +import com.javiersc.kotlin.kopy.KopyFunctionInvoke +import com.javiersc.kotlin.kopy.KopyFunctionKopy +import com.javiersc.kotlin.kopy.compiler.fir.Key +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.FirTypeParameter +import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef +import org.jetbrains.kotlin.fir.declarations.utils.isInfix +import org.jetbrains.kotlin.fir.expressions.builder.buildBlock +import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension +import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar +import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext +import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate +import org.jetbrains.kotlin.fir.plugin.createMemberFunction +import org.jetbrains.kotlin.fir.resolve.defaultType +import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredFunctionSymbols +import org.jetbrains.kotlin.fir.resolve.providers.getRegularClassSymbolByClassId +import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap +import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirValueParameterSymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.ConeTypeProjection +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +internal class FirKopyDeclarationGenerationExtension( + session: FirSession, +) : FirDeclarationGenerationExtension(session) { + + private val kopyableClassId: ClassId = "com.javiersc.kotlin.kopy.runtime.Kopyable".toClassId() + private val invokeName = "invoke".toName() + private val copyName = "copy".toName() + + override fun generateFunctions( + callableId: CallableId, + context: MemberGenerationContext? + ): List { + val kopyFunctions: List = + createKopyInvokeFunctions(callableId, context) + + return kopyFunctions + } + + private fun createKopyInvokeFunctions( + callableId: CallableId, + context: MemberGenerationContext? + ): List { + val callableName: Name = callableId.callableName + if (callableName != invokeName && callableName != copyName) return emptyList() + + val owner: FirClassSymbol<*> = context?.owner ?: return emptyList() + + val invokeFunction: FirSimpleFunction = createInvokeOrCopy(callableId, owner) + return listOf(invokeFunction.symbol) + } + + private fun createInvokeOrCopy( + callableId: CallableId, + owner: FirClassSymbol<*> + ): FirSimpleFunction { + val invokeFunction: FirNamedFunctionSymbol = + session.symbolProvider + .getClassDeclaredFunctionSymbols(kopyableClassId, callableId.callableName) + .first() + val invokeValueParameter: FirValueParameterSymbol = + invokeFunction.valueParameterSymbols.first() + + val type: ConeKotlinType = + owner.kopyableSubstitutor.substituteOrSelf(invokeValueParameter.coneKotlinType) + + val function: FirSimpleFunction = + createMemberFunction( + owner = owner, + key = Key, + name = callableId.callableName, + returnType = owner.fir.defaultType(), + config = { + status { + isInfix = invokeFunction.isInfix + isOperator = callableId.callableName == invokeName + } + modality = Modality.FINAL + valueParameter(name = copyName, type = type) + }, + ) + .apply { + val annotationClassId = + when (callableId.callableName) { + invokeName -> classId() + copyName -> classId() + else -> error("This should never happen") + } + val kopyInvokeTypeRef: FirTypeRef = + session.symbolProvider + .getRegularClassSymbolByClassId(annotationClassId) + ?.toFirTypeRef() ?: return@apply + replaceAnnotations(listOf(createFirAnnotation(kopyInvokeTypeRef))) + replaceBody(buildBlock()) + } + + return function + } + + private val kopyableTypeParameterSymbols: List + get() = + session.symbolProvider + .getClassLikeSymbolByClassId(kopyableClassId) + ?.typeParameterSymbols + .orEmpty() + + private val FirClassSymbol<*>.kopyableSubstitutor: ConeSubstitutor + get() = session.substitutor(kopyableTypeParameterSymbols, listOf(defaultType())) + + override fun getCallableNamesForClass( + classSymbol: FirClassSymbol<*>, + context: MemberGenerationContext + ): Set { + val names: Set = + setOf( + invokeName, + copyName, + ) + return names + } + + override fun FirDeclarationPredicateRegistrar.registerPredicates() { + register(DeclarationPredicate.create { annotated(fqName()) }) + } +} + +private fun FirSession.substitutor( + fromTypeParameters: List, + toTypeParameters: List, +): ConeSubstitutor { + val substitutionMap: Map = + fromTypeParameters.zip(toTypeParameters) { from, to -> from to to }.toMap() + + return substitutorByMap(substitutionMap, this) +} + +@JvmName("substitutor1") +private fun FirSession.substitutor( + fromTypeParameters: List, + toTypeParameters: List, +): ConeSubstitutor = substitutor(fromTypeParameters.map(FirTypeParameter::symbol), toTypeParameters) + +@JvmName("substitutor2") +private fun FirSession.substitutor( + fromTypeParameters: List, + toTypeParameters: List, +): ConeSubstitutor = + substitutor(fromTypeParameters, toTypeParameters.map(FirTypeParameterSymbol::coneKotlinType)) + +@JvmName("substitutor3") +private fun FirSession.substitutor( + fromTypeParameters: List, + toTypeParameters: List, +): ConeSubstitutor = + substitutor( + fromTypeParameters.map(FirTypeParameterRef::symbol), + toTypeParameters.map(FirTypeParameterSymbol::coneKotlinType) + ) + +@JvmName("substitutor4") +private fun FirSession.substitutor( + fromTypeParameters: List, + toTypeParameters: List, +): ConeSubstitutor = + substitutor(fromTypeParameters.map(FirTypeParameterRef::symbol), toTypeParameters) + +@JvmName("substitutor5") +private fun FirSession.substitutor( + fromTypeParameters: Map>, + toTypeParameters: List, +): ConeSubstitutor { + val params: List = + fromTypeParameters.map { (projection: ConeTypeProjection, container: FirBasedSymbol<*>) -> + projection.toFirTypeParameter( + session = this, + key = Key, + containingDeclarationSymbol = container + ) + } + return substitutor(params, toTypeParameters) +} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopySupertypeGenerationExtension.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopySupertypeGenerationExtension.kt deleted file mode 100644 index 85df835..0000000 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/fir/generation/FirKopySupertypeGenerationExtension.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.javiersc.kotlin.kopy.compiler.fir.generation - -import com.javiersc.kotlin.compiler.extensions.common.classId -import com.javiersc.kotlin.compiler.extensions.common.fqName -import com.javiersc.kotlin.compiler.extensions.fir.createFirResolvedTypeRef -import com.javiersc.kotlin.compiler.extensions.fir.toConeType -import com.javiersc.kotlin.kopy.Kopy as KopyAnnotation -import com.javiersc.kotlin.kopy.runtime.Kopyable -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration -import org.jetbrains.kotlin.fir.declarations.utils.classId -import org.jetbrains.kotlin.fir.expressions.FirAnnotation -import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar -import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension -import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate -import org.jetbrains.kotlin.fir.resolve.fqName -import org.jetbrains.kotlin.fir.types.ConeClassLikeType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef - -internal class FirKopySupertypeGenerationExtension( - session: FirSession, -) : FirSupertypeGenerationExtension(session) { - - context(TypeResolveServiceContainer) - override fun computeAdditionalSupertypes( - classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List - ): List { - if (classLikeDeclaration.annotations.isEmpty()) return emptyList() - if (classLikeDeclaration.annotations.none { it.isKopy }) return emptyList() - val typeArgument: ConeClassLikeType = classLikeDeclaration.classId.toConeType() - val type: ConeClassLikeType = classId>().toConeType(typeArgument) - val supertype: FirResolvedTypeRef = createFirResolvedTypeRef(type) - return listOf(supertype) - } - - override fun needTransformSupertypes(declaration: FirClassLikeDeclaration): Boolean = true - - override fun FirDeclarationPredicateRegistrar.registerPredicates() { - register(LookupPredicate.create { annotated(fqName()) }) - } - - private val FirAnnotation.isKopy: Boolean - get() = fqName(session) == fqName() -} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/IrKopyGenerationExtension.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/IrKopyGenerationExtension.kt index 77cac9d..7367a47 100644 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/IrKopyGenerationExtension.kt +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/IrKopyGenerationExtension.kt @@ -1,31 +1,29 @@ package com.javiersc.kotlin.kopy.compiler.ir -import com.javiersc.kotlin.compiler.extensions.ir.asIrOrNull -import com.javiersc.kotlin.compiler.extensions.ir.name -import com.javiersc.kotlin.kopy.compiler.ir._internal.InvokeCallTransformer -import com.javiersc.kotlin.kopy.compiler.ir._internal.UpdateCallTransformer -import com.javiersc.kotlin.stdlib.tree.TreeNode import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer internal class IrKopyGenerationExtension( private val configuration: CompilerConfiguration, ) : IrGenerationExtension { override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { - moduleFragment.transform(InvokeCallTransformer(moduleFragment, pluginContext), null) - moduleFragment.transform(UpdateCallTransformer(moduleFragment, pluginContext), null) + moduleFragment.generate(pluginContext) + } + + @JvmName("generate2") + private fun IrModuleFragment.generate(pluginContext: IrPluginContext) { + // transform(InvokeOrKopyFunctionTransformer(this, pluginContext)) + // transform(SetOrUpdateFunctionTransformer(this, pluginContext)) + // transform(SetOrUpdateCallTransformer(this, pluginContext)) - println("IrKopyGenerationExtension") + println("FINISHED") } - private fun TreeNode.addNestedReceivers(call: IrFunctionAccessExpression) { - val receiver = call.extensionReceiver?.asIrOrNull() ?: return - addChild(TreeNode(receiver.name)) - addNestedReceivers(receiver) + private fun IrModuleFragment.transform(transformer: IrElementTransformer) { + this.transform(transformer, null) } } diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeCallTransformer.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeCallTransformer.kt deleted file mode 100644 index d90dd2d..0000000 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeCallTransformer.kt +++ /dev/null @@ -1,176 +0,0 @@ -package com.javiersc.kotlin.kopy.compiler.ir._internal - -import com.javiersc.kotlin.compiler.extensions.common.toCallableId -import com.javiersc.kotlin.compiler.extensions.common.toName -import com.javiersc.kotlin.compiler.extensions.ir.asIr -import com.javiersc.kotlin.compiler.extensions.ir.asIrOrNull -import com.javiersc.kotlin.compiler.extensions.ir.createIrFunctionExpression -import com.javiersc.kotlin.compiler.extensions.ir.declarationIrBuilder -import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext -import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder -import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.builders.declarations.buildFun -import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter -import org.jetbrains.kotlin.ir.builders.irBlockBody -import org.jetbrains.kotlin.ir.builders.irCall -import org.jetbrains.kotlin.ir.builders.irGet -import org.jetbrains.kotlin.ir.builders.irReturn -import org.jetbrains.kotlin.ir.builders.irSet -import org.jetbrains.kotlin.ir.builders.irTemporary -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction -import org.jetbrains.kotlin.ir.declarations.IrVariable -import org.jetbrains.kotlin.ir.expressions.IrBlockBody -import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression -import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression -import org.jetbrains.kotlin.ir.expressions.IrGetValue -import org.jetbrains.kotlin.ir.expressions.IrSetValue -import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall -import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.types.IrSimpleType -import org.jetbrains.kotlin.ir.types.typeWith -import org.jetbrains.kotlin.ir.util.statements -import org.jetbrains.kotlin.name.SpecialNames - -internal class InvokeCallTransformer( - private val moduleFragment: IrModuleFragment, - private val pluginContext: IrPluginContext, -) : IrElementTransformerVoidWithContext() { - - override fun visitCall(expression: IrCall): IrExpression { - fun originalCall(): IrExpression = super.visitCall(expression) - - if (!expression.isKopyInvoke) return originalCall() - val runCall: IrFunctionAccessExpression = createRunCall(expression) ?: return originalCall() - - return runCall - } - - private fun IrSymbol.declarationIrBuilder(): DeclarationIrBuilder = - pluginContext.declarationIrBuilder(this) - - private fun createRunCall(originalCall: IrCall): IrFunctionAccessExpression? { - val originalCallParent: IrDeclarationParent = - originalCall.findDeclarationParent(moduleFragment)?.asIrOrNull() - ?: return null - val type = originalCall.dispatchReceiver?.type ?: return null - - val runFunction: IrSimpleFunction = - pluginContext - .referenceFunctions("kotlin.run".toCallableId()) - .first { it.owner.typeParameters.count() == 2 } - .owner - - val runBlockFunction: IrSimpleFunction = - pluginContext.irFactory - .buildFun { - name = SpecialNames.ANONYMOUS - visibility = DescriptorVisibilities.LOCAL - returnType = type - origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA - } - .apply { - parent = originalCallParent - extensionReceiverParameter = - buildValueParameter(this) { - this.name = "${'$'}this${'$'}run".toName() - this.type = type - } - } - - val originalStatements = - originalCall - .getValueArgument(0) - .asIrOrNull() - ?.function - ?.body - ?.statements ?: return null - - val runBlockFunctionBody: IrBlockBody = - runBlockFunction.symbol.declarationIrBuilder().irBlockBody { - val thisRunReceiver: IrGetValue = - runBlockFunction.extensionReceiverParameter?.let { valueParameter -> - runBlockFunction.symbol.declarationIrBuilder().irGet(valueParameter) - } ?: return@irBlockBody - - val tempVar: IrVariable = irTemporary(value = thisRunReceiver, isMutable = true) - for (statement in originalStatements) { - +statement.processStatement(originalCall, runBlockFunction, tempVar) - } - +irReturn(runBlockFunction.symbol.declarationIrBuilder().irGet(tempVar)) - } - - runBlockFunction.body = runBlockFunctionBody - - val runCall: IrFunctionAccessExpression = - runFunction.symbol.declarationIrBuilder().irCall(runFunction).apply { - extensionReceiver = originalCall.dispatchReceiver - putTypeArgument(index = 0, type = type) - putTypeArgument(index = 1, type = type) - val kFunction1Type: IrSimpleType = - runFunction.valueParameters - .first() - .type - .asIr() - .classifier - .typeWith(type, type) - putValueArgument( - index = 0, - valueArgument = - createIrFunctionExpression( - type = kFunction1Type, - function = runBlockFunction, - origin = IrStatementOrigin.LAMBDA, - ) - ) - this.type = type - } - - return runCall - } - - private fun IrStatement.processStatement( - originalCall: IrCall, - runBlockFunction: IrSimpleFunction, - tempVar: IrVariable, - ): IrStatement { - val operatorCall: IrFunctionAccessExpression = - asIrOrNull()?.argument?.asIrOrNull() ?: return this - - val original = originalCall.dispatchReceiver.asIrOrNull() ?: return this - val originalType = original.type - val originalName = original.symbol.descriptor.name - - val operator = operatorCall.dispatchReceiver.asIrOrNull() ?: return this - val operatorType = operator.type - val operatorName = operator.symbol.descriptor.name - - val originalThisName = "${'$'}this${'$'}$originalName" - val originalThisCopyName = "${'$'}this${'$'}copy" - val hasSameReceiver = - originalType == operatorType && - (originalThisName == "$operatorName" || originalThisCopyName == "$operatorName") - - if (!hasSameReceiver) return this - - operatorCall.apply { - val receiver: () -> IrGetValue = { - runBlockFunction.symbol.declarationIrBuilder().irGet(tempVar) - } - dispatchReceiver = receiver() - extensionReceiver.asIrOrNull()?.dispatchReceiver = - receiver() - } - val tempVarSet: IrSetValue = - runBlockFunction.symbol.declarationIrBuilder().irSet(tempVar, operatorCall) - - return tempVarSet - } -} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeOrKopyFunctionTransformer.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeOrKopyFunctionTransformer.kt new file mode 100644 index 0000000..3a260ff --- /dev/null +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/InvokeOrKopyFunctionTransformer.kt @@ -0,0 +1,117 @@ +@file:Suppress("DEPRECATION_ERROR") + +package com.javiersc.kotlin.kopy.compiler.ir._internal + +import com.javiersc.kotlin.compiler.extensions.common.classId +import com.javiersc.kotlin.compiler.extensions.ir.asIr +import com.javiersc.kotlin.compiler.extensions.ir.declarationIrBuilder +import com.javiersc.kotlin.compiler.extensions.ir.firstIrClass +import com.javiersc.kotlin.kopy.compiler.ir._internal.utils.isKopyInvokeOrKopy +import com.javiersc.kotlin.kopy.runtime.KopyableScope +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irCallConstructor +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.builders.irTemporary +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrFail +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.getSimpleFunction +import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.primaryConstructor + +internal class InvokeOrKopyFunctionTransformer( + private val moduleFragment: IrModuleFragment, + private val pluginContext: IrPluginContext, +) : IrElementTransformerVoidWithContext() { + + private val kopyableScopeClass: IrClass by lazy { + pluginContext.firstIrClass(classId>()) + } + + private val kFunction2InvokeFunction: IrSimpleFunction by lazy { + pluginContext.irBuiltIns.functionN(2).getSimpleFunction("invoke")!!.owner + } + + override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement { + fun originalFunction(): IrStatement = super.visitSimpleFunction(declaration) + + if (!declaration.isKopyInvokeOrKopy) return originalFunction() + + val function: IrSimpleFunction = + declaration.apply { + body = + pluginContext.declarationIrBuilder(declaration.symbol).irBlockBody { + val scopeVariable: IrVariable = + irTemporary(value = createKopyableScopeConstructorCall(declaration)) + +createKopyValueArgumentCall(declaration, scopeVariable) + val scopeVariableGetCall: IrCall = + irCall(scopeVariable.getKopyableReferenceFunction).apply { + dispatchReceiver = irGet(scopeVariable) + } + +irReturn(scopeVariableGetCall) + } + } + return function + } + + private fun createKopyableScopeConstructorCall( + invokeOrKopyFunction: IrSimpleFunction, + ): IrConstructorCall { + val thisReceiverGet: IrGetValue = + pluginContext + .declarationIrBuilder(invokeOrKopyFunction.parentAsClass.symbol) + .irGet(invokeOrKopyFunction.dispatchReceiverParameter!!) + .apply { symbol.owner.parent = invokeOrKopyFunction } + val typeParameterType: IrType = invokeOrKopyFunction.returnType + val kopyableScopeConstructorSymbol: IrConstructorSymbol = + kopyableScopeClass.primaryConstructor!!.symbol + val constructorCall: IrConstructorCall = + pluginContext.declarationIrBuilder(kopyableScopeClass.symbol).run { + irCallConstructor(kopyableScopeConstructorSymbol, listOf(typeParameterType)).apply { + type = kopyableScopeClass.typeWith(typeParameterType) + putValueArgument(0, thisReceiverGet) + } + } + return constructorCall + } + + private fun createKopyValueArgumentCall( + invokeOrKopyFunction: IrSimpleFunction, + scopeVariable: IrVariable + ): IrCall { + val kopyArgument: IrValueParameter = invokeOrKopyFunction.valueParameters.first() + val kopyValueArgumentCall: IrCall = + pluginContext.declarationIrBuilder(invokeOrKopyFunction.symbol).run { + irCall(callee = kFunction2InvokeFunction.symbol) + .apply { + dispatchReceiver = irGet(kopyArgument) + putValueArgument(0, irGet(scopeVariable)) + val scopeVariableGetCall: IrCall = + irCall(scopeVariable.getKopyableReferenceFunction).apply { + dispatchReceiver = irGet(scopeVariable) + } + putValueArgument(1, scopeVariableGetCall) + } + .asIr() + } + return kopyValueArgumentCall + } + + private val IrVariable.getKopyableReferenceFunction: IrSimpleFunctionSymbol + get() = type.classOrFail.getSimpleFunction("getKopyableReference")!! +} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateCallTransformer.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateCallTransformer.kt new file mode 100644 index 0000000..e36e6a9 --- /dev/null +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateCallTransformer.kt @@ -0,0 +1,172 @@ +package com.javiersc.kotlin.kopy.compiler.ir._internal + +import com.javiersc.kotlin.compiler.extensions.common.toCallableId +import com.javiersc.kotlin.compiler.extensions.ir.asIrOrNull +import com.javiersc.kotlin.compiler.extensions.ir.createIrFunctionExpression +import com.javiersc.kotlin.compiler.extensions.ir.declarationIrBuilder +import com.javiersc.kotlin.compiler.extensions.ir.firstIrSimpleFunction +import com.javiersc.kotlin.kopy.compiler.ir._internal.utils.findDeclarationParent +import com.javiersc.kotlin.kopy.compiler.ir._internal.utils.isKopySetOrUpdate +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildFun +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrFail +import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.util.getSimpleFunction +import org.jetbrains.kotlin.name.SpecialNames + +internal class SetOrUpdateCallTransformer( + private val moduleFragment: IrModuleFragment, + private val pluginContext: IrPluginContext, +) : IrElementTransformerVoidWithContext() { + + override fun visitCall(expression: IrCall): IrExpression { + fun originalCall(): IrExpression = super.visitCall(expression) + if (!expression.isKopySetOrUpdate) return originalCall() + + val alsoCall: IrCall = createAlsoCall(expression) ?: return originalCall() + val originalCallCallWithAlsoCall: IrCall = + expression.apply { putValueArgument(valueArgumentsCount - 1, alsoCall) } + return originalCallCallWithAlsoCall + } + + private fun createAlsoCall(expression: IrCall): IrCall? { + val alsoItValueParameter: IrExpression = + expression.getValueArgument((expression.valueArgumentsCount - 1).coerceAtLeast(0)) + ?: return null + val expressionParent: IrDeclarationParent = + expression.findDeclarationParent(moduleFragment)?.asIrOrNull() + ?: return null + val setOrUpdateType: IrType = expression.extensionReceiver?.type ?: return null + val alsoFunction: IrSimpleFunction = + pluginContext.firstIrSimpleFunction("kotlin.also".toCallableId()) + + val alsoBlockFunction: IrSimpleFunction = + pluginContext.irFactory + .buildFun { + name = SpecialNames.ANONYMOUS + visibility = DescriptorVisibilities.LOCAL + returnType = pluginContext.irBuiltIns.unitType + origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA + } + .apply { + parent = expressionParent + addValueParameter { + this.name = StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME + this.type = setOrUpdateType + } + + body = + pluginContext.declarationIrBuilder(this.symbol).irBlockBody { + val itValueParameter: IrValueParameter = valueParameters.first() + val alsoItValueParameterGetValue: IrGetValue = irGet(itValueParameter) + val setKopyableReferenceCall: IrCall? = + createSetKopyableReferenceCall( + originalExpression = expression, + alsoItValueParameterGetValue = alsoItValueParameterGetValue + ) + if (setKopyableReferenceCall != null) +setKopyableReferenceCall + } + } + + val alsoCall: IrCall = + pluginContext.declarationIrBuilder(alsoFunction.symbol).run { + irCall(alsoFunction.symbol).apply { + type = alsoItValueParameter.type + + extensionReceiver = run { + val index: Int = (expression.valueArgumentsCount - 1).coerceAtLeast(0) + expression.getValueArgument(index) + } + putTypeArgument(0, setOrUpdateType) + val alsoBlockFunctionExpression: IrFunctionExpression = + createIrFunctionExpression( + type = + pluginContext.irBuiltIns.run { + functionN(1).typeWith(setOrUpdateType, unitType) + }, + function = alsoBlockFunction, + origin = IrStatementOrigin.LAMBDA, + ) + putValueArgument(index = 0, valueArgument = alsoBlockFunctionExpression) + } + } + + return alsoCall + } + + private fun createSetKopyableReferenceCall( + originalExpression: IrCall, + alsoItValueParameterGetValue: IrGetValue, + ): IrCall? { + val kopyClassType: IrType = originalExpression.dispatchReceiver?.type ?: return null + val kopyableGetValue: IrGetValue = + originalExpression.asIrOrNull()?.getValueArgument(0)?.asIrOrNull() + ?: return null + val kopyableValueDeclaration: IrValueDeclaration = kopyableGetValue.symbol.owner + + val kopyableScopeClass: IrClassSymbol = kopyableGetValue.type.classOrFail + val getKopyableReferenceFunction: IrSimpleFunctionSymbol = + kopyableScopeClass.getSimpleFunction("getKopyableReference")!! + + val getKopyableReferenceCall: IrCall = + pluginContext.declarationIrBuilder(kopyableGetValue.symbol).run { + irCall(getKopyableReferenceFunction).apply { + dispatchReceiver = irGet(kopyableValueDeclaration) + type = kopyClassType + } + } + + val propertyGetFunction: IrSimpleFunction = + originalExpression.extensionReceiver.asIrOrNull()?.symbol?.owner ?: return null + + val kopyClass = kopyClassType.classOrFail + val kopyClassCopyFunctionSymbol = kopyClass.owner.getSimpleFunction("copy")!! + + val copyCall: IrCall = + pluginContext.declarationIrBuilder(originalExpression.symbol).run { + irCall(kopyClassCopyFunctionSymbol).apply { + dispatchReceiver = getKopyableReferenceCall + + val copyParamIndex: Int = + kopyClassCopyFunctionSymbol.owner.valueParameters.indexOfFirst { + it.name == propertyGetFunction.correspondingPropertySymbol?.owner?.name + } + putValueArgument(copyParamIndex, alsoItValueParameterGetValue) + } + } + + val setKopyableReferenceFunction: IrSimpleFunctionSymbol = + kopyableScopeClass.getSimpleFunction("setKopyableReference")!! + + val setKopyableReferenceCall: IrCall = + pluginContext.declarationIrBuilder(kopyableGetValue.symbol).run { + irCall(setKopyableReferenceFunction).apply { + dispatchReceiver = irGet(kopyableValueDeclaration) + putValueArgument(0, copyCall) + } + } + + return setKopyableReferenceCall + } +} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateFunctionTransformer.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateFunctionTransformer.kt new file mode 100644 index 0000000..6bac2f9 --- /dev/null +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/SetOrUpdateFunctionTransformer.kt @@ -0,0 +1,36 @@ +package com.javiersc.kotlin.kopy.compiler.ir._internal + +import com.javiersc.kotlin.compiler.extensions.ir.declarationIrBuilder +import com.javiersc.kotlin.kopy.compiler.ir._internal.utils.isKopySetOrUpdate +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irGetObjectValue +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl + +internal class SetOrUpdateFunctionTransformer( + private val moduleFragment: IrModuleFragment, + private val pluginContext: IrPluginContext, +) : IrElementTransformerVoidWithContext() { + + override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement { + fun originalFunction(): IrStatement = super.visitSimpleFunction(declaration) + + if (!declaration.isKopySetOrUpdate) return originalFunction() + + val function: IrSimpleFunction = + declaration.apply { + body = + pluginContext.declarationIrBuilder(declaration.symbol).irBlockBody { + val unitObjectGet: IrGetObjectValueImpl = + pluginContext.irBuiltIns.run { irGetObjectValue(unitType, unitClass) } + +irReturn(unitObjectGet) + } + } + return function + } +} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/UpdateCallTransformer.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/UpdateCallTransformer.kt deleted file mode 100644 index bc43913..0000000 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/UpdateCallTransformer.kt +++ /dev/null @@ -1,220 +0,0 @@ -package com.javiersc.kotlin.kopy.compiler.ir._internal - -import com.javiersc.kotlin.compiler.extensions.common.toCallableId -import com.javiersc.kotlin.compiler.extensions.common.toName -import com.javiersc.kotlin.compiler.extensions.ir.asIr -import com.javiersc.kotlin.compiler.extensions.ir.asIrOrNull -import com.javiersc.kotlin.compiler.extensions.ir.createIrFunctionExpression -import com.javiersc.kotlin.compiler.extensions.ir.declarationIrBuilder -import com.javiersc.kotlin.compiler.extensions.ir.filterIrIsInstance -import com.javiersc.kotlin.compiler.extensions.ir.firstIrSimpleFunction -import com.javiersc.kotlin.compiler.extensions.ir.treeNode -import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext -import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext -import org.jetbrains.kotlin.builtins.StandardNames -import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder -import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter -import org.jetbrains.kotlin.ir.builders.declarations.buildFun -import org.jetbrains.kotlin.ir.builders.irBlockBody -import org.jetbrains.kotlin.ir.builders.irCall -import org.jetbrains.kotlin.ir.builders.irReturn -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction -import org.jetbrains.kotlin.ir.declarations.IrValueParameter -import org.jetbrains.kotlin.ir.expressions.IrBlockBody -import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression -import org.jetbrains.kotlin.ir.expressions.IrGetField -import org.jetbrains.kotlin.ir.expressions.IrGetValue -import org.jetbrains.kotlin.ir.expressions.IrReturn -import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol -import org.jetbrains.kotlin.ir.types.IrSimpleType -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.typeWith -import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.statements -import org.jetbrains.kotlin.name.SpecialNames - -internal class UpdateCallTransformer( - private val moduleFragment: IrModuleFragment, - private val pluginContext: IrPluginContext, -) : IrElementTransformerVoidWithContext() { - - override fun visitCall(expression: IrCall): IrExpression { - fun originalCall(): IrExpression = super.visitCall(expression) - if (!expression.isKopyUpdate) return originalCall() - - val letCall: IrCall = createLetCall(expression) - - val copyCall: IrCall = createCopyCall(expression, letCall) - - return copyCall - } - - private fun createLetCall(updateCall: IrCall): IrCall { - val declarationParent: IrDeclarationParent = - updateCall.findDeclarationParent(moduleFragment).asIrOrNull() - ?: return updateCall - - val updateBlockStatements: List = - updateCall - .getValueArgument((updateCall.valueArgumentsCount - 1).takeIf { it >= 0 } ?: 0) - .asIrOrNull() - ?.function - ?.body - ?.statements - .orEmpty() - - val type: IrType = updateCall.type - - val letFunction: IrSimpleFunction = - pluginContext.firstIrSimpleFunction("kotlin.let".toCallableId()) - - val letBlockFunction: IrSimpleFunction = - pluginContext.irFactory - .buildFun { - name = SpecialNames.ANONYMOUS - visibility = DescriptorVisibilities.LOCAL - returnType = type - origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA - } - .apply { - parent = declarationParent - addValueParameter { - this.name = StandardNames.IMPLICIT_LAMBDA_PARAMETER_NAME - this.type = type - } - } - - val letBlockBody: IrBlockBody = - pluginContext.declarationIrBuilder(letBlockFunction).irBlockBody { - replaceUpdateBlockItWithLetBlockIt(updateCall, letBlockFunction) - for (statement in updateBlockStatements) { - +processUpdateBlockStatement(statement) - } - } - letBlockFunction.body = letBlockBody - - val letCall: IrCall = - pluginContext - .declarationIrBuilder(letFunction.symbol) - .irCall(letFunction.symbol) - .apply { - this.extensionReceiver = updateCall.extensionReceiver - this.dispatchReceiver = null - putTypeArgument(index = 0, type = type) - putTypeArgument(index = 1, type = type) - val kFunction1Type: IrSimpleType = - letFunction.valueParameters - .first() - .type - .asIr() - .classifier - .typeWith(type, type) - putValueArgument( - index = 0, - valueArgument = - createIrFunctionExpression( - type = kFunction1Type, - function = letBlockFunction, - origin = IrStatementOrigin.LAMBDA, - ) - ) - this.type = type - } - - return letCall - } - - private fun replaceUpdateBlockItWithLetBlockIt( - updateCall: IrCall, - letBlockFunction: IrSimpleFunction, - ) { - val updateItValueParameter: IrValueParameter = - updateCall - .getValueArgument(0) - ?.asIrOrNull() - ?.function - ?.valueParameters - ?.firstOrNull() ?: return - val its: List = - updateCall - .getValueArgument(0) - ?.treeNode - ?.asSequence() - ?.filterIrIsInstance() - ?.filter { it.symbol.owner == updateItValueParameter } - .orEmpty() - .toList() - - val letItValueParameter: IrValueParameter = letBlockFunction.valueParameters.first() - - for (it in its) { - it.symbol = letItValueParameter.symbol - } - } - - private fun IrBlockBodyBuilder.processUpdateBlockStatement( - statement: IrStatement - ): IrStatement { - - return if (statement is IrReturn) irReturn(statement.value) else statement - } - - private fun createCopyCall(updateCall: IrCall, letCall: IrCall): IrCall { - val tempVarGet: IrGetValue = - updateCall.dispatchReceiver.asIrOrNull() ?: return letCall - val propertySymbol: IrPropertySymbol = - letCall.extensionReceiver - .asIrOrNull() - ?.symbol - ?.owner - ?.correspondingPropertySymbol ?: return letCall - val copyFunction: IrSimpleFunction = - tempVarGet.type - .asIrOrNull() - ?.classifier - ?.owner - ?.asIrOrNull() - ?.functions - ?.firstOrNull { it.name == "copy".toName() } ?: return letCall - - val copyCall: IrCall = - pluginContext.declarationIrBuilder(copyFunction).irCall(copyFunction.symbol).apply { - dispatchReceiver = tempVarGet - extensionReceiver = null - for (index in 0 ..< valueArgumentsCount) { - val isSameProperty: Boolean = - copyFunction.getIsSameProperty(index, propertySymbol) - if (!isSameProperty) putValueArgument(index, null) - else putValueArgument(index, letCall) - } - } - - return copyCall - } - - private fun IrFunction.getIsSameProperty( - index: Int, - propertySymbol: IrPropertySymbol - ): Boolean = - valueParameters - .getOrNull(index) - ?.asIrOrNull() - ?.symbol - ?.owner - ?.defaultValue - ?.expression - ?.asIrOrNull() - ?.symbol - ?.owner - ?.correspondingPropertySymbol == propertySymbol -} diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/isKopy.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/isKopy.kt deleted file mode 100644 index eef5d21..0000000 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/isKopy.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.javiersc.kotlin.kopy.compiler.ir._internal - -import com.javiersc.kotlin.compiler.extensions.common.fqName -import com.javiersc.kotlin.compiler.extensions.ir.hasAnnotation -import com.javiersc.kotlin.kopy.KopyFunctionInvoke -import com.javiersc.kotlin.kopy.KopyFunctionUpdate -import org.jetbrains.kotlin.ir.expressions.IrCall - -internal val IrCall.isKopyInvoke: Boolean - get() = hasAnnotation(fqName()) - -internal val IrCall.isKopyUpdate: Boolean - get() = hasAnnotation(fqName()) diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/irTree.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/utils/irTree.kt similarity index 93% rename from kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/irTree.kt rename to kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/utils/irTree.kt index fcccff3..507d23c 100644 --- a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/irTree.kt +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/utils/irTree.kt @@ -1,4 +1,4 @@ -package com.javiersc.kotlin.kopy.compiler.ir._internal +package com.javiersc.kotlin.kopy.compiler.ir._internal.utils import com.javiersc.kotlin.compiler.extensions.ir.treeNode import com.javiersc.kotlin.stdlib.tree.TreeNode diff --git a/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/utils/isKopy.kt b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/utils/isKopy.kt new file mode 100644 index 0000000..21ab701 --- /dev/null +++ b/kopy-compiler/main/kotlin/com/javiersc/kotlin/kopy/compiler/ir/_internal/utils/isKopy.kt @@ -0,0 +1,25 @@ +package com.javiersc.kotlin.kopy.compiler.ir._internal.utils + +import com.javiersc.kotlin.compiler.extensions.common.fqName +import com.javiersc.kotlin.compiler.extensions.ir.hasAnnotation +import com.javiersc.kotlin.kopy.KopyFunctionInvoke +import com.javiersc.kotlin.kopy.KopyFunctionKopy +import com.javiersc.kotlin.kopy.KopyFunctionSet +import com.javiersc.kotlin.kopy.KopyFunctionUpdate +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrCall + +internal val IrCall.isKopyInvoke: Boolean + get() = hasAnnotation(fqName()) + +internal val IrSimpleFunction.isKopyInvokeOrKopy: Boolean + get() = hasAnnotation(fqName()) || hasAnnotation(fqName()) + +internal val IrCall.isKopyUpdate: Boolean + get() = hasAnnotation(fqName()) + +internal val IrCall.isKopySetOrUpdate: Boolean + get() = hasAnnotation(fqName()) || hasAnnotation(fqName()) + +internal val IrSimpleFunction.isKopySetOrUpdate: Boolean + get() = hasAnnotation(fqName()) || hasAnnotation(fqName()) diff --git a/kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.ir.txt b/kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.ir.txt deleted file mode 100644 index d75e369..0000000 --- a/kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.ir.txt +++ /dev/null @@ -1,246 +0,0 @@ -FILE fqName:com.javiersc.kotlin.kopy.playground fileName:/no-nest-copy-update-no-it.kt - FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String - BLOCK_BODY - VAR name:house0 type:com.javiersc.kotlin.kopy.playground.House [val] - CONSTRUCTOR_CALL 'public constructor (street: kotlin.String, squareMeters: kotlin.Int) declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - street: CONST String type=kotlin.String value="Street" - squareMeters: CONST Int type=kotlin.Int value=20 - VAR name:house1 type:com.javiersc.kotlin.kopy.playground.House [val] - CALL 'public final fun run (block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.run declared in kotlin' type=com.javiersc.kotlin.kopy.playground.House origin=null - : com.javiersc.kotlin.kopy.playground.House - : com.javiersc.kotlin.kopy.playground.House - $receiver: GET_VAR 'val house0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:com.javiersc.kotlin.kopy.playground.House) returnType:com.javiersc.kotlin.kopy.playground.House - $receiver: VALUE_PARAMETER name:$this$run type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:com.javiersc.kotlin.kopy.playground.House [var] - GET_VAR '$this$run: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=kotlin.Unit origin=EQ - CALL 'public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - $this: GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - squareMeters: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let declared in kotlin' type=kotlin.Int origin=null - : kotlin.Int - : kotlin.Int - $receiver: CALL 'public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box.' - CONST Int type=kotlin.Int value=40 - RETURN type=kotlin.Nothing from='local final fun (): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' - GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - VAR name:house2 type:com.javiersc.kotlin.kopy.playground.House [val] - CALL 'public final fun run (block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.run declared in kotlin' type=com.javiersc.kotlin.kopy.playground.House origin=null - : com.javiersc.kotlin.kopy.playground.House - : com.javiersc.kotlin.kopy.playground.House - $receiver: GET_VAR 'val house0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:com.javiersc.kotlin.kopy.playground.House) returnType:com.javiersc.kotlin.kopy.playground.House - $receiver: VALUE_PARAMETER name:$this$run type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR name:tmp0 type:com.javiersc.kotlin.kopy.playground.House [var] - GET_VAR '$this$run: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=kotlin.Unit origin=EQ - CALL 'public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - $this: GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - squareMeters: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let declared in kotlin' type=kotlin.Int origin=null - : kotlin.Int - : kotlin.Int - $receiver: CALL 'public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box.' - CONST Int type=kotlin.Int value=40 - RETURN type=kotlin.Nothing from='local final fun (): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' - GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in com.javiersc.kotlin.kopy.playground' - WHEN type=kotlin.String origin=IF - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val house1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_VAR 'val house2: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: CONST String type=kotlin.String value="OK" - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="Fail: \nHouse1: " - GET_VAR 'val house1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=" \nHouse2: " - GET_VAR 'val house2: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - CLASS CLASS name:House modality:FINAL visibility:internal [data] superTypes:[kotlin.Any; com.javiersc.kotlin.kopy.runtime.Kopyable] - annotations: - Kopy - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:com.javiersc.kotlin.kopy.playground.House - CONSTRUCTOR visibility:public <> (street:kotlin.String, squareMeters:kotlin.Int) returnType:com.javiersc.kotlin.kopy.playground.House [primary] - VALUE_PARAMETER name:street index:0 type:kotlin.String - VALUE_PARAMETER name:squareMeters index:1 type:kotlin.Int - BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:House modality:FINAL visibility:internal [data] superTypes:[kotlin.Any; com.javiersc.kotlin.kopy.runtime.Kopyable]' - PROPERTY name:street visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final] - EXPRESSION_BODY - GET_VAR 'street: kotlin.String declared in com.javiersc.kotlin.kopy.playground.House.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String - correspondingProperty: PROPERTY name:street visibility:public modality:FINAL [val] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.' type=com.javiersc.kotlin.kopy.playground.House origin=null - PROPERTY name:squareMeters visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final] - EXPRESSION_BODY - GET_VAR 'squareMeters: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int - correspondingProperty: PROPERTY name:squareMeters visibility:public modality:FINAL [val] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String [operator] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.component1' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:component2 visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int [operator] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun component2 (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.component2' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House, street:kotlin.String, squareMeters:kotlin.Int) returnType:com.javiersc.kotlin.kopy.playground.House - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - VALUE_PARAMETER name:street index:0 type:kotlin.String - EXPRESSION_BODY - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.copy' type=com.javiersc.kotlin.kopy.playground.House origin=null - VALUE_PARAMETER name:squareMeters index:1 type:kotlin.Int - EXPRESSION_BODY - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.copy' type=com.javiersc.kotlin.kopy.playground.House origin=null - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' - CONSTRUCTOR_CALL 'public constructor (street: kotlin.String, squareMeters: kotlin.Int) declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - street: GET_VAR 'street: kotlin.String declared in com.javiersc.kotlin.kopy.playground.House.copy' type=kotlin.String origin=null - squareMeters: GET_VAR 'squareMeters: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.copy' type=kotlin.Int origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="House(" - CONST String type=kotlin.String value="street=" - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.toString' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=", " - CONST String type=kotlin.String value="squareMeters=" - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.toString' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=")" - FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR name:result type:kotlin.Int [var] - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Unit origin=EQ - CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: GET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Int origin=null - other: CONST Int type=kotlin.Int value=31 - other: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=com.javiersc.kotlin.kopy.playground.House origin=null - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Int origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ - arg0: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=true - WHEN type=kotlin.Unit origin=null - BRANCH - if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=com.javiersc.kotlin.kopy.playground.House - GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:com.javiersc.kotlin.kopy.playground.House [val] - TYPE_OP type=com.javiersc.kotlin.kopy.playground.House origin=CAST typeOperand=com.javiersc.kotlin.kopy.playground.House - GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR 'val tmp_1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR 'val tmp_1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=true - FUN FAKE_OVERRIDE name:copy visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, kopy:@[ExtensionFunctionType] kotlin.Function1) returnType:com.javiersc.kotlin.kopy.playground.House [fake_override,infix] - annotations: - KopyFunctionInvoke - overridden: - public open fun copy (kopy: @[ExtensionFunctionType] kotlin.Function1): T of com.javiersc.kotlin.kopy.runtime.Kopyable declared in com.javiersc.kotlin.kopy.runtime.Kopyable - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - VALUE_PARAMETER name:kopy index:0 type:@[ExtensionFunctionType] kotlin.Function1 - FUN FAKE_OVERRIDE name:invoke visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, kopy:@[ExtensionFunctionType] kotlin.Function1) returnType:com.javiersc.kotlin.kopy.playground.House [fake_override,operator,infix] - annotations: - KopyFunctionInvoke - overridden: - public open fun invoke (kopy: @[ExtensionFunctionType] kotlin.Function1): T of com.javiersc.kotlin.kopy.runtime.Kopyable declared in com.javiersc.kotlin.kopy.runtime.Kopyable - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - VALUE_PARAMETER name:kopy index:0 type:@[ExtensionFunctionType] kotlin.Function1 - FUN FAKE_OVERRIDE name:set visibility:public modality:OPEN ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, $receiver:R of com.javiersc.kotlin.kopy.playground.House.set, other:R of com.javiersc.kotlin.kopy.playground.House.set) returnType:R of com.javiersc.kotlin.kopy.playground.House.set [fake_override,infix] - annotations: - KopyFunctionSet - overridden: - public open fun set (other: R of com.javiersc.kotlin.kopy.runtime.Kopyable.set): R of com.javiersc.kotlin.kopy.runtime.Kopyable.set declared in com.javiersc.kotlin.kopy.runtime.Kopyable - TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?] reified:false - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - $receiver: VALUE_PARAMETER name: type:R of com.javiersc.kotlin.kopy.playground.House.set - VALUE_PARAMETER name:other index:0 type:R of com.javiersc.kotlin.kopy.playground.House.set - FUN FAKE_OVERRIDE name:update visibility:public modality:OPEN ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, $receiver:R of com.javiersc.kotlin.kopy.playground.House.update, other:kotlin.Function1) returnType:R of com.javiersc.kotlin.kopy.playground.House.update [fake_override,infix] - annotations: - KopyFunctionUpdate - overridden: - public open fun update (other: kotlin.Function1): R of com.javiersc.kotlin.kopy.runtime.Kopyable.update declared in com.javiersc.kotlin.kopy.runtime.Kopyable - TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?] reified:false - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - $receiver: VALUE_PARAMETER name: type:R of com.javiersc.kotlin.kopy.playground.House.update - VALUE_PARAMETER name:other index:0 type:kotlin.Function1 -FILE fqName: fileName:/SomeFile.kt diff --git a/kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.txt b/kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.txt deleted file mode 100644 index 3e4f332..0000000 --- a/kopy-compiler/test-data/box/no-nest-copy-update-no-it.fir.txt +++ /dev/null @@ -1,49 +0,0 @@ -FILE: no-nest-copy-update-no-it.kt - package com.javiersc.kotlin.kopy.playground - - public final fun box(): R|kotlin/String| { - lval house0: R|com/javiersc/kotlin/kopy/playground/House| = R|com/javiersc/kotlin/kopy/playground/House.House|(street = String(Street), squareMeters = Int(20)) - lval house1: R|com/javiersc/kotlin/kopy/playground/House| = R|/house0|.R|SubstitutionOverride|(copy@fun R|com/javiersc/kotlin/kopy/playground/House|.(): R|kotlin/Unit| { - (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { - ^ Int(40) - } - ) - } - ) - lval house2: R|com/javiersc/kotlin/kopy/playground/House| = R|/house0|.R|kotlin/run|( = run@fun R|com/javiersc/kotlin/kopy/playground/House|.(): R|com/javiersc/kotlin/kopy/playground/House| { - lvar tmp0: R|com/javiersc/kotlin/kopy/playground/House| = this@R|special/anonymous| - R|/tmp0| = R|/tmp0|.R|com/javiersc/kotlin/kopy/playground/House.copy|(squareMeters = R|/tmp0|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|.R|kotlin/let|( = let@fun (it: R|kotlin/Int|): R|kotlin/Int| { - ^ Int(40) - } - )) - ^ R|/tmp0| - } - ) - ^box when () { - ==(R|/house1|, R|/house2|) -> { - String(OK) - } - else -> { - (String(Fail: ), Char(10), String(House1: ), R|/house1|, String( ), Char(10), String(House2: ), R|/house2|) - } - } - - } - @R|com/javiersc/kotlin/kopy/Kopy|() internal final data class House : R|kotlin/Any|, R|com/javiersc/kotlin/kopy/runtime/Kopyable| { - public constructor(street: R|kotlin/String|, squareMeters: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/House| { - super() - } - - public final val street: R|kotlin/String| = R|/street| - public get(): R|kotlin/String| - - public final val squareMeters: R|kotlin/Int| = R|/squareMeters| - public get(): R|kotlin/Int| - - public final operator fun component1(): R|kotlin/String| - - public final operator fun component2(): R|kotlin/Int| - - public final fun copy(street: R|kotlin/String| = this@R|com/javiersc/kotlin/kopy/playground/House|.R|com/javiersc/kotlin/kopy/playground/House.street|, squareMeters: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/House|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|): R|com/javiersc/kotlin/kopy/playground/House| - - } diff --git a/kopy-compiler/test-data/box/no-nest-copy-update-no-it.kt b/kopy-compiler/test-data/box/no-nest-copy-update-no-it.kt.disabled similarity index 100% rename from kopy-compiler/test-data/box/no-nest-copy-update-no-it.kt rename to kopy-compiler/test-data/box/no-nest-copy-update-no-it.kt.disabled diff --git a/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.ir.txt b/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.ir.txt deleted file mode 100644 index a49513b..0000000 --- a/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.ir.txt +++ /dev/null @@ -1,246 +0,0 @@ -FILE fqName:com.javiersc.kotlin.kopy.playground fileName:/no-nest-invoke-update-no-it.kt - FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String - BLOCK_BODY - VAR name:house0 type:com.javiersc.kotlin.kopy.playground.House [val] - CONSTRUCTOR_CALL 'public constructor (street: kotlin.String, squareMeters: kotlin.Int) declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - street: CONST String type=kotlin.String value="Street" - squareMeters: CONST Int type=kotlin.Int value=20 - VAR name:house1 type:com.javiersc.kotlin.kopy.playground.House [val] - CALL 'public final fun run (block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.run declared in kotlin' type=com.javiersc.kotlin.kopy.playground.House origin=null - : com.javiersc.kotlin.kopy.playground.House - : com.javiersc.kotlin.kopy.playground.House - $receiver: GET_VAR 'val house0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=VARIABLE_AS_FUNCTION - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:com.javiersc.kotlin.kopy.playground.House) returnType:com.javiersc.kotlin.kopy.playground.House - $receiver: VALUE_PARAMETER name:$this$run type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:com.javiersc.kotlin.kopy.playground.House [var] - GET_VAR '$this$run: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=kotlin.Unit origin=EQ - CALL 'public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - $this: GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - squareMeters: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let declared in kotlin' type=kotlin.Int origin=null - : kotlin.Int - : kotlin.Int - $receiver: CALL 'public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box.' - CONST Int type=kotlin.Int value=40 - RETURN type=kotlin.Nothing from='local final fun (): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' - GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - VAR name:house2 type:com.javiersc.kotlin.kopy.playground.House [val] - CALL 'public final fun run (block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.run declared in kotlin' type=com.javiersc.kotlin.kopy.playground.House origin=null - : com.javiersc.kotlin.kopy.playground.House - : com.javiersc.kotlin.kopy.playground.House - $receiver: GET_VAR 'val house0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:com.javiersc.kotlin.kopy.playground.House) returnType:com.javiersc.kotlin.kopy.playground.House - $receiver: VALUE_PARAMETER name:$this$run type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR name:tmp0 type:com.javiersc.kotlin.kopy.playground.House [var] - GET_VAR '$this$run: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=kotlin.Unit origin=EQ - CALL 'public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - $this: GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - squareMeters: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let declared in kotlin' type=kotlin.Int origin=null - : kotlin.Int - : kotlin.Int - $receiver: CALL 'public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box.' - CONST Int type=kotlin.Int value=40 - RETURN type=kotlin.Nothing from='local final fun (): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' - GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in com.javiersc.kotlin.kopy.playground' - WHEN type=kotlin.String origin=IF - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val house1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_VAR 'val house2: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: CONST String type=kotlin.String value="OK" - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="Fail: \nHouse1: " - GET_VAR 'val house1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=" \nHouse2: " - GET_VAR 'val house2: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - CLASS CLASS name:House modality:FINAL visibility:internal [data] superTypes:[kotlin.Any; com.javiersc.kotlin.kopy.runtime.Kopyable] - annotations: - Kopy - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:com.javiersc.kotlin.kopy.playground.House - CONSTRUCTOR visibility:public <> (street:kotlin.String, squareMeters:kotlin.Int) returnType:com.javiersc.kotlin.kopy.playground.House [primary] - VALUE_PARAMETER name:street index:0 type:kotlin.String - VALUE_PARAMETER name:squareMeters index:1 type:kotlin.Int - BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:House modality:FINAL visibility:internal [data] superTypes:[kotlin.Any; com.javiersc.kotlin.kopy.runtime.Kopyable]' - PROPERTY name:street visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final] - EXPRESSION_BODY - GET_VAR 'street: kotlin.String declared in com.javiersc.kotlin.kopy.playground.House.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String - correspondingProperty: PROPERTY name:street visibility:public modality:FINAL [val] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.' type=com.javiersc.kotlin.kopy.playground.House origin=null - PROPERTY name:squareMeters visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final] - EXPRESSION_BODY - GET_VAR 'squareMeters: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int - correspondingProperty: PROPERTY name:squareMeters visibility:public modality:FINAL [val] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String [operator] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.component1' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:component2 visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int [operator] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun component2 (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.component2' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House, street:kotlin.String, squareMeters:kotlin.Int) returnType:com.javiersc.kotlin.kopy.playground.House - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - VALUE_PARAMETER name:street index:0 type:kotlin.String - EXPRESSION_BODY - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.copy' type=com.javiersc.kotlin.kopy.playground.House origin=null - VALUE_PARAMETER name:squareMeters index:1 type:kotlin.Int - EXPRESSION_BODY - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.copy' type=com.javiersc.kotlin.kopy.playground.House origin=null - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' - CONSTRUCTOR_CALL 'public constructor (street: kotlin.String, squareMeters: kotlin.Int) declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - street: GET_VAR 'street: kotlin.String declared in com.javiersc.kotlin.kopy.playground.House.copy' type=kotlin.String origin=null - squareMeters: GET_VAR 'squareMeters: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.copy' type=kotlin.Int origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="House(" - CONST String type=kotlin.String value="street=" - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.toString' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=", " - CONST String type=kotlin.String value="squareMeters=" - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.toString' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=")" - FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR name:result type:kotlin.Int [var] - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Unit origin=EQ - CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: GET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Int origin=null - other: CONST Int type=kotlin.Int value=31 - other: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=com.javiersc.kotlin.kopy.playground.House origin=null - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Int origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ - arg0: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=true - WHEN type=kotlin.Unit origin=null - BRANCH - if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=com.javiersc.kotlin.kopy.playground.House - GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:com.javiersc.kotlin.kopy.playground.House [val] - TYPE_OP type=com.javiersc.kotlin.kopy.playground.House origin=CAST typeOperand=com.javiersc.kotlin.kopy.playground.House - GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR 'val tmp_1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR 'val tmp_1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=true - FUN FAKE_OVERRIDE name:copy visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, kopy:@[ExtensionFunctionType] kotlin.Function1) returnType:com.javiersc.kotlin.kopy.playground.House [fake_override,infix] - annotations: - KopyFunctionInvoke - overridden: - public open fun copy (kopy: @[ExtensionFunctionType] kotlin.Function1): T of com.javiersc.kotlin.kopy.runtime.Kopyable declared in com.javiersc.kotlin.kopy.runtime.Kopyable - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - VALUE_PARAMETER name:kopy index:0 type:@[ExtensionFunctionType] kotlin.Function1 - FUN FAKE_OVERRIDE name:invoke visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, kopy:@[ExtensionFunctionType] kotlin.Function1) returnType:com.javiersc.kotlin.kopy.playground.House [fake_override,operator,infix] - annotations: - KopyFunctionInvoke - overridden: - public open fun invoke (kopy: @[ExtensionFunctionType] kotlin.Function1): T of com.javiersc.kotlin.kopy.runtime.Kopyable declared in com.javiersc.kotlin.kopy.runtime.Kopyable - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - VALUE_PARAMETER name:kopy index:0 type:@[ExtensionFunctionType] kotlin.Function1 - FUN FAKE_OVERRIDE name:set visibility:public modality:OPEN ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, $receiver:R of com.javiersc.kotlin.kopy.playground.House.set, other:R of com.javiersc.kotlin.kopy.playground.House.set) returnType:R of com.javiersc.kotlin.kopy.playground.House.set [fake_override,infix] - annotations: - KopyFunctionSet - overridden: - public open fun set (other: R of com.javiersc.kotlin.kopy.runtime.Kopyable.set): R of com.javiersc.kotlin.kopy.runtime.Kopyable.set declared in com.javiersc.kotlin.kopy.runtime.Kopyable - TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?] reified:false - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - $receiver: VALUE_PARAMETER name: type:R of com.javiersc.kotlin.kopy.playground.House.set - VALUE_PARAMETER name:other index:0 type:R of com.javiersc.kotlin.kopy.playground.House.set - FUN FAKE_OVERRIDE name:update visibility:public modality:OPEN ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, $receiver:R of com.javiersc.kotlin.kopy.playground.House.update, other:kotlin.Function1) returnType:R of com.javiersc.kotlin.kopy.playground.House.update [fake_override,infix] - annotations: - KopyFunctionUpdate - overridden: - public open fun update (other: kotlin.Function1): R of com.javiersc.kotlin.kopy.runtime.Kopyable.update declared in com.javiersc.kotlin.kopy.runtime.Kopyable - TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?] reified:false - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - $receiver: VALUE_PARAMETER name: type:R of com.javiersc.kotlin.kopy.playground.House.update - VALUE_PARAMETER name:other index:0 type:kotlin.Function1 -FILE fqName: fileName:/SomeFile.kt diff --git a/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.txt b/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.txt deleted file mode 100644 index b176940..0000000 --- a/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.fir.txt +++ /dev/null @@ -1,49 +0,0 @@ -FILE: no-nest-invoke-update-no-it.kt - package com.javiersc.kotlin.kopy.playground - - public final fun box(): R|kotlin/String| { - lval house0: R|com/javiersc/kotlin/kopy/playground/House| = R|com/javiersc/kotlin/kopy/playground/House.House|(street = String(Street), squareMeters = Int(20)) - lval house1: R|com/javiersc/kotlin/kopy/playground/House| = R|/house0|.R|SubstitutionOverride|( = house0@fun R|com/javiersc/kotlin/kopy/playground/House|.(): R|kotlin/Unit| { - (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { - ^ Int(40) - } - ) - } - ) - lval house2: R|com/javiersc/kotlin/kopy/playground/House| = R|/house0|.R|kotlin/run|( = run@fun R|com/javiersc/kotlin/kopy/playground/House|.(): R|com/javiersc/kotlin/kopy/playground/House| { - lvar tmp0: R|com/javiersc/kotlin/kopy/playground/House| = this@R|special/anonymous| - R|/tmp0| = R|/tmp0|.R|com/javiersc/kotlin/kopy/playground/House.copy|(squareMeters = R|/tmp0|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|.R|kotlin/let|( = let@fun (it: R|kotlin/Int|): R|kotlin/Int| { - ^ Int(40) - } - )) - ^ R|/tmp0| - } - ) - ^box when () { - ==(R|/house1|, R|/house2|) -> { - String(OK) - } - else -> { - (String(Fail: ), Char(10), String(House1: ), R|/house1|, String( ), Char(10), String(House2: ), R|/house2|) - } - } - - } - @R|com/javiersc/kotlin/kopy/Kopy|() internal final data class House : R|kotlin/Any|, R|com/javiersc/kotlin/kopy/runtime/Kopyable| { - public constructor(street: R|kotlin/String|, squareMeters: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/House| { - super() - } - - public final val street: R|kotlin/String| = R|/street| - public get(): R|kotlin/String| - - public final val squareMeters: R|kotlin/Int| = R|/squareMeters| - public get(): R|kotlin/Int| - - public final operator fun component1(): R|kotlin/String| - - public final operator fun component2(): R|kotlin/Int| - - public final fun copy(street: R|kotlin/String| = this@R|com/javiersc/kotlin/kopy/playground/House|.R|com/javiersc/kotlin/kopy/playground/House.street|, squareMeters: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/House|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|): R|com/javiersc/kotlin/kopy/playground/House| - - } diff --git a/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.kt b/kopy-compiler/test-data/box/no-nest-invoke-update-no-it.kt.disabled similarity index 100% rename from kopy-compiler/test-data/box/no-nest-invoke-update-no-it.kt rename to kopy-compiler/test-data/box/no-nest-invoke-update-no-it.kt.disabled diff --git a/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.ir.txt b/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.ir.txt deleted file mode 100644 index 70ca699..0000000 --- a/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.ir.txt +++ /dev/null @@ -1,250 +0,0 @@ -FILE fqName:com.javiersc.kotlin.kopy.playground fileName:/no-nest-invoke-update-with-it.kt - FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String - BLOCK_BODY - VAR name:house0 type:com.javiersc.kotlin.kopy.playground.House [val] - CONSTRUCTOR_CALL 'public constructor (street: kotlin.String, squareMeters: kotlin.Int) declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - street: CONST String type=kotlin.String value="Street" - squareMeters: CONST Int type=kotlin.Int value=20 - VAR name:house1 type:com.javiersc.kotlin.kopy.playground.House [val] - CALL 'public final fun run (block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.run declared in kotlin' type=com.javiersc.kotlin.kopy.playground.House origin=null - : com.javiersc.kotlin.kopy.playground.House - : com.javiersc.kotlin.kopy.playground.House - $receiver: GET_VAR 'val house0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=VARIABLE_AS_FUNCTION - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:com.javiersc.kotlin.kopy.playground.House) returnType:com.javiersc.kotlin.kopy.playground.House - $receiver: VALUE_PARAMETER name:$this$run type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:com.javiersc.kotlin.kopy.playground.House [var] - GET_VAR '$this$run: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=kotlin.Unit origin=EQ - CALL 'public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - $this: GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - squareMeters: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let declared in kotlin' type=kotlin.Int origin=null - : kotlin.Int - : kotlin.Int - $receiver: CALL 'public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box.' - CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=PLUS - $this: GET_VAR 'it: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box..' type=kotlin.Int origin=null - other: CONST Int type=kotlin.Int value=20 - RETURN type=kotlin.Nothing from='local final fun (): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' - GET_VAR 'var tmp_0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - VAR name:house2 type:com.javiersc.kotlin.kopy.playground.House [val] - CALL 'public final fun run (block: @[ExtensionFunctionType] kotlin.Function1): R of kotlin.run declared in kotlin' type=com.javiersc.kotlin.kopy.playground.House origin=null - : com.javiersc.kotlin.kopy.playground.House - : com.javiersc.kotlin.kopy.playground.House - $receiver: GET_VAR 'val house0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=@[ExtensionFunctionType] kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:com.javiersc.kotlin.kopy.playground.House) returnType:com.javiersc.kotlin.kopy.playground.House - $receiver: VALUE_PARAMETER name:$this$run type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR name:tmp0 type:com.javiersc.kotlin.kopy.playground.House [var] - GET_VAR '$this$run: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=kotlin.Unit origin=EQ - CALL 'public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - $this: GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - squareMeters: CALL 'public final fun let (block: kotlin.Function1): R of kotlin.let declared in kotlin' type=kotlin.Int origin=null - : kotlin.Int - : kotlin.Int - $receiver: CALL 'public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' type=kotlin.Int origin=GET_PROPERTY - $this: GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - block: FUN_EXPR type=kotlin.Function1 origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.Int) returnType:kotlin.Int - VALUE_PARAMETER name:it index:0 type:kotlin.Int - BLOCK_BODY - RETURN type=kotlin.Nothing from='local final fun (it: kotlin.Int): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box.' - CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=PLUS - $this: GET_VAR 'it: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.box..' type=kotlin.Int origin=null - other: CONST Int type=kotlin.Int value=20 - RETURN type=kotlin.Nothing from='local final fun (): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' - GET_VAR 'var tmp0: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box.' type=com.javiersc.kotlin.kopy.playground.House origin=null - RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in com.javiersc.kotlin.kopy.playground' - WHEN type=kotlin.String origin=IF - BRANCH - if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val house1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_VAR 'val house2: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: CONST String type=kotlin.String value="OK" - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="Fail: \nHouse1: " - GET_VAR 'val house1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=" \nHouse2: " - GET_VAR 'val house2: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.box' type=com.javiersc.kotlin.kopy.playground.House origin=null - CLASS CLASS name:House modality:FINAL visibility:internal [data] superTypes:[kotlin.Any; com.javiersc.kotlin.kopy.runtime.Kopyable] - annotations: - Kopy - $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:com.javiersc.kotlin.kopy.playground.House - CONSTRUCTOR visibility:public <> (street:kotlin.String, squareMeters:kotlin.Int) returnType:com.javiersc.kotlin.kopy.playground.House [primary] - VALUE_PARAMETER name:street index:0 type:kotlin.String - VALUE_PARAMETER name:squareMeters index:1 type:kotlin.Int - BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' - INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:House modality:FINAL visibility:internal [data] superTypes:[kotlin.Any; com.javiersc.kotlin.kopy.runtime.Kopyable]' - PROPERTY name:street visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final] - EXPRESSION_BODY - GET_VAR 'street: kotlin.String declared in com.javiersc.kotlin.kopy.playground.House.' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String - correspondingProperty: PROPERTY name:street visibility:public modality:FINAL [val] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.' type=com.javiersc.kotlin.kopy.playground.House origin=null - PROPERTY name:squareMeters visibility:public modality:FINAL [val] - FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final] - EXPRESSION_BODY - GET_VAR 'squareMeters: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER - FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int - correspondingProperty: PROPERTY name:squareMeters visibility:public modality:FINAL [val] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String [operator] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.component1' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:component2 visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int [operator] - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun component2 (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.component2' type=com.javiersc.kotlin.kopy.playground.House origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:com.javiersc.kotlin.kopy.playground.House, street:kotlin.String, squareMeters:kotlin.Int) returnType:com.javiersc.kotlin.kopy.playground.House - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - VALUE_PARAMETER name:street index:0 type:kotlin.String - EXPRESSION_BODY - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.copy' type=com.javiersc.kotlin.kopy.playground.House origin=null - VALUE_PARAMETER name:squareMeters index:1 type:kotlin.Int - EXPRESSION_BODY - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.copy' type=com.javiersc.kotlin.kopy.playground.House origin=null - BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun copy (street: kotlin.String, squareMeters: kotlin.Int): com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House' - CONSTRUCTOR_CALL 'public constructor (street: kotlin.String, squareMeters: kotlin.Int) declared in com.javiersc.kotlin.kopy.playground.House' type=com.javiersc.kotlin.kopy.playground.House origin=null - street: GET_VAR 'street: kotlin.String declared in com.javiersc.kotlin.kopy.playground.House.copy' type=kotlin.String origin=null - squareMeters: GET_VAR 'squareMeters: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.copy' type=kotlin.Int origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.String - overridden: - public open fun toString (): kotlin.String declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in com.javiersc.kotlin.kopy.playground.House' - STRING_CONCATENATION type=kotlin.String - CONST String type=kotlin.String value="House(" - CONST String type=kotlin.String value="street=" - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.toString' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=", " - CONST String type=kotlin.String value="squareMeters=" - GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.toString' type=com.javiersc.kotlin.kopy.playground.House origin=null - CONST String type=kotlin.String value=")" - FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House) returnType:kotlin.Int - overridden: - public open fun hashCode (): kotlin.Int declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - BLOCK_BODY - VAR name:result type:kotlin.Int [var] - CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.String' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=com.javiersc.kotlin.kopy.playground.House origin=null - SET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Unit origin=EQ - CALL 'public final fun plus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: CALL 'public final fun times (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: GET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Int origin=null - other: CONST Int type=kotlin.Int value=31 - other: CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=null - $this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=com.javiersc.kotlin.kopy.playground.House origin=null - RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House' - GET_VAR 'var result: kotlin.Int declared in com.javiersc.kotlin.kopy.playground.House.hashCode' type=kotlin.Int origin=null - FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.playground.House, other:kotlin.Any?) returnType:kotlin.Boolean [operator] - overridden: - public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.playground.House - VALUE_PARAMETER name:other index:0 type:kotlin.Any? - BLOCK_BODY - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ - arg0: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=true - WHEN type=kotlin.Unit origin=null - BRANCH - if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=com.javiersc.kotlin.kopy.playground.House - GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:com.javiersc.kotlin.kopy.playground.House [val] - TYPE_OP type=com.javiersc.kotlin.kopy.playground.House origin=CAST typeOperand=com.javiersc.kotlin.kopy.playground.House - GET_VAR 'other: kotlin.Any? declared in com.javiersc.kotlin.kopy.playground.House.equals' type=kotlin.Any? origin=null - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:street type:kotlin.String visibility:private [final]' type=kotlin.String origin=null - receiver: GET_VAR 'val tmp_1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - WHEN type=kotlin.Unit origin=null - BRANCH - if: CALL 'public final fun not (): kotlin.Boolean declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ - $this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ - arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR ': com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:squareMeters type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null - receiver: GET_VAR 'val tmp_1: com.javiersc.kotlin.kopy.playground.House declared in com.javiersc.kotlin.kopy.playground.House.equals' type=com.javiersc.kotlin.kopy.playground.House origin=null - then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=false - RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in com.javiersc.kotlin.kopy.playground.House' - CONST Boolean type=kotlin.Boolean value=true - FUN FAKE_OVERRIDE name:copy visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, kopy:@[ExtensionFunctionType] kotlin.Function1) returnType:com.javiersc.kotlin.kopy.playground.House [fake_override,infix] - annotations: - KopyFunctionInvoke - overridden: - public open fun copy (kopy: @[ExtensionFunctionType] kotlin.Function1): T of com.javiersc.kotlin.kopy.runtime.Kopyable declared in com.javiersc.kotlin.kopy.runtime.Kopyable - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - VALUE_PARAMETER name:kopy index:0 type:@[ExtensionFunctionType] kotlin.Function1 - FUN FAKE_OVERRIDE name:invoke visibility:public modality:OPEN <> ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, kopy:@[ExtensionFunctionType] kotlin.Function1) returnType:com.javiersc.kotlin.kopy.playground.House [fake_override,operator,infix] - annotations: - KopyFunctionInvoke - overridden: - public open fun invoke (kopy: @[ExtensionFunctionType] kotlin.Function1): T of com.javiersc.kotlin.kopy.runtime.Kopyable declared in com.javiersc.kotlin.kopy.runtime.Kopyable - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - VALUE_PARAMETER name:kopy index:0 type:@[ExtensionFunctionType] kotlin.Function1 - FUN FAKE_OVERRIDE name:set visibility:public modality:OPEN ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, $receiver:R of com.javiersc.kotlin.kopy.playground.House.set, other:R of com.javiersc.kotlin.kopy.playground.House.set) returnType:R of com.javiersc.kotlin.kopy.playground.House.set [fake_override,infix] - annotations: - KopyFunctionSet - overridden: - public open fun set (other: R of com.javiersc.kotlin.kopy.runtime.Kopyable.set): R of com.javiersc.kotlin.kopy.runtime.Kopyable.set declared in com.javiersc.kotlin.kopy.runtime.Kopyable - TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?] reified:false - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - $receiver: VALUE_PARAMETER name: type:R of com.javiersc.kotlin.kopy.playground.House.set - VALUE_PARAMETER name:other index:0 type:R of com.javiersc.kotlin.kopy.playground.House.set - FUN FAKE_OVERRIDE name:update visibility:public modality:OPEN ($this:com.javiersc.kotlin.kopy.runtime.Kopyable, $receiver:R of com.javiersc.kotlin.kopy.playground.House.update, other:kotlin.Function1) returnType:R of com.javiersc.kotlin.kopy.playground.House.update [fake_override,infix] - annotations: - KopyFunctionUpdate - overridden: - public open fun update (other: kotlin.Function1): R of com.javiersc.kotlin.kopy.runtime.Kopyable.update declared in com.javiersc.kotlin.kopy.runtime.Kopyable - TYPE_PARAMETER name:R index:0 variance: superTypes:[kotlin.Any?] reified:false - $this: VALUE_PARAMETER name: type:com.javiersc.kotlin.kopy.runtime.Kopyable - $receiver: VALUE_PARAMETER name: type:R of com.javiersc.kotlin.kopy.playground.House.update - VALUE_PARAMETER name:other index:0 type:kotlin.Function1 -FILE fqName: fileName:/SomeFile.kt diff --git a/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.txt b/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.txt deleted file mode 100644 index 7ca31d7..0000000 --- a/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.fir.txt +++ /dev/null @@ -1,49 +0,0 @@ -FILE: no-nest-invoke-update-with-it.kt - package com.javiersc.kotlin.kopy.playground - - public final fun box(): R|kotlin/String| { - lval house0: R|com/javiersc/kotlin/kopy/playground/House| = R|com/javiersc/kotlin/kopy/playground/House.House|(street = String(Street), squareMeters = Int(20)) - lval house1: R|com/javiersc/kotlin/kopy/playground/House| = R|/house0|.R|SubstitutionOverride|( = house0@fun R|com/javiersc/kotlin/kopy/playground/House|.(): R|kotlin/Unit| { - (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { - ^ R|/it|.R|kotlin/Int.plus|(Int(20)) - } - ) - } - ) - lval house2: R|com/javiersc/kotlin/kopy/playground/House| = R|/house0|.R|kotlin/run|( = run@fun R|com/javiersc/kotlin/kopy/playground/House|.(): R|com/javiersc/kotlin/kopy/playground/House| { - lvar tmp0: R|com/javiersc/kotlin/kopy/playground/House| = this@R|special/anonymous| - R|/tmp0| = R|/tmp0|.R|com/javiersc/kotlin/kopy/playground/House.copy|(squareMeters = R|/tmp0|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|.R|kotlin/let|( = let@fun (it: R|kotlin/Int|): R|kotlin/Int| { - ^ R|/it|.R|kotlin/Int.plus|(Int(20)) - } - )) - ^ R|/tmp0| - } - ) - ^box when () { - ==(R|/house1|, R|/house2|) -> { - String(OK) - } - else -> { - (String(Fail: ), Char(10), String(House1: ), R|/house1|, String( ), Char(10), String(House2: ), R|/house2|) - } - } - - } - @R|com/javiersc/kotlin/kopy/Kopy|() internal final data class House : R|kotlin/Any|, R|com/javiersc/kotlin/kopy/runtime/Kopyable| { - public constructor(street: R|kotlin/String|, squareMeters: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/House| { - super() - } - - public final val street: R|kotlin/String| = R|/street| - public get(): R|kotlin/String| - - public final val squareMeters: R|kotlin/Int| = R|/squareMeters| - public get(): R|kotlin/Int| - - public final operator fun component1(): R|kotlin/String| - - public final operator fun component2(): R|kotlin/Int| - - public final fun copy(street: R|kotlin/String| = this@R|com/javiersc/kotlin/kopy/playground/House|.R|com/javiersc/kotlin/kopy/playground/House.street|, squareMeters: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/House|.R|com/javiersc/kotlin/kopy/playground/House.squareMeters|): R|com/javiersc/kotlin/kopy/playground/House| - - } diff --git a/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.kt b/kopy-compiler/test-data/box/no-nest-invoke-update-with-it.kt.disabled similarity index 100% rename from kopy-compiler/test-data/box/no-nest-invoke-update-with-it.kt rename to kopy-compiler/test-data/box/no-nest-invoke-update-with-it.kt.disabled diff --git a/kopy-compiler/test-data/box/no-nest-kopy-complex-tree-set-calculated.kt.disabled b/kopy-compiler/test-data/box/no-nest-kopy-complex-tree-set-calculated.kt.disabled new file mode 100644 index 0000000..3a15617 --- /dev/null +++ b/kopy-compiler/test-data/box/no-nest-kopy-complex-tree-set-calculated.kt.disabled @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -MISSING_DEPENDENCY_SUPERCLASS -INVISIBLE_REFERENCE + +@file:Suppress("DEPRECATION_ERROR") + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy +import com.javiersc.kotlin.kopy.runtime.KopyableScope + +fun box(): String { + val a: A = A(B(C(10), D(20)), C(30), D(40)) + val a1: A = a kopy { b.c.value.set(30) } + val a11: A = a kopy { b.apply { c.value.set(30) } } + val a2: A = a.copy(b = a.b.copy(c = a.b.c.copy(value = 30))) + return if (a1 == a2) "OK" else "Fail: $a1 | $a2" +} + +@Kopy data class A(val b: B, val c: C, val d: D) +@Kopy data class B(val c: C, val d: D) +@Kopy data class C(val value: Int) +@Kopy data class D(val value: Int) diff --git a/kopy-compiler/test-data/box/no-nest-kopy-set-calculated.kt.disabled b/kopy-compiler/test-data/box/no-nest-kopy-set-calculated.kt.disabled new file mode 100644 index 0000000..1800000 --- /dev/null +++ b/kopy-compiler/test-data/box/no-nest-kopy-set-calculated.kt.disabled @@ -0,0 +1,17 @@ +// !DIAGNOSTICS: -MISSING_DEPENDENCY_SUPERCLASS -INVISIBLE_REFERENCE + +@file:Suppress("DEPRECATION_ERROR") + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy +import com.javiersc.kotlin.kopy.runtime.KopyableScope + +fun box(): String { + val house: House = House(street = "Street", squareMeters = 20) + val house1: House = house kopy { squareMeters.set(30) } + val house2: House = house.copy(squareMeters = 30) + return if (house1 == house2) "OK" else "Fail: $house1 | $house2" +} + +@Kopy data class House(val street: String, val squareMeters: Int) diff --git a/kopy-compiler/test-data/box/no-nest-kopy-set.kt.disabled b/kopy-compiler/test-data/box/no-nest-kopy-set.kt.disabled new file mode 100644 index 0000000..e2cbb7f --- /dev/null +++ b/kopy-compiler/test-data/box/no-nest-kopy-set.kt.disabled @@ -0,0 +1,35 @@ +// !DIAGNOSTICS: -MISSING_DEPENDENCY_SUPERCLASS -INVISIBLE_REFERENCE + +@file:Suppress("DEPRECATION_ERROR") + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy +import com.javiersc.kotlin.kopy.runtime.KopyableScope + +fun box(): String { + val house: House = House(street = "Street", squareMeters = 20) + val house2: House2 = House2(street = "Street", squareMeters = 20) + val houseCopied: House = house kopy { squareMeters.set(30) } + val house2Copied: House2 = + house2 kopy2 { + squareMeters.set2( + 30.also { setKopyableReference(getKopyableReference().copy(squareMeters = it)) } + ) + } + return "OK" +} + +@Kopy data class House(val street: String, val squareMeters: Int) + +data class House2(val street: String, val squareMeters: Int) { + + infix fun kopy2(kopy: context(KopyableScope) House2.() -> Unit): House2 { + val scope = KopyableScope(this) + kopy(scope, scope.getKopyableReference()) + return scope.getKopyableReference() + } + + context(KopyableScope) + infix fun D.set2(other: D): Unit = Unit +} diff --git a/kopy-compiler/test-data/box/no-nest-kopy.kt.disabled b/kopy-compiler/test-data/box/no-nest-kopy.kt.disabled new file mode 100644 index 0000000..df6d013 --- /dev/null +++ b/kopy-compiler/test-data/box/no-nest-kopy.kt.disabled @@ -0,0 +1,30 @@ +// !DIAGNOSTICS: -MISSING_DEPENDENCY_SUPERCLASS -INVISIBLE_REFERENCE + +@file:Suppress("DEPRECATION_ERROR") + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy +import com.javiersc.kotlin.kopy.runtime.KopyableScope + +fun box(): String { + val house0: House = House(street = "Street", squareMeters = 20) + val house00: House2 = House2(street = "Street", squareMeters = 20) + val house1: House = house0 kopy { } + val house11: House2 = house00 kopy2 { } + return "OK" +} + +@Kopy data class House(val street: String, val squareMeters: Int) + +data class House2(val street: String, val squareMeters: Int) { + + infix fun kopy2(kopy: context(KopyableScope) House2.() -> Unit): House2 { + val scope = KopyableScope(this) + kopy(scope, scope.getKopyableReference()) + return scope.getKopyableReference() + } + + context(KopyableScope) + infix fun D.set2(other: D): Unit = Unit +} diff --git a/kopy-compiler/test-data/diagnostics/.empty b/kopy-compiler/test-data/diagnostics/.empty deleted file mode 100644 index e69de29..0000000 diff --git a/kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.fir.txt b/kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.fir.txt new file mode 100644 index 0000000..b39fb27 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.fir.txt @@ -0,0 +1,122 @@ +FILE: complex-1.kt + package com.javiersc.kotlin.kopy.playground + + public final fun diagnostics(): R|kotlin/Unit| { + lval qux0: R|com/javiersc/kotlin/kopy/playground/Qux| = R|com/javiersc/kotlin/kopy/playground/Qux.Qux|(number = Int(7)) + lval baz0: R|com/javiersc/kotlin/kopy/playground/Baz| = R|com/javiersc/kotlin/kopy/playground/Baz.Baz|(qux = R|/qux0|, text = String(Random)) + lval bar0: R|com/javiersc/kotlin/kopy/playground/Bar| = R|com/javiersc/kotlin/kopy/playground/Bar.Bar|(baz = R|/baz0|, isValid = Boolean(true)) + lval foo0: R|com/javiersc/kotlin/kopy/playground/Foo| = R|com/javiersc/kotlin/kopy/playground/Foo.Foo|(bar = R|/bar0|, letter = Char(W)) + lval foo10: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, R|/bar0|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(42)) + } + ) + lval foo11: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, R|/bar0|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(42)) + } + ) + lval foo20: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|kotlin/apply|( = apply@fun R|com/javiersc/kotlin/kopy/playground/Baz|.(): R|kotlin/Unit| { + ^@apply Unit + } + ).R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(42)) + } + ) + lval foo21: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|kotlin/apply|( = apply@fun R|com/javiersc/kotlin/kopy/playground/Baz|.(): R|kotlin/Unit| { + ^@apply Unit + } + ).R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(42)) + } + ) + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Qux : R|kotlin/Any| { + public constructor(number: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/Qux| { + super() + } + + public final val number: R|kotlin/Int| = R|/number| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(number: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/Qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|): R|com/javiersc/kotlin/kopy/playground/Qux| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Baz : R|kotlin/Any| { + public constructor(qux: R|com/javiersc/kotlin/kopy/playground/Qux|, text: R|kotlin/String|): R|com/javiersc/kotlin/kopy/playground/Baz| { + super() + } + + public final val qux: R|com/javiersc/kotlin/kopy/playground/Qux| = R|/qux| + public get(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final val text: R|kotlin/String| = R|/text| + public get(): R|kotlin/String| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final operator fun component2(): R|kotlin/String| + + public final fun copy(qux: R|com/javiersc/kotlin/kopy/playground/Qux| = this@R|com/javiersc/kotlin/kopy/playground/Baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|, text: R|kotlin/String| = this@R|com/javiersc/kotlin/kopy/playground/Baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|): R|com/javiersc/kotlin/kopy/playground/Baz| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Bar : R|kotlin/Any| { + public constructor(baz: R|com/javiersc/kotlin/kopy/playground/Baz|, isValid: R|kotlin/Boolean|): R|com/javiersc/kotlin/kopy/playground/Bar| { + super() + } + + public final val baz: R|com/javiersc/kotlin/kopy/playground/Baz| = R|/baz| + public get(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final val isValid: R|kotlin/Boolean| = R|/isValid| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final operator fun component2(): R|kotlin/Boolean| + + public final fun copy(baz: R|com/javiersc/kotlin/kopy/playground/Baz| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|, isValid: R|kotlin/Boolean| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|): R|com/javiersc/kotlin/kopy/playground/Bar| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Foo : R|kotlin/Any| { + public constructor(bar: R|com/javiersc/kotlin/kopy/playground/Bar|, letter: R|kotlin/Char|): R|com/javiersc/kotlin/kopy/playground/Foo| { + super() + } + + public final val bar: R|com/javiersc/kotlin/kopy/playground/Bar| = R|/bar| + public get(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final val letter: R|kotlin/Char| = R|/letter| + public get(): R|kotlin/Char| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final operator fun component2(): R|kotlin/Char| + + public final fun copy(bar: R|com/javiersc/kotlin/kopy/playground/Bar| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|, letter: R|kotlin/Char| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.letter|): R|com/javiersc/kotlin/kopy/playground/Foo| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + } diff --git a/kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.kt b/kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.kt new file mode 100644 index 0000000..ecd35a2 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/invalid-call-chain/complex-1.kt @@ -0,0 +1,24 @@ +// !LANGUAGE: +ContextReceivers +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -MISSING_DEPENDENCY_CLASS -MISSING_DEPENDENCY_SUPERCLASS + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy + +fun diagnostics() { + val qux0 = Qux(number = 7) + val baz0 = Baz(qux = qux0, text = "Random") + val bar0 = Bar(baz = baz0, isValid = true) + val foo0 = Foo(bar = bar0, letter = 'W') + + val foo10 = foo0 { bar0.baz.qux.number.set(42) } + val foo11 = foo0 copy { bar0.baz.qux.number.set(42) } + + val foo20 = foo0 { bar.baz.apply {}.qux.number.set(42) } + val foo21 = foo0 copy { bar.baz.apply {}.qux.number.set(42) } +} + +@Kopy data class Qux(val number: Int) +@Kopy data class Baz(val qux: Qux, val text: String) +@Kopy data class Bar(val baz: Baz, val isValid: Boolean) +@Kopy data class Foo(val bar: Bar, val letter: Char) diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.fir.txt b/kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.fir.txt new file mode 100644 index 0000000..bb03413 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.fir.txt @@ -0,0 +1,167 @@ +FILE: complex-1.kt + package com.javiersc.kotlin.kopy.playground + + public final fun diagnostics(): R|kotlin/Unit| { + lval qux0: R|com/javiersc/kotlin/kopy/playground/Qux| = R|com/javiersc/kotlin/kopy/playground/Qux.Qux|(number = Int(7)) + lval baz0: R|com/javiersc/kotlin/kopy/playground/Baz| = R|com/javiersc/kotlin/kopy/playground/Baz.Baz|(qux = R|/qux0|, text = String(Random)) + lval bar0: R|com/javiersc/kotlin/kopy/playground/Bar| = R|com/javiersc/kotlin/kopy/playground/Bar.Bar|(baz = R|/baz0|, isValid = Boolean(true)) + lval foo0: R|com/javiersc/kotlin/kopy/playground/Foo| = R|com/javiersc/kotlin/kopy/playground/Foo.Foo|(bar = R|/bar0|, letter = Char(W)) + lval foo10: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + ^@foo0 Unit + } + ) + lval foo11: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + ^@copy Unit + } + ) + lval foo20: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + } + ) + lval foo21: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + } + ) + lval foo30: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/Int.plus|(Int(10)) + } + ) + } + ) + lval foo31: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/Int.plus|(Int(10)) + } + ) + } + ) + lval foo40: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|(String(Random 2)) + } + ) + lval foo41: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|(String(Random 2)) + } + ) + lval foo50: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/String|): R|kotlin/String| { + ^ R|/it|.R|kotlin/String.plus|(String( 2)) + } + ) + } + ) + lval foo51: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/String|): R|kotlin/String| { + ^ R|/it|.R|kotlin/String.plus|(String( 2)) + } + ) + } + ) + lval foo60: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/String|): R|kotlin/String| { + ^ (R|/it|, String( Random 2)) + } + ) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|).R|SubstitutionOverride|(Boolean(false)) + } + ) + lval foo61: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/Int.plus|(Int(10)) + } + ) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|(String(Random 2)) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Boolean|): R|kotlin/Boolean| { + ^ R|/it|.R|kotlin/Boolean.not|() + } + ) + } + ) + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Qux : R|kotlin/Any| { + public constructor(number: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/Qux| { + super() + } + + public final val number: R|kotlin/Int| = R|/number| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(number: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/Qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|): R|com/javiersc/kotlin/kopy/playground/Qux| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final class Baz : R|kotlin/Any| { + public constructor(qux: R|com/javiersc/kotlin/kopy/playground/Qux|, text: R|kotlin/String|): R|com/javiersc/kotlin/kopy/playground/Baz| { + super() + } + + public final val qux: R|com/javiersc/kotlin/kopy/playground/Qux| = R|/qux| + public get(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final val text: R|kotlin/String| = R|/text| + public get(): R|kotlin/String| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Bar : R|kotlin/Any| { + public constructor(baz: R|com/javiersc/kotlin/kopy/playground/Baz|, isValid: R|kotlin/Boolean|): R|com/javiersc/kotlin/kopy/playground/Bar| { + super() + } + + public final val baz: R|com/javiersc/kotlin/kopy/playground/Baz| = R|/baz| + public get(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final val isValid: R|kotlin/Boolean| = R|/isValid| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final operator fun component2(): R|kotlin/Boolean| + + public final fun copy(baz: R|com/javiersc/kotlin/kopy/playground/Baz| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|, isValid: R|kotlin/Boolean| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|): R|com/javiersc/kotlin/kopy/playground/Bar| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Foo : R|kotlin/Any| { + public constructor(bar: R|com/javiersc/kotlin/kopy/playground/Bar|, letter: R|kotlin/Char|): R|com/javiersc/kotlin/kopy/playground/Foo| { + super() + } + + public final val bar: R|com/javiersc/kotlin/kopy/playground/Bar| = R|/bar| + public get(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final val letter: R|kotlin/Char| = R|/letter| + public get(): R|kotlin/Char| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final operator fun component2(): R|kotlin/Char| + + public final fun copy(bar: R|com/javiersc/kotlin/kopy/playground/Bar| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|, letter: R|kotlin/Char| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.letter|): R|com/javiersc/kotlin/kopy/playground/Foo| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + } diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.kt b/kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.kt new file mode 100644 index 0000000..73a5d5c --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/complex-1.kt @@ -0,0 +1,45 @@ +// !LANGUAGE: +ContextReceivers +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -MISSING_DEPENDENCY_CLASS -MISSING_DEPENDENCY_SUPERCLASS + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy + +fun diagnostics() { + val qux0 = Qux(number = 7) + val baz0 = Baz(qux = qux0, text = "Random") + val bar0 = Bar(baz = baz0, isValid = true) + val foo0 = Foo(bar = bar0, letter = 'W') + + val foo10 = foo0 {} + val foo11 = foo0 copy {} + + val foo20 = foo0 { bar.baz.qux.number.set(10) } + val foo21 = foo0 copy { bar.baz.qux.number.set(10) } + + val foo30 = foo0 { bar.baz.qux.number.update { it + 10 } } + val foo31 = foo0 copy { bar.baz.qux.number.update { it + 10 } } + + val foo40 = foo0 { bar.baz.text.set("Random 2") } + val foo41 = foo0 copy { bar.baz.text.set("Random 2") } + + val foo50 = foo0 { bar.baz.text.update { it + " 2" } } + val foo51 = foo0 copy { bar.baz.text.update { it + " 2" } } + + val foo60 = foo0 { + bar.baz.qux.number.set(10) + bar.baz.text.update { "$it Random 2" } + bar.isValid.set(false) + } + + val foo61 = foo0 { + bar.baz.qux.number.update {it + 10 } + bar.baz.text.set("Random 2") + bar.isValid.update { !it } + } +} + +@Kopy data class Qux(val number: Int) +@Kopy class Baz(val qux: Qux, val text: String) +@Kopy data class Bar(val baz: Baz, val isValid: Boolean) +@Kopy data class Foo(val bar: Bar, val letter: Char) diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.fir.txt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.fir.txt new file mode 100644 index 0000000..ab75642 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.fir.txt @@ -0,0 +1,101 @@ +FILE: simple-1.kt + package com.javiersc.kotlin.kopy.playground + + public final fun diagnostics(): R|kotlin/Unit| { + lval qux0: R|com/javiersc/kotlin/kopy/playground/Qux| = R|com/javiersc/kotlin/kopy/playground/Qux.Qux|(number = Int(7)) + lval baz0: R|com/javiersc/kotlin/kopy/playground/Baz| = R|com/javiersc/kotlin/kopy/playground/Baz.Baz|(qux = R|/qux0|, text = String(Random)) + lval bar0: R|com/javiersc/kotlin/kopy/playground/Bar| = R|com/javiersc/kotlin/kopy/playground/Bar.Bar|(baz = R|/baz0|, isValid = Boolean(true)) + lval foo0: R|com/javiersc/kotlin/kopy/playground/Foo| = R|com/javiersc/kotlin/kopy/playground/Foo.Foo|(bar = R|/bar0|, letter = Char(W)) + lval foo61: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/Int.plus|(Int(10)) + } + ) + } + ) + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Qux : R|kotlin/Any| { + public constructor(number: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/Qux| { + super() + } + + public final val number: R|kotlin/Int| = R|/number| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(number: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/Qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|): R|com/javiersc/kotlin/kopy/playground/Qux| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final class Baz : R|kotlin/Any| { + public constructor(qux: R|com/javiersc/kotlin/kopy/playground/Qux|, text: R|kotlin/String|): R|com/javiersc/kotlin/kopy/playground/Baz| { + super() + } + + public final val qux: R|com/javiersc/kotlin/kopy/playground/Qux| = R|/qux| + public get(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final val text: R|kotlin/String| = R|/text| + public get(): R|kotlin/String| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Bar : R|kotlin/Any| { + public constructor(baz: R|com/javiersc/kotlin/kopy/playground/Baz|, isValid: R|kotlin/Boolean|): R|com/javiersc/kotlin/kopy/playground/Bar| { + super() + } + + public final val baz: R|com/javiersc/kotlin/kopy/playground/Baz| = R|/baz| + public get(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final val isValid: R|kotlin/Boolean| = R|/isValid| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final operator fun component2(): R|kotlin/Boolean| + + public final fun copy(baz: R|com/javiersc/kotlin/kopy/playground/Baz| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|, isValid: R|kotlin/Boolean| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|): R|com/javiersc/kotlin/kopy/playground/Bar| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Foo : R|kotlin/Any| { + public constructor(bar: R|com/javiersc/kotlin/kopy/playground/Bar|, letter: R|kotlin/Char|): R|com/javiersc/kotlin/kopy/playground/Foo| { + super() + } + + public final val bar: R|com/javiersc/kotlin/kopy/playground/Bar| = R|/bar| + public get(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final val letter: R|kotlin/Char| = R|/letter| + public get(): R|kotlin/Char| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final operator fun component2(): R|kotlin/Char| + + public final fun copy(bar: R|com/javiersc/kotlin/kopy/playground/Bar| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|, letter: R|kotlin/Char| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.letter|): R|com/javiersc/kotlin/kopy/playground/Foo| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + } diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.kt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.kt new file mode 100644 index 0000000..592929c --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-1.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +ContextReceivers +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -MISSING_DEPENDENCY_CLASS -MISSING_DEPENDENCY_SUPERCLASS + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy + +fun diagnostics() { + val qux0 = Qux(number = 7) + val baz0 = Baz(qux = qux0, text = "Random") + val bar0 = Bar(baz = baz0, isValid = true) + val foo0 = Foo(bar = bar0, letter = 'W') + + val foo61 = foo0 { + bar.baz.qux.number.update { it + 10 } + } +} + +@Kopy data class Qux(val number: Int) +@Kopy class Baz(val qux: Qux, val text: String) +@Kopy data class Bar(val baz: Baz, val isValid: Boolean) +@Kopy data class Foo(val bar: Bar, val letter: Char) diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.fir.txt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.fir.txt new file mode 100644 index 0000000..5c3b025 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.fir.txt @@ -0,0 +1,98 @@ +FILE: simple-2.kt + package com.javiersc.kotlin.kopy.playground + + public final fun diagnostics(): R|kotlin/Unit| { + lval qux0: R|com/javiersc/kotlin/kopy/playground/Qux| = R|com/javiersc/kotlin/kopy/playground/Qux.Qux|(number = Int(7)) + lval baz0: R|com/javiersc/kotlin/kopy/playground/Baz| = R|com/javiersc/kotlin/kopy/playground/Baz.Baz|(qux = R|/qux0|, text = String(Random)) + lval bar0: R|com/javiersc/kotlin/kopy/playground/Bar| = R|com/javiersc/kotlin/kopy/playground/Bar.Bar|(baz = R|/baz0|, isValid = Boolean(true)) + lval foo0: R|com/javiersc/kotlin/kopy/playground/Foo| = R|com/javiersc/kotlin/kopy/playground/Foo.Foo|(bar = R|/bar0|, letter = Char(W)) + lval foo61: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|(String(Random 2)) + } + ) + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Qux : R|kotlin/Any| { + public constructor(number: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/Qux| { + super() + } + + public final val number: R|kotlin/Int| = R|/number| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(number: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/Qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|): R|com/javiersc/kotlin/kopy/playground/Qux| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final class Baz : R|kotlin/Any| { + public constructor(qux: R|com/javiersc/kotlin/kopy/playground/Qux|, text: R|kotlin/String|): R|com/javiersc/kotlin/kopy/playground/Baz| { + super() + } + + public final val qux: R|com/javiersc/kotlin/kopy/playground/Qux| = R|/qux| + public get(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final val text: R|kotlin/String| = R|/text| + public get(): R|kotlin/String| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Bar : R|kotlin/Any| { + public constructor(baz: R|com/javiersc/kotlin/kopy/playground/Baz|, isValid: R|kotlin/Boolean|): R|com/javiersc/kotlin/kopy/playground/Bar| { + super() + } + + public final val baz: R|com/javiersc/kotlin/kopy/playground/Baz| = R|/baz| + public get(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final val isValid: R|kotlin/Boolean| = R|/isValid| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final operator fun component2(): R|kotlin/Boolean| + + public final fun copy(baz: R|com/javiersc/kotlin/kopy/playground/Baz| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|, isValid: R|kotlin/Boolean| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|): R|com/javiersc/kotlin/kopy/playground/Bar| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Foo : R|kotlin/Any| { + public constructor(bar: R|com/javiersc/kotlin/kopy/playground/Bar|, letter: R|kotlin/Char|): R|com/javiersc/kotlin/kopy/playground/Foo| { + super() + } + + public final val bar: R|com/javiersc/kotlin/kopy/playground/Bar| = R|/bar| + public get(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final val letter: R|kotlin/Char| = R|/letter| + public get(): R|kotlin/Char| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final operator fun component2(): R|kotlin/Char| + + public final fun copy(bar: R|com/javiersc/kotlin/kopy/playground/Bar| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|, letter: R|kotlin/Char| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.letter|): R|com/javiersc/kotlin/kopy/playground/Foo| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + } diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.kt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.kt new file mode 100644 index 0000000..e7fc42a --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-2.kt @@ -0,0 +1,22 @@ +// !LANGUAGE: +ContextReceivers +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -MISSING_DEPENDENCY_CLASS -MISSING_DEPENDENCY_SUPERCLASS + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy + +fun diagnostics() { + val qux0 = Qux(number = 7) + val baz0 = Baz(qux = qux0, text = "Random") + val bar0 = Bar(baz = baz0, isValid = true) + val foo0 = Foo(bar = bar0, letter = 'W') + + val foo61 = foo0 { + bar.baz.text.set("Random 2") + } +} + +@Kopy data class Qux(val number: Int) +@Kopy class Baz(val qux: Qux, val text: String) +@Kopy data class Bar(val baz: Baz, val isValid: Boolean) +@Kopy data class Foo(val bar: Bar, val letter: Char) diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.fir.txt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.fir.txt new file mode 100644 index 0000000..e6459f2 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.fir.txt @@ -0,0 +1,98 @@ +FILE: simple-3.kt + package com.javiersc.kotlin.kopy.playground + + public final fun diagnostics(): R|kotlin/Unit| { + lval qux0: R|com/javiersc/kotlin/kopy/playground/Qux| = R|com/javiersc/kotlin/kopy/playground/Qux.Qux|(number = Int(7)) + lval baz0: R|com/javiersc/kotlin/kopy/playground/Baz| = R|com/javiersc/kotlin/kopy/playground/Baz.Baz|(qux = R|/qux0|, text = String(Random)) + lval bar0: R|com/javiersc/kotlin/kopy/playground/Bar| = R|com/javiersc/kotlin/kopy/playground/Bar.Bar|(baz = R|/baz0|, isValid = Boolean(true)) + lval foo0: R|com/javiersc/kotlin/kopy/playground/Foo| = R|com/javiersc/kotlin/kopy/playground/Foo.Foo|(bar = R|/bar0|, letter = Char(W)) + lval foo20: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + } + ) + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Qux : R|kotlin/Any| { + public constructor(number: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/Qux| { + super() + } + + public final val number: R|kotlin/Int| = R|/number| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(number: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/Qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|): R|com/javiersc/kotlin/kopy/playground/Qux| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final class Baz : R|kotlin/Any| { + public constructor(qux: R|com/javiersc/kotlin/kopy/playground/Qux|, text: R|kotlin/String|): R|com/javiersc/kotlin/kopy/playground/Baz| { + super() + } + + public final val qux: R|com/javiersc/kotlin/kopy/playground/Qux| = R|/qux| + public get(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final val text: R|kotlin/String| = R|/text| + public get(): R|kotlin/String| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Bar : R|kotlin/Any| { + public constructor(baz: R|com/javiersc/kotlin/kopy/playground/Baz|, isValid: R|kotlin/Boolean|): R|com/javiersc/kotlin/kopy/playground/Bar| { + super() + } + + public final val baz: R|com/javiersc/kotlin/kopy/playground/Baz| = R|/baz| + public get(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final val isValid: R|kotlin/Boolean| = R|/isValid| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final operator fun component2(): R|kotlin/Boolean| + + public final fun copy(baz: R|com/javiersc/kotlin/kopy/playground/Baz| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|, isValid: R|kotlin/Boolean| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|): R|com/javiersc/kotlin/kopy/playground/Bar| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Foo : R|kotlin/Any| { + public constructor(bar: R|com/javiersc/kotlin/kopy/playground/Bar|, letter: R|kotlin/Char|): R|com/javiersc/kotlin/kopy/playground/Foo| { + super() + } + + public final val bar: R|com/javiersc/kotlin/kopy/playground/Bar| = R|/bar| + public get(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final val letter: R|kotlin/Char| = R|/letter| + public get(): R|kotlin/Char| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final operator fun component2(): R|kotlin/Char| + + public final fun copy(bar: R|com/javiersc/kotlin/kopy/playground/Bar| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|, letter: R|kotlin/Char| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.letter|): R|com/javiersc/kotlin/kopy/playground/Foo| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + } diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.kt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.kt new file mode 100644 index 0000000..a61d320 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-3.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +ContextReceivers +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -MISSING_DEPENDENCY_CLASS -MISSING_DEPENDENCY_SUPERCLASS + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy + +fun diagnostics() { + val qux0 = Qux(number = 7) + val baz0 = Baz(qux = qux0, text = "Random") + val bar0 = Bar(baz = baz0, isValid = true) + val foo0 = Foo(bar = bar0, letter = 'W') + + val foo20 = foo0 { bar.baz.qux.number.set(10) } +} + +@Kopy data class Qux(val number: Int) +@Kopy class Baz(val qux: Qux, val text: String) +@Kopy data class Bar(val baz: Baz, val isValid: Boolean) +@Kopy data class Foo(val bar: Bar, val letter: Char) diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.fir.txt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.fir.txt new file mode 100644 index 0000000..1259efb --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.fir.txt @@ -0,0 +1,99 @@ +FILE: simple-4.kt + package com.javiersc.kotlin.kopy.playground + + public final fun diagnostics(): R|kotlin/Unit| { + lval qux0: R|com/javiersc/kotlin/kopy/playground/Qux| = R|com/javiersc/kotlin/kopy/playground/Qux.Qux|(number = Int(7)) + lval baz0: R|com/javiersc/kotlin/kopy/playground/Baz| = R|com/javiersc/kotlin/kopy/playground/Baz.Baz|(qux = R|/qux0|, text = String(Random)) + lval bar0: R|com/javiersc/kotlin/kopy/playground/Bar| = R|com/javiersc/kotlin/kopy/playground/Bar.Bar|(baz = R|/baz0|, isValid = Boolean(true)) + lval foo0: R|com/javiersc/kotlin/kopy/playground/Foo| = R|com/javiersc/kotlin/kopy/playground/Foo.Foo|(bar = R|/bar0|, letter = Char(W)) + lval foo60: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|).R|SubstitutionOverride|(Boolean(false)) + } + ) + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Qux : R|kotlin/Any| { + public constructor(number: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/Qux| { + super() + } + + public final val number: R|kotlin/Int| = R|/number| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(number: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/Qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|): R|com/javiersc/kotlin/kopy/playground/Qux| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final class Baz : R|kotlin/Any| { + public constructor(qux: R|com/javiersc/kotlin/kopy/playground/Qux|, text: R|kotlin/String|): R|com/javiersc/kotlin/kopy/playground/Baz| { + super() + } + + public final val qux: R|com/javiersc/kotlin/kopy/playground/Qux| = R|/qux| + public get(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final val text: R|kotlin/String| = R|/text| + public get(): R|kotlin/String| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Bar : R|kotlin/Any| { + public constructor(baz: R|com/javiersc/kotlin/kopy/playground/Baz|, isValid: R|kotlin/Boolean|): R|com/javiersc/kotlin/kopy/playground/Bar| { + super() + } + + public final val baz: R|com/javiersc/kotlin/kopy/playground/Baz| = R|/baz| + public get(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final val isValid: R|kotlin/Boolean| = R|/isValid| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final operator fun component2(): R|kotlin/Boolean| + + public final fun copy(baz: R|com/javiersc/kotlin/kopy/playground/Baz| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|, isValid: R|kotlin/Boolean| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|): R|com/javiersc/kotlin/kopy/playground/Bar| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Foo : R|kotlin/Any| { + public constructor(bar: R|com/javiersc/kotlin/kopy/playground/Bar|, letter: R|kotlin/Char|): R|com/javiersc/kotlin/kopy/playground/Foo| { + super() + } + + public final val bar: R|com/javiersc/kotlin/kopy/playground/Bar| = R|/bar| + public get(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final val letter: R|kotlin/Char| = R|/letter| + public get(): R|kotlin/Char| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final operator fun component2(): R|kotlin/Char| + + public final fun copy(bar: R|com/javiersc/kotlin/kopy/playground/Bar| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|, letter: R|kotlin/Char| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.letter|): R|com/javiersc/kotlin/kopy/playground/Foo| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + } diff --git a/kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.kt b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.kt new file mode 100644 index 0000000..8695259 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/missing-data-class/simple-4.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: +ContextReceivers +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -MISSING_DEPENDENCY_CLASS -MISSING_DEPENDENCY_SUPERCLASS + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy + +fun diagnostics() { + val qux0 = Qux(number = 7) + val baz0 = Baz(qux = qux0, text = "Random") + val bar0 = Bar(baz = baz0, isValid = true) + val foo0 = Foo(bar = bar0, letter = 'W') + + val foo60 = foo0 { + bar.baz.qux.number.set(10) + bar.isValid.set(false) + } +} + +@Kopy data class Qux(val number: Int) +@Kopy class Baz(val qux: Qux, val text: String) +@Kopy data class Bar(val baz: Baz, val isValid: Boolean) +@Kopy data class Foo(val bar: Bar, val letter: Char) diff --git a/kopy-compiler/test-data/diagnostics/valid/complex-1.fir.txt b/kopy-compiler/test-data/diagnostics/valid/complex-1.fir.txt new file mode 100644 index 0000000..a598750 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/valid/complex-1.fir.txt @@ -0,0 +1,173 @@ +FILE: complex-1.kt + package com.javiersc.kotlin.kopy.playground + + public final fun diagnostics(): R|kotlin/Unit| { + lval qux0: R|com/javiersc/kotlin/kopy/playground/Qux| = R|com/javiersc/kotlin/kopy/playground/Qux.Qux|(number = Int(7)) + lval baz0: R|com/javiersc/kotlin/kopy/playground/Baz| = R|com/javiersc/kotlin/kopy/playground/Baz.Baz|(qux = R|/qux0|, text = String(Random)) + lval bar0: R|com/javiersc/kotlin/kopy/playground/Bar| = R|com/javiersc/kotlin/kopy/playground/Bar.Bar|(baz = R|/baz0|, isValid = Boolean(true)) + lval foo0: R|com/javiersc/kotlin/kopy/playground/Foo| = R|com/javiersc/kotlin/kopy/playground/Foo.Foo|(bar = R|/bar0|, letter = Char(W)) + lval foo10: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + ^@foo0 Unit + } + ) + lval foo11: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + ^@copy Unit + } + ) + lval house20: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + } + ) + lval house21: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + } + ) + lval house30: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/Int.plus|(Int(10)) + } + ) + } + ) + lval house31: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/Int.plus|(Int(10)) + } + ) + } + ) + lval house40: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|(String(Random 2)) + } + ) + lval house41: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|(String(Random 2)) + } + ) + lval house50: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/String|): R|kotlin/String| { + ^ R|/it|.R|kotlin/String.plus|(String( 2)) + } + ) + } + ) + lval house51: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.copy|(copy@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/String|): R|kotlin/String| { + ^ R|/it|.R|kotlin/String.plus|(String( 2)) + } + ) + } + ) + lval house60: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|(Int(10)) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/String|): R|kotlin/String| { + ^ (R|/it|, String( Random 2)) + } + ) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|).R|SubstitutionOverride|(Boolean(false)) + } + ) + lval house61: R|com/javiersc/kotlin/kopy/playground/Foo| = R|/foo0|.R|com/javiersc/kotlin/kopy/playground/Foo.invoke|( = foo0@fun R|com/javiersc/kotlin/kopy/playground/Foo|.(): R|kotlin/Unit| { + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/Int.plus|(Int(10)) + } + ) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|).R|SubstitutionOverride|(String(Random 2)) + (this@R|special/anonymous|, this@R|special/anonymous|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|).R|SubstitutionOverride|( = update@fun (it: R|kotlin/Boolean|): R|kotlin/Boolean| { + ^ R|/it|.R|kotlin/Boolean.not|() + } + ) + } + ) + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Qux : R|kotlin/Any| { + public constructor(number: R|kotlin/Int|): R|com/javiersc/kotlin/kopy/playground/Qux| { + super() + } + + public final val number: R|kotlin/Int| = R|/number| + public get(): R|kotlin/Int| + + public final operator fun component1(): R|kotlin/Int| + + public final fun copy(number: R|kotlin/Int| = this@R|com/javiersc/kotlin/kopy/playground/Qux|.R|com/javiersc/kotlin/kopy/playground/Qux.number|): R|com/javiersc/kotlin/kopy/playground/Qux| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Qux) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Qux| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Baz : R|kotlin/Any| { + public constructor(qux: R|com/javiersc/kotlin/kopy/playground/Qux|, text: R|kotlin/String|): R|com/javiersc/kotlin/kopy/playground/Baz| { + super() + } + + public final val qux: R|com/javiersc/kotlin/kopy/playground/Qux| = R|/qux| + public get(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final val text: R|kotlin/String| = R|/text| + public get(): R|kotlin/String| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Qux| + + public final operator fun component2(): R|kotlin/String| + + public final fun copy(qux: R|com/javiersc/kotlin/kopy/playground/Qux| = this@R|com/javiersc/kotlin/kopy/playground/Baz|.R|com/javiersc/kotlin/kopy/playground/Baz.qux|, text: R|kotlin/String| = this@R|com/javiersc/kotlin/kopy/playground/Baz|.R|com/javiersc/kotlin/kopy/playground/Baz.text|): R|com/javiersc/kotlin/kopy/playground/Baz| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Baz) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Baz| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Bar : R|kotlin/Any| { + public constructor(baz: R|com/javiersc/kotlin/kopy/playground/Baz|, isValid: R|kotlin/Boolean|): R|com/javiersc/kotlin/kopy/playground/Bar| { + super() + } + + public final val baz: R|com/javiersc/kotlin/kopy/playground/Baz| = R|/baz| + public get(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final val isValid: R|kotlin/Boolean| = R|/isValid| + public get(): R|kotlin/Boolean| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Baz| + + public final operator fun component2(): R|kotlin/Boolean| + + public final fun copy(baz: R|com/javiersc/kotlin/kopy/playground/Baz| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.baz|, isValid: R|kotlin/Boolean| = this@R|com/javiersc/kotlin/kopy/playground/Bar|.R|com/javiersc/kotlin/kopy/playground/Bar.isValid|): R|com/javiersc/kotlin/kopy/playground/Bar| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Bar) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Bar| { + } + + } + @R|com/javiersc/kotlin/kopy/Kopy|() public final data class Foo : R|kotlin/Any| { + public constructor(bar: R|com/javiersc/kotlin/kopy/playground/Bar|, letter: R|kotlin/Char|): R|com/javiersc/kotlin/kopy/playground/Foo| { + super() + } + + public final val bar: R|com/javiersc/kotlin/kopy/playground/Bar| = R|/bar| + public get(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final val letter: R|kotlin/Char| = R|/letter| + public get(): R|kotlin/Char| + + public final operator fun component1(): R|com/javiersc/kotlin/kopy/playground/Bar| + + public final operator fun component2(): R|kotlin/Char| + + public final fun copy(bar: R|com/javiersc/kotlin/kopy/playground/Bar| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.bar|, letter: R|kotlin/Char| = this@R|com/javiersc/kotlin/kopy/playground/Foo|.R|com/javiersc/kotlin/kopy/playground/Foo.letter|): R|com/javiersc/kotlin/kopy/playground/Foo| + + @R|com/javiersc/kotlin/kopy/KopyFunctionKopy|() public final infix fun copy(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + @R|com/javiersc/kotlin/kopy/KopyFunctionInvoke|() public final operator infix fun invoke(copy: R|@ContextFunctionTypeParams com/javiersc/kotlin/kopy/runtime/KopyableScope.(com/javiersc/kotlin/kopy/playground/Foo) -> kotlin/Unit|): R|com/javiersc/kotlin/kopy/playground/Foo| { + } + + } diff --git a/kopy-compiler/test-data/diagnostics/valid/complex-1.kt b/kopy-compiler/test-data/diagnostics/valid/complex-1.kt new file mode 100644 index 0000000..217ec87 --- /dev/null +++ b/kopy-compiler/test-data/diagnostics/valid/complex-1.kt @@ -0,0 +1,45 @@ +// !LANGUAGE: +ContextReceivers +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -MISSING_DEPENDENCY_CLASS -MISSING_DEPENDENCY_SUPERCLASS + +package com.javiersc.kotlin.kopy.playground + +import com.javiersc.kotlin.kopy.Kopy + +fun diagnostics() { + val qux0 = Qux(number = 7) + val baz0 = Baz(qux = qux0, text = "Random") + val bar0 = Bar(baz = baz0, isValid = true) + val foo0 = Foo(bar = bar0, letter = 'W') + + val foo10 = foo0 {} + val foo11 = foo0 copy {} + + val house20 = foo0 { bar.baz.qux.number.set(10) } + val house21 = foo0 copy { bar.baz.qux.number.set(10) } + + val house30 = foo0 { bar.baz.qux.number.update { it + 10 } } + val house31 = foo0 copy { bar.baz.qux.number.update { it + 10 } } + + val house40 = foo0 { bar.baz.text.set("Random 2") } + val house41 = foo0 copy { bar.baz.text.set("Random 2") } + + val house50 = foo0 { bar.baz.text.update { it + " 2" } } + val house51 = foo0 copy { bar.baz.text.update { it + " 2" } } + + val house60 = foo0 { + bar.baz.qux.number.set(10) + bar.baz.text.update { "$it Random 2" } + bar.isValid.set(false) + } + + val house61 = foo0 { + bar.baz.qux.number.update { it + 10 } + bar.baz.text.set("Random 2") + bar.isValid.update { !it } + } +} + +@Kopy data class Qux(val number: Int) +@Kopy data class Baz(val qux: Qux, val text: String) +@Kopy data class Bar(val baz: Baz, val isValid: Boolean) +@Kopy data class Foo(val bar: Bar, val letter: Char) diff --git a/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/BoxTestGenerated.java b/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/BoxTestGenerated.java index 1ddfcc4..ad091fe 100644 --- a/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/BoxTestGenerated.java +++ b/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/BoxTestGenerated.java @@ -21,22 +21,4 @@ public class BoxTestGenerated extends AbstractBoxTest { public void testAllFilesPresentInBox() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("test-data/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } - - @Test - @TestMetadata("no-nest-copy-update-no-it.kt") - public void testNo_nest_copy_update_no_it() throws Exception { - runTest("test-data/box/no-nest-copy-update-no-it.kt"); - } - - @Test - @TestMetadata("no-nest-invoke-update-no-it.kt") - public void testNo_nest_invoke_update_no_it() throws Exception { - runTest("test-data/box/no-nest-invoke-update-no-it.kt"); - } - - @Test - @TestMetadata("no-nest-invoke-update-with-it.kt") - public void testNo_nest_invoke_update_with_it() throws Exception { - runTest("test-data/box/no-nest-invoke-update-with-it.kt"); - } } diff --git a/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/DiagnosticTestGenerated.java b/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/DiagnosticTestGenerated.java index 481c027..6b68ae0 100644 --- a/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/DiagnosticTestGenerated.java +++ b/kopy-compiler/test-gen/java/com/javiersc/kotlin/kopy/compiler/DiagnosticTestGenerated.java @@ -20,4 +20,76 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { public void testAllFilesPresentInDiagnostics() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("test-data/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true); } + + @Nested + @TestMetadata("test-data/diagnostics/invalid-call-chain") + @TestDataPath("$PROJECT_ROOT") + public class Invalid_call_chain { + @Test + public void testAllFilesPresentInInvalid_call_chain() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("test-data/diagnostics/invalid-call-chain"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("complex-1.kt") + public void testComplex_1() throws Exception { + runTest("test-data/diagnostics/invalid-call-chain/complex-1.kt"); + } + } + + @Nested + @TestMetadata("test-data/diagnostics/missing-data-class") + @TestDataPath("$PROJECT_ROOT") + public class Missing_data_class { + @Test + public void testAllFilesPresentInMissing_data_class() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("test-data/diagnostics/missing-data-class"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("complex-1.kt") + public void testComplex_1() throws Exception { + runTest("test-data/diagnostics/missing-data-class/complex-1.kt"); + } + + @Test + @TestMetadata("simple-1.kt") + public void testSimple_1() throws Exception { + runTest("test-data/diagnostics/missing-data-class/simple-1.kt"); + } + + @Test + @TestMetadata("simple-2.kt") + public void testSimple_2() throws Exception { + runTest("test-data/diagnostics/missing-data-class/simple-2.kt"); + } + + @Test + @TestMetadata("simple-3.kt") + public void testSimple_3() throws Exception { + runTest("test-data/diagnostics/missing-data-class/simple-3.kt"); + } + + @Test + @TestMetadata("simple-4.kt") + public void testSimple_4() throws Exception { + runTest("test-data/diagnostics/missing-data-class/simple-4.kt"); + } + } + + @Nested + @TestMetadata("test-data/diagnostics/valid") + @TestDataPath("$PROJECT_ROOT") + public class Valid { + @Test + public void testAllFilesPresentInValid() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("test-data/diagnostics/valid"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("complex-1.kt") + public void testComplex_1() throws Exception { + runTest("test-data/diagnostics/valid/complex-1.kt"); + } + } } diff --git a/kopy-gradle-plugin/build.gradle.kts b/kopy-gradle-plugin/build.gradle.kts index 62ccb7c..54bdb33 100644 --- a/kopy-gradle-plugin/build.gradle.kts +++ b/kopy-gradle-plugin/build.gradle.kts @@ -8,6 +8,7 @@ hubdle { api() } explicitApi() + format.isEnabled = false projectConfig { // generateProjectData(true) } @@ -51,7 +52,7 @@ hubdle { main { dependencies { compileOnly(projects.kopyCompiler) - compileOnly(hubdle.jetbrains.kotlin.kotlinGradlePlugin) + compileOnly(hubdle.jetbrains.kotlin.gradle.plugin) } } } diff --git a/kopy-runtime/build.gradle.kts b/kopy-runtime/build.gradle.kts index 125faab..f469f3e 100644 --- a/kopy-runtime/build.gradle.kts +++ b/kopy-runtime/build.gradle.kts @@ -8,6 +8,7 @@ hubdle { api() } explicitApi() + format.isEnabled = false publishing() } kotlin { diff --git a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/Kopy.kt b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/Kopy.kt index ad641d9..c744ee9 100644 --- a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/Kopy.kt +++ b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/Kopy.kt @@ -14,6 +14,13 @@ public annotation class KopyFunctionInvoke { public companion object } +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +public annotation class KopyFunctionKopy { + + public companion object +} + @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.BINARY) public annotation class KopyFunctionSet { diff --git a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/Kopyable.kt b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/Kopyable.kt index de0a270..bd5ba10 100644 --- a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/Kopyable.kt +++ b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/Kopyable.kt @@ -5,23 +5,43 @@ package com.javiersc.kotlin.kopy.runtime import com.javiersc.kotlin.kopy.KopyFunctionInvoke import com.javiersc.kotlin.kopy.KopyFunctionSet import com.javiersc.kotlin.kopy.KopyFunctionUpdate +import java.util.concurrent.atomic.AtomicReference -public interface Kopyable { +public interface Kopyable { @KopyFunctionInvoke - public infix operator fun invoke(kopy: /*context(KopyableScope)*/ T.() -> Unit): T = TODO(error) + public infix operator fun invoke(copy: context(KopyableScope) M.() -> Unit): M { + val scope = KopyableScope(kopyError()) + copy(scope, scope.getKopyableReference()) + return scope.getKopyableReference() + } @KopyFunctionInvoke - public infix fun copy(kopy: /*context(KopyableScope)*/ T.() -> Unit): T = TODO(error) + public infix fun copy(copy: context(KopyableScope) M.() -> Unit): M = invoke(copy) +} + +@Deprecated("This is deprecated", level = DeprecationLevel.ERROR) +public class KopyableScope internal constructor(data: M) { + + private val atomic = AtomicReference(data) - // context(KopyableScope) - @KopyFunctionSet public infix fun R.set(other: R): R = TODO(error) + public fun getKopyableReference(): M = atomic.get() - // context(KopyableScope) - @KopyFunctionUpdate public infix fun R.update(other: (R) -> R): R = TODO(error) + public fun setKopyableReference(other: M) { + atomic.set(other) + } - @Deprecated("This is deprecated", level = DeprecationLevel.ERROR) - public interface KopyableScope + context(KopyableScope) + @KopyFunctionSet + public infix fun D.set(other: D): Unit = Unit + + context(KopyableScope) + @KopyFunctionUpdate + public infix fun D.update(other: (D) -> D) { + other(this) + } } +private fun kopyError(): T = TODO(error) + private const val error = "Kopy plugin is not applied" diff --git a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete.kt b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete.kt index 719a8de..b2cd1b5 100644 --- a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete.kt +++ b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete.kt @@ -1,18 +1,27 @@ -package com.javiersc.kotlin.kopy.playground - -import com.javiersc.kotlin.kopy.Kopy -import com.javiersc.kotlin.kopy.runtime.Kopyable - -internal fun box(): String { - val house0 = House(street = "Street", squareMeters = 20) - val house1 = house0 { squareMeters.update { it + 20 } } - val house2 = - house0.run { - var tmp0 = this - tmp0 = tmp0.copy(squareMeters = tmp0.squareMeters.let { it + 20 }) - tmp0 - } - return if (house1 == house2) "OK" else "Fail: \nHouse1: $house1 \nHouse2: $house2" -} - -@Kopy internal data class House(val street: String, val squareMeters: Int) : Kopyable +//package com.javiersc.kotlin.kopy.playground +//// +//import com.javiersc.kotlin.kopy.Kopy +//import com.javiersc.kotlin.kopy.runtime.Kopyable +//// +////internal fun box(): String { +//// val house0 = House(street = "Street", squareMeters = 20) +//// val house1 = house0 { squareMeters.update { it + 20 } } +//// val house2 = +//// house0.run { +//// var tmp0 = this +//// tmp0 = tmp0.copy(squareMeters = tmp0.squareMeters.let { it + 20 }) +//// tmp0 +//// } +//// return if (house1 == house2) "OK" else "Fail: \nHouse1: $house1 \nHouse2: $house2" +////} +//// +// +//internal fun diagnostics() { +// val house0 = House(street = "Street", squareMeters = 20) +// +// val house1 = house0 kopy {} +// +// val house2 = house0 kopy { squareMeters.set(40) } +//} +// +//@Kopy internal data class House(val street: String, val squareMeters: Int) : Kopyable diff --git a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete2.kt b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete2.kt index 5206c57..c78448e 100644 --- a/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete2.kt +++ b/kopy-runtime/main/kotlin/com/javiersc/kotlin/kopy/runtime/delete/Delete2.kt @@ -1,26 +1,31 @@ +@file:Suppress("DEPRECATION_ERROR") + package com.javiersc.kotlin.kopy.runtime.delete -import com.javiersc.kotlin.kopy.Kopy -import com.javiersc.kotlin.kopy.runtime.Kopyable +import com.javiersc.kotlin.kopy.runtime.KopyableScope + +internal fun box() { + val d = D(num = 0) + val c = C(d = d, text = "Text") + val b = B(c = c, isValid = true) + val a = A(b = b, letter = 'A') -public fun box(): String { - val house0 = House(street = "Street", squareMeters = 20) - val house1 = house0.copy() - val house2 = house1 { squareMeters.update { 40 } } - val house3 = house1.copy(squareMeters = house1.squareMeters.let { 40 }) - return if (house2 == house3) "OK" else "ERROR" + val a1 = a kopy { + b.isValid.set(false) + b.c.text.update { "$it Random 2" } + } } -@Kopy internal data class House(val street: String, val squareMeters: Int) : Kopyable +//@Kopy data class House(val street: String, val squareMeters: Int) -internal fun delete() { - val house0 = House(street = "Street", squareMeters = 20) - val house1 = house0 { squareMeters.update { 2 } } -} +internal data class A(val b: B, val letter: Char) { -// internal fun House.hello() { -// squareMeters.update { 2 } -// val house = this { -// squareMeters.update { 2 } -// } -// } + infix fun kopy(kopy: context(KopyableScope) A.() -> Unit): A { + val scope: KopyableScope = KopyableScope(this) + kopy(scope, scope.getKopyableReference()) + return scope.getKopyableReference() + } +} +internal data class B(val c: C, val isValid: Boolean) +internal data class C(val d: D, val text: String) +internal data class D(val num: Int) diff --git a/settings.gradle.kts b/settings.gradle.kts index 052ad10..e175ef9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -38,18 +38,19 @@ dependencyResolutionManagement { val catalogFile = file("$rootDir/gradle/libs.versions.toml").readLines() -val hubdleCatalogVersion: String = catalogFile.first { it.contains("hubdleCatalog") }.split("\"")[1] +val hubdleCatalogVersion: String = + catalogFile.first { it.contains("hubdleCatalog =") }.split("\"")[1] val kotlinCompilerExtensionsVersion: String = - catalogFile.first { it.contains("javiersc-kotlin-kotlinCompilerExtensions") }.split("\"")[1] + catalogFile.first { it.contains("javiersc-kotlin-compiler-extensions =") }.split("\"")[1] val kotlinStdlibAndTestVersion: String = - catalogFile.first { it.contains("javiersc-kotlin-kotlinStdlibAndTest") }.split("\"")[1] + catalogFile.first { it.contains("javiersc-kotlin =") }.split("\"")[1] hubdleSettings { catalog { // version(hubdleCatalogVersion) replaceVersion( - "javiersc-kotlin-kotlinCompilerExtensions" to kotlinCompilerExtensionsVersion, - "javiersc-kotlin-kotlinStdlibAndTest" to kotlinStdlibAndTestVersion, + "javiersc-kotlin-compiler-extensions" to kotlinCompilerExtensionsVersion, + "javiersc-kotlin" to kotlinStdlibAndTestVersion, ) } }