mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
JPS mappings for incremental compilation refactoring: check affection among those nodes only, that depend on affected usages' owners; explicit way to specify affection calculation scope when adding a usage query predicate
GitOrigin-RevId: 8d03716c595b0a1111b5becfd1fa088fd3d94d0e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1b01a71fc0
commit
a66230a4da
@@ -26,7 +26,7 @@ public interface DifferentiateContext {
|
||||
|
||||
void affectUsage(@NotNull Usage usage, @NotNull Predicate<Node<?, ?>> constraint);
|
||||
|
||||
void affectUsage(@NotNull BiPredicate<Node<?, ?>, Usage> usageQuery);
|
||||
void affectUsage(Iterable<? extends ReferenceID> affectionScopeNodes, @NotNull BiPredicate<Node<?, ?>, Usage> usageQuery);
|
||||
|
||||
void affectNodeSource(@NotNull NodeSource source);
|
||||
|
||||
|
||||
@@ -35,8 +35,11 @@ public interface MultiMaplet<K, V> extends BaseMaplet<K> {
|
||||
boolean beforeEmpty = Iterators.isEmpty(dataBefore);
|
||||
boolean afterEmpty = Iterators.isEmpty(dataAfter);
|
||||
if (beforeEmpty || afterEmpty) {
|
||||
if (!beforeEmpty || !afterEmpty) {
|
||||
put(key, dataAfter);
|
||||
if (!afterEmpty) { // => beforeEmpty
|
||||
appendValues(key, dataAfter);
|
||||
}
|
||||
else if (!beforeEmpty) {
|
||||
remove(key);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -120,7 +120,10 @@ public final class DependencyGraphImpl extends GraphImpl implements DependencyGr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void affectUsage(@NotNull BiPredicate<Node<?, ?>, Usage> usageQuery) {
|
||||
public void affectUsage(Iterable<? extends ReferenceID> affectionScopeNodes, @NotNull BiPredicate<Node<?, ?>, Usage> usageQuery) {
|
||||
for (Usage u : map(affectionScopeNodes, AffectionScopeMetaUsage::new)) {
|
||||
affectUsage(u);
|
||||
}
|
||||
usageQueries.add(usageQuery);
|
||||
}
|
||||
|
||||
@@ -169,10 +172,10 @@ public final class DependencyGraphImpl extends GraphImpl implements DependencyGr
|
||||
return Boolean.TRUE;
|
||||
});
|
||||
|
||||
Iterable<ReferenceID> scopeNodes = unique(flat(map(nodesAfter, Node::getReferenceID), map(diffContext.affectedUsages.keySet(), Usage::getElementOwner)));
|
||||
Iterable<ReferenceID> scopeNodes = unique(map(diffContext.affectedUsages.keySet(), Usage::getElementOwner));
|
||||
Set<ReferenceID> candidates = collect(filter(flat(map(scopeNodes, this::getDependingNodes)), id -> !dependingOnDeleted.contains(id)), new HashSet<>());
|
||||
|
||||
for (NodeSource depSrc : unique(flat(map(candidates, dependent -> getSources(dependent))))) {
|
||||
|
||||
for (NodeSource depSrc : unique(flat(map(candidates, this::getSources)))) {
|
||||
if (!affectedSources.contains(depSrc) && !diffContext.affectedSources.contains(depSrc) && !allProcessedSources.contains(depSrc) && params.affectionFilter().test(depSrc)) {
|
||||
boolean affectSource = false;
|
||||
for (var depNode : filter(getNodes(depSrc), n -> candidates.contains(n.getReferenceID()))) {
|
||||
|
||||
@@ -194,7 +194,7 @@ public class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImpl {
|
||||
if (!removedTargets.isEmpty()) {
|
||||
debug("Removed some annotation targets, adding annotation query");
|
||||
TypeRepr.ClassType classType = new TypeRepr.ClassType(changedClass.getName());
|
||||
context.affectUsage((node, usage) -> {
|
||||
context.affectUsage(asIterable(changedClass.getReferenceID()), (node, usage) -> {
|
||||
if (usage instanceof AnnotationUsage) {
|
||||
AnnotationUsage annotUsage = (AnnotationUsage)usage;
|
||||
if (classType.equals(annotUsage.getClassType())) {
|
||||
@@ -334,7 +334,7 @@ public class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImpl {
|
||||
debug("Class is annotation, default value is removed => adding annotation query");
|
||||
String argName = changedMethod.getName();
|
||||
TypeRepr.ClassType annotType = new TypeRepr.ClassType(changedClass.getName());
|
||||
context.affectUsage((node, usage) -> {
|
||||
context.affectUsage(asIterable(changedClass.getReferenceID()), (node, usage) -> {
|
||||
if (usage instanceof AnnotationUsage) {
|
||||
// need to find annotation usages that do not use arguments this annotation uses
|
||||
AnnotationUsage au = (AnnotationUsage)usage;
|
||||
@@ -572,11 +572,10 @@ public class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImpl {
|
||||
|
||||
if (!isEmpty(addedMethod.getArgTypes()) && !present.hasOverriddenMethods(changedClass, addedMethod)) {
|
||||
debug("Conservative case on overriding methods, affecting method usages");
|
||||
context.affectUsage(addedMethod.createUsageQuery(changedClass.getReferenceID()));
|
||||
context.affectUsage(asIterable(changedClass.getReferenceID()), addedMethod.createUsageQuery(changedClass.getReferenceID()));
|
||||
if (!addedMethod.isConstructor()) { // do not propagate constructors access, since constructors are always concrete and not accessible via references to subclasses
|
||||
for (JvmNodeReferenceID id : propagated) {
|
||||
context.affectUsage(new AffectionScopeMetaUsage(id));
|
||||
context.affectUsage(addedMethod.createUsageQuery(id));
|
||||
context.affectUsage(asIterable(id), addedMethod.createUsageQuery(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -687,13 +686,9 @@ public class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImpl {
|
||||
if (!addedField.isPrivate() && addedField.isStatic()) {
|
||||
affectStaticMemberOnDemandUsages(context, subClass, Collections.emptyList());
|
||||
}
|
||||
else {
|
||||
// ensure analysis scope includes classes that depend on the subclass
|
||||
context.affectUsage(new AffectionScopeMetaUsage(subClass));
|
||||
}
|
||||
}
|
||||
|
||||
context.affectUsage((n, u) -> {
|
||||
context.affectUsage(changedClassWithSubclasses, (n, u) -> {
|
||||
// affect all clients that access fields with the same name via subclasses,
|
||||
// if the added field is not visible to the client
|
||||
if (!(u instanceof FieldUsage) || !(n instanceof JvmClass)) {
|
||||
|
||||
@@ -116,12 +116,13 @@ public final class Utils {
|
||||
}
|
||||
|
||||
public Iterable<JvmNodeReferenceID> allDirectSupertypes(JvmNodeReferenceID classId) {
|
||||
return unique(flat(map(getNodes(classId, JvmClass.class), cl -> map(cl.getSuperTypes(), st -> new JvmNodeReferenceID(st)))));
|
||||
// return only those direct supertypes that exist in the graph as Nodes
|
||||
return unique(flat(map(getNodes(classId, JvmClass.class), cl -> flat(map(cl.getSuperTypes(), st -> map(getNodes(new JvmNodeReferenceID(st), JvmClass.class), JvmClass::getReferenceID))))));
|
||||
}
|
||||
|
||||
public Iterable<JvmNodeReferenceID> allSupertypes(JvmNodeReferenceID classId) {
|
||||
//return Iterators.recurseDepth(className, s -> allDirectSupertypes(s), false);
|
||||
return recurse(classId, s -> allDirectSupertypes(s), false);
|
||||
//return recurseDepth(className, this::allDirectSupertypes, false);
|
||||
return recurse(classId, this::allDirectSupertypes, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -4,7 +4,6 @@ package org.jetbrains.jps.dependency.kotlin;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.dependency.AffectionScopeMetaUsage;
|
||||
import org.jetbrains.jps.dependency.DifferentiateContext;
|
||||
import org.jetbrains.jps.dependency.diff.Difference;
|
||||
import org.jetbrains.jps.dependency.java.*;
|
||||
@@ -70,22 +69,20 @@ public final class KotlinAwareJavaDifferentiateStrategy extends JvmDifferentiate
|
||||
@Override
|
||||
public boolean processAddedMethod(DifferentiateContext context, JvmClass changedClass, JvmMethod addedMethod, Utils future, Utils present) {
|
||||
// any added method may conflict with an extension method to this class, defined elsewhere
|
||||
if (!addedMethod.isPrivate()) {
|
||||
affectConflictingExtensionMethods(context, changedClass, addedMethod, null, future);
|
||||
}
|
||||
affectConflictingExtensionMethods(context, changedClass, addedMethod, null, future);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void affectConflictingExtensionMethods(DifferentiateContext context, JvmClass cls, JvmMethod clsMethod, @Nullable TypeRepr.ClassType samType, Utils utils) {
|
||||
if (clsMethod.isPrivate() || clsMethod.isConstructor()) {
|
||||
return;
|
||||
}
|
||||
// the first arg is always the class being extended
|
||||
Set<String> firstArgTypes = collect(
|
||||
map(flat(utils.allSupertypes(cls.getReferenceID()), utils.collectSubclassesWithoutMethod(cls.getReferenceID(), clsMethod)), id -> id.getNodeName()), new HashSet<>()
|
||||
);
|
||||
firstArgTypes.add(cls.getName());
|
||||
for (String clsName : firstArgTypes) {
|
||||
context.affectUsage(new AffectionScopeMetaUsage(new JvmNodeReferenceID(clsName)));
|
||||
}
|
||||
context.affectUsage((n, u) -> {
|
||||
context.affectUsage(map(firstArgTypes, JvmNodeReferenceID::new), (n, u) -> {
|
||||
if (!(u instanceof MethodUsage) || !(n instanceof JvmClass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ public final class BuildDataManager {
|
||||
if (deleteExisting) {
|
||||
FileUtil.delete(mappingsRoot);
|
||||
}
|
||||
myDepGraph = asSynchronizableGraph(new DependencyGraphImpl(Containers.createPersistentContainerFactory(mappingsRoot.getAbsolutePath())));
|
||||
myDepGraph = asSynchronizedGraph(new DependencyGraphImpl(Containers.createPersistentContainerFactory(mappingsRoot.getAbsolutePath())));
|
||||
}
|
||||
else {
|
||||
try {
|
||||
@@ -216,7 +216,7 @@ public final class BuildDataManager {
|
||||
if (deleteExisting) {
|
||||
FileUtil.delete(mappingsRoot);
|
||||
}
|
||||
myDepGraph = asSynchronizableGraph(new DependencyGraphImpl(Containers.createPersistentContainerFactory(mappingsRoot.getAbsolutePath())));
|
||||
myDepGraph = asSynchronizedGraph(new DependencyGraphImpl(Containers.createPersistentContainerFactory(mappingsRoot.getAbsolutePath())));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -485,7 +485,7 @@ public final class BuildDataManager {
|
||||
};
|
||||
}
|
||||
|
||||
private static DependencyGraph asSynchronizableGraph(DependencyGraph graph) {
|
||||
private static DependencyGraph asSynchronizedGraph(DependencyGraph graph) {
|
||||
//noinspection IOResourceOpenedButNotSafelyClosed
|
||||
DependencyGraph delegate = new LoggingDependencyGraph(graph, msg -> LOG.info(msg));
|
||||
return new DependencyGraph() {
|
||||
|
||||
Reference in New Issue
Block a user