From ca91e175a5b027cecee331d89e5be83f6adbf19e Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 11 Mar 2024 15:08:56 +0100 Subject: [PATCH] JPS mappings for incremental compilation refactoring: handle changed [function => property] and [property => function] GitOrigin-RevId: dfb6469ffb87e20111854c3d18512cf4dc28d451 --- .../KotlinAwareJavaDifferentiateStrategy.java | 26 +++++++++++++++++++ .../build.log | 5 ++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/dependency/kotlin/KotlinAwareJavaDifferentiateStrategy.java b/jps/jps-builders/src/org/jetbrains/jps/dependency/kotlin/KotlinAwareJavaDifferentiateStrategy.java index 94bd2faad78b..94dd1e8058b8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/dependency/kotlin/KotlinAwareJavaDifferentiateStrategy.java +++ b/jps/jps-builders/src/org/jetbrains/jps/dependency/kotlin/KotlinAwareJavaDifferentiateStrategy.java @@ -130,6 +130,18 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate affectSubclasses(context, future, change.getNow().getReferenceID(), true); } + for (KmFunction removedFunction : metaDiff.functions().removed()) { + JvmMethod method = getJvmMethod(change.getNow(), JvmExtensionsKt.getSignature(removedFunction)); + if (method != null && !method.isPrivate()) { + // a function in kotlin code was replaced with a property, but at the bytecode level corresponding methods are preserved + for (JvmClass subClass : filter(flat(map(future.allSubclasses(changedClass.getReferenceID()), id -> future.getNodes(id, JvmClass.class))), n -> isKotlinNode(n))) { + if (find(subClass.getMethods(), m -> !m.isPrivate() && method.isSameByJavaRules(m)) != null) { + affectNodeSources(context, subClass.getReferenceID(), "Kotlin function " + removedFunction.getName() + " has been removed. Affecting corresponding method in subclasses: "); + } + } + } + } + for (Difference.Change funChange : metaDiff.functions().changed()) { KmFunction changedKmFunction = funChange.getPast(); Visibility visibility = Attributes.getVisibility(changedKmFunction); @@ -161,6 +173,20 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate } } + for (KmProperty removedProp : metaDiff.properties().removed()) { + List propertyAccessors = Arrays.asList(JvmExtensionsKt.getGetterSignature(removedProp), JvmExtensionsKt.getSetterSignature(removedProp)); + List accessorMethods = collect(filter(map(propertyAccessors, acc -> acc != null? getJvmMethod(change.getNow(), acc) : null), m -> m != null && !m.isPrivate()), new SmartList<>()); + + if (!accessorMethods.isEmpty()) { + // property in kotlin code was replaced with a function(s), but at the bytecode level corresponding methods are preserved + for (JvmClass subClass : filter(flat(map(future.allSubclasses(changedClass.getReferenceID()), id -> future.getNodes(id, JvmClass.class))), n -> isKotlinNode(n))) { + if (find(subClass.getMethods(), m -> !m.isPrivate() && find(accessorMethods, m::isSameByJavaRules) != null) != null) { + affectNodeSources(context, subClass.getReferenceID(), "Kotlin property " + removedProp.getName() + " has been removed. Affecting corresponding accessor method(s) in subclasses: "); + } + } + } + } + for (Difference.Change propChange : metaDiff.properties().changed()) { KmProperty prop = propChange.getPast(); KotlinMeta.KmPropertiesDiff propDiff = propChange.getDiff(); diff --git a/plugins/kotlin/jps/graphImplementationTests/testData/incremental/withJava/javaUsedInKotlin/changeMethodToPropertyInInheritance/build.log b/plugins/kotlin/jps/graphImplementationTests/testData/incremental/withJava/javaUsedInKotlin/changeMethodToPropertyInInheritance/build.log index 4c8cfd4f9295..d0a1ddcd0afc 100644 --- a/plugins/kotlin/jps/graphImplementationTests/testData/incremental/withJava/javaUsedInKotlin/changeMethodToPropertyInInheritance/build.log +++ b/plugins/kotlin/jps/graphImplementationTests/testData/incremental/withJava/javaUsedInKotlin/changeMethodToPropertyInInheritance/build.log @@ -2,17 +2,16 @@ Cleaning output files: out/production/module/Base.class + out/production/module/META-INF/module.kotlin_module End of files -Exit code: NOTHING_DONE ------------------------------------------- Compiling files: src/Base.kt End of files Exit code: OK ------------------------------------------ Cleaning output files: - out/production/module/META-INF/module.kotlin_module out/production/module/ChildClass.class + out/production/module/META-INF/module.kotlin_module End of files Compiling files: src/ChildClass.kt