JPS mappings for incremental compilation refactoring: handle type parameter variance changes

GitOrigin-RevId: 1bd908b12d8b6d481d16e3821c9bcc1c6c635652
This commit is contained in:
Eugene Zhuravlev
2024-03-07 20:32:50 +00:00
committed by intellij-monorepo-bot
parent c20dc77fce
commit d5ffaced4b
4 changed files with 51 additions and 16 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.jps.javac;
import org.jetbrains.annotations.NotNull;
@@ -63,7 +63,11 @@ public final class Iterators {
public interface Function<S, T> {
T fun(S s);
}
public interface BiFunction<S1, S2, T> {
T fun(S1 s1, S2 s2);
}
public interface BooleanFunction<T> {
boolean fun(T t);
}
@@ -368,12 +372,21 @@ public final class Iterators {
}
public static <T> boolean equals(Iterable<? extends T> s1, Iterable<? extends T> s2) {
return equals(s1, s2, new BiFunction<T, T, Boolean>() {
@Override
public Boolean fun(T t1, T t2) {
return t1.equals(t2);
}
});
}
public static <T> boolean equals(Iterable<? extends T> s1, Iterable<? extends T> s2, BiFunction<? super T, ? super T, Boolean> comparator) {
Iterator<? extends T> it2 = s2.iterator();
for (T elem : s1) {
if (!it2.hasNext()) {
return false;
}
if (!elem.equals(it2.next())) {
if (!comparator.fun(elem, it2.next())) {
return false;
}
}
@@ -56,7 +56,7 @@ public abstract class JvmDifferentiateStrategyImpl implements JvmDifferentiateSt
else {
context.affectUsage(usageFactory.apply(id));
}
debug("Affect ", usageKind, " usage owned by node ", id.getNodeName());
debug("Affect ", usageKind, " usage owned by node '", id.getNodeName(), "'");
}
}
@@ -151,6 +151,11 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
return container != null? container.getFunctions() : Collections.emptyList();
}
public Iterable<KmTypeParameter> getTypeParameters() {
KmDeclarationContainer container = getDeclarationContainer();
return container instanceof KmClass? ((KmClass)container).getTypeParameters() : Collections.emptyList();
}
@Nullable
public KmDeclarationContainer getDeclarationContainer() {
KotlinClassMetadata clsMeta = getClassMetadata();
@@ -192,7 +197,7 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
@Override
public boolean unchanged() {
return !kindChanged() && !versionChanged() && !packageChanged() && !extraChanged() && functions().unchanged() && properties().unchanged()/*&& !dataChanged()*/;
return !kindChanged() && !versionChanged() && !packageChanged() && !extraChanged() && !typeParametersVarianceChanged() && functions().unchanged() && properties().unchanged()/*&& !dataChanged()*/;
}
public boolean kindChanged() {
@@ -215,6 +220,10 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
return myPast.myExtraInt != myExtraInt || !Objects.equals(myPast.myExtraString, myExtraString);
}
public boolean typeParametersVarianceChanged() {
return !Iterators.equals(myPast.getTypeParameters(), getTypeParameters(), (p1, p2) -> p1.getVariance() == p2.getVariance());
}
public Specifier<KmFunction, KmFunctionsDiff> functions() {
return myFunctionsDiff.get();
}
@@ -32,9 +32,8 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate
if (!addedClass.isPrivate()) {
// calls to newly added class' constructors may shadow calls to functions named similarly
String ktName = getKotlinName(addedClass);
debug("Affecting lookup usages for added class ", ktName);
affectLookupUsages(context, asIterable(new JvmNodeReferenceID(addedClass.getPackageName())), ktName != null? JvmClass.getShortName(ktName) : addedClass.getShortName(), future, null);
debug("Affecting lookup usages for added class ", addedClass.getName());
affectClassLookupUsages(context, addedClass, future);
}
return true;
@@ -50,9 +49,8 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate
// this will affect all imports of this class in kotlin sources
KmDeclarationContainer container = getDeclarationContainer(removedClass);
if (container == null /*is non-kotlin node*/ || container instanceof KmClass) {
String clsName = container != null? ((KmClass)container).getName() : removedClass.getName();
debug("Affecting lookup usages for removed class ", clsName);
affectLookupUsages(context, asIterable(new JvmNodeReferenceID(removedClass.getPackageName())), JvmClass.getShortName(clsName), present, null);
debug("Affecting lookup usages for removed class ", removedClass.getName());
affectClassLookupUsages(context, removedClass, present);
}
}
@@ -127,6 +125,11 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate
for (Difference.Change<KotlinMeta, KotlinMeta.Diff> metaChange : diff.metadata(KotlinMeta.class).changed()) {
KotlinMeta.Diff metaDiff = metaChange.getDiff();
if (metaDiff.typeParametersVarianceChanged()) {
debug("Kotlin class' type parameters' variance changed; affecting class usage ", changedClass.getName());
affectSubclasses(context, future, change.getNow().getReferenceID(), true);
}
for (Difference.Change<KmFunction, KotlinMeta.KmFunctionsDiff> funChange : metaDiff.functions().changed()) {
KmFunction changedKmFunction = funChange.getPast();
Visibility visibility = Attributes.getVisibility(changedKmFunction);
@@ -272,11 +275,16 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate
if (clsMethod.isPrivate()) {
return;
}
Set<JvmNodeReferenceID> targets = collect(
flat(utils.allSupertypes(cls.getReferenceID()), utils.collectSubclassesWithoutMethod(cls.getReferenceID(), clsMethod)), new SmartHashSet<>()
);
targets.add(cls.getReferenceID());
affectLookupUsages(context, targets, getMethodKotlinName(cls, clsMethod), utils, constraint);
if (clsMethod.isConstructor()) {
affectClassLookupUsages(context, cls, utils);
}
else {
Set<JvmNodeReferenceID> targets = collect(
flat(utils.allSupertypes(cls.getReferenceID()), utils.collectSubclassesWithoutMethod(cls.getReferenceID(), clsMethod)), new SmartHashSet<>()
);
targets.add(cls.getReferenceID());
affectLookupUsages(context, targets, getMethodKotlinName(cls, clsMethod), utils, constraint);
}
}
private static final class PropertyDescriptor{
@@ -350,6 +358,11 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate
return !iterator.hasNext();
}
private void affectClassLookupUsages(DifferentiateContext context, JvmClass cls, Utils utils) {
String ktName = getKotlinName(cls);
affectLookupUsages(context, asIterable(new JvmNodeReferenceID(cls.getPackageName())), ktName != null? JvmClass.getShortName(ktName) : cls.getShortName(), utils, null);
}
private void affectMemberLookupUsages(DifferentiateContext context, JvmClass cls, String name, Utils utils) {
affectLookupUsages(context, filter(map(utils.withAllSubclasses(cls.getReferenceID()), id -> id instanceof JvmNodeReferenceID? ((JvmNodeReferenceID)id) : null), Objects::nonNull), name, utils, null);
}