JPS mappings for incremental compilation refactoring: mark hierarchy-induced dependencies on initial stage before compilation starts

GitOrigin-RevId: 2d4543e13729ee6a8d1df393565e6d128f59645f
This commit is contained in:
Eugene Zhuravlev
2024-04-16 12:02:05 +02:00
committed by intellij-monorepo-bot
parent fb25fbd19e
commit f8674d9894
13 changed files with 238 additions and 88 deletions

View File

@@ -2783,6 +2783,7 @@ f:org.jetbrains.jps.dependency.AffectionScopeMetaUsage
- hashCode():I
- write(org.jetbrains.jps.dependency.GraphDataOutput):V
org.jetbrains.jps.dependency.BackDependencyIndex
- s:createEmpty(java.lang.String):org.jetbrains.jps.dependency.BackDependencyIndex
- a:getDependencies(org.jetbrains.jps.dependency.ReferenceID):java.lang.Iterable
- a:getKeys():java.lang.Iterable
- a:getName():java.lang.String
@@ -2808,10 +2809,11 @@ org.jetbrains.jps.dependency.Delta
- a:associate(org.jetbrains.jps.dependency.Node,java.lang.Iterable):V
- a:getBaseSources():java.util.Set
- a:getDeletedSources():java.util.Set
- a:isSourceOnly():Z
org.jetbrains.jps.dependency.DependencyGraph
- java.io.Closeable
- org.jetbrains.jps.dependency.Graph
- a:createDelta(java.lang.Iterable,java.lang.Iterable):org.jetbrains.jps.dependency.Delta
- a:createDelta(java.lang.Iterable,java.lang.Iterable,Z):org.jetbrains.jps.dependency.Delta
- a:differentiate(org.jetbrains.jps.dependency.Delta,org.jetbrains.jps.dependency.DifferentiateParameters):org.jetbrains.jps.dependency.DifferentiateResult
- a:integrate(org.jetbrains.jps.dependency.DifferentiateResult):V
org.jetbrains.jps.dependency.DifferentiateContext

View File

@@ -131,12 +131,8 @@ public final class JavaBuilderUtil {
NodeSourcePathMapper pathMapper = graphConfig.getPathMapper();
Set<File> inputFiles = getFilesContainer(context, FILES_TO_COMPILE_KEY);
Set<File> compiledWithErrors = getFilesContainer(context, COMPILED_WITH_ERRORS_KEY);
List<Pair<Node<?, ?>, Iterable<NodeSource>>> compiledNodes;
if (callback != null) {
compiledNodes = callback.getNodes();
// Important: in case of errors some sources sent to recompilation might not have corresponding output classes either because a source has compilation errors
// or because compiler stopped compilation and has not managed to compile some sources.
// In this case use empty set of delta's "base sources" for dependency calculation, so that only actually recompiled sources will take part in dependency analysis and affected files calculation.
@@ -145,9 +141,10 @@ public final class JavaBuilderUtil {
Set<File> deltaBaseSources = Utils.errorsDetected(context)? Collections.emptySet() : inputFiles;
delta = graphConfig.getGraph().createDelta(
Iterators.map(deltaBaseSources, pathMapper::toNodeSource),
Iterators.map(getRemovedPaths(chunk, dirtyFilesHolder), pathMapper::toNodeSource)
Iterators.map(getRemovedPaths(chunk, dirtyFilesHolder), pathMapper::toNodeSource),
false
);
for (var nodeData : compiledNodes) {
for (var nodeData : callback.getNodes()) {
delta.associate(nodeData.getFirst(), nodeData.getSecond());
}
// todo: consider using delta for marking additional sources for compilation
@@ -157,32 +154,11 @@ public final class JavaBuilderUtil {
// }
//}
}
else {
compiledNodes = Collections.emptyList();
}
boolean additionalPassRequired = false;
if (Utils.errorsDetected(context) || !inputFiles.isEmpty() && compiledNodes.isEmpty()) {
// In case of compilation errors additionally mark files referenced from "error"-files.
// So next time compilation is invoked, the compilation scope will be broader: directly used dependencies will be compiled as well.
DependencyGraph graph = graphConfig.getGraph();
Set<File> errFiles = !compiledWithErrors.isEmpty()? compiledWithErrors : inputFiles;
Iterable<Node<?, ?>> nodesWithErrors = Iterators.flat(Iterators.map(Iterators.map(errFiles, pathMapper::toNodeSource), graph::getNodes));
Iterable<ReferenceID> usedDependencies = Iterators.unique(Iterators.map(Iterators.flat(Iterators.map(nodesWithErrors, Node::getUsages)), Usage::getElementOwner));
for (File src : Iterators.filter(Iterators.map(Iterators.unique(Iterators.flat(Iterators.map(usedDependencies, graph::getSources))), ns -> pathMapper.toPath(ns).toFile()), f -> !inputFiles.contains(f))) {
additionalPassRequired = true;
FSOperations.markDirtyIfNotDeleted(context, CompilationRound.NEXT, src);
}
}
for (Key<?> key : List.of(GRAPH_DELTA_CALLBACK_KEY, FILES_TO_COMPILE_KEY, COMPILED_WITH_ERRORS_KEY, SUCCESSFULLY_COMPILED_FILES_KEY)) {
key.set(context, null);
}
if (delta != null && updateDependencyGraph(context, delta, chunk, CompilationRound.NEXT, createOrFilter(SKIP_MARKING_DIRTY_FILTERS_KEY.get(context)))) {
additionalPassRequired = true;
}
return additionalPassRequired;
return delta != null && updateDependencyGraph(context, delta, chunk, CompilationRound.NEXT, createOrFilter(SKIP_MARKING_DIRTY_FILTERS_KEY.get(context)));
}
Mappings delta = null;
@@ -226,20 +202,25 @@ public final class JavaBuilderUtil {
}
public static void markDirtyDependenciesForInitialRound(CompileContext context, DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dfh, ModuleChunk chunk) throws IOException {
if (hasRemovedPaths(chunk, dfh)) {
BuildDataManager dataManager = context.getProjectDescriptor().dataManager;
GraphConfiguration graphConfig = dataManager.getDependencyGraph();
if (isDepGraphEnabled() && graphConfig != null) {
NodeSourcePathMapper mapper = graphConfig.getPathMapper();
BuildDataManager dataManager = context.getProjectDescriptor().dataManager;
GraphConfiguration graphConfig = dataManager.getDependencyGraph();
if (isDepGraphEnabled() && graphConfig != null) {
NodeSourcePathMapper mapper = graphConfig.getPathMapper();
Set<NodeSource> toCompile = new HashSet<>();
dfh.processDirtyFiles((target, file, root) -> toCompile.add(mapper.toNodeSource(file)));
if (!toCompile.isEmpty() || hasRemovedPaths(chunk, dfh)) {
Delta delta = graphConfig.getGraph().createDelta(
Collections.emptyList(), Iterators.map(getRemovedPaths(chunk, dfh), mapper::toNodeSource)
toCompile, Iterators.map(getRemovedPaths(chunk, dfh), mapper::toNodeSource), true
);
updateDependencyGraph(context, delta, chunk, CompilationRound.CURRENT, null);
return;
}
final Mappings delta = dataManager.getMappings().createDelta();
final Set<File> empty = Collections.emptySet();
updateMappings(context, delta, dfh, chunk, empty, empty, CompilationRound.CURRENT, null);
}
else {
if (hasRemovedPaths(chunk, dfh)) {
final Mappings delta = dataManager.getMappings().createDelta();
final Set<File> empty = Collections.emptySet();
updateMappings(context, delta, dfh, chunk, empty, empty, CompilationRound.CURRENT, null);
}
}
}

View File

@@ -1,8 +1,10 @@
// 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.dependency;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public interface BackDependencyIndex {
@NotNull String getName();
@@ -13,4 +15,33 @@ public interface BackDependencyIndex {
void indexNode(@NotNull Node<?, ?> node);
void integrate(Iterable<Node<?, ?>> deletedNodes, Iterable<Node<?, ?>> updatedNodes, BackDependencyIndex deltaIndex);
static BackDependencyIndex createEmpty(String name) {
return new BackDependencyIndex() {
@Override
public @NotNull String getName() {
return name;
}
@Override
public Iterable<ReferenceID> getKeys() {
return Collections.emptyList();
}
@Override
public Iterable<ReferenceID> getDependencies(@NotNull ReferenceID id) {
return Collections.emptyList();
}
@Override
public void indexNode(@NotNull Node<?, ?> node) {
// nothing here
}
@Override
public void integrate(Iterable<Node<?, ?>> deletedNodes, Iterable<Node<?, ?>> updatedNodes, BackDependencyIndex deltaIndex) {
// nothing here
}
};
}
}

View File

@@ -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.dependency;
import org.jetbrains.annotations.NotNull;
@@ -10,6 +10,12 @@ import java.util.Set;
*/
public interface Delta extends Graph {
/**
* @return true, if this Delta describes only changes in sources and no Nodes were generated, because compiler has not been run.
* Value false means the Delta object contains changes in sources and possibly in Nodes, because compiler has been run and new set of Nodes corresponding to the new content of sources has been generated
*/
boolean isSourceOnly();
/**
* @param node node reflecting compilation unit built by a compiler
* @param sources sources, that were used to build the node

View File

@@ -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.dependency;
import org.jetbrains.annotations.NotNull;
@@ -11,7 +11,7 @@ import java.io.IOException;
*/
public interface DependencyGraph extends Graph, Closeable {
Delta createDelta(Iterable<NodeSource> sourcesToProcess, Iterable<NodeSource> deletedSources) throws IOException;
Delta createDelta(Iterable<NodeSource> sourcesToProcess, Iterable<NodeSource> deletedSources, boolean isSourceOnly) throws IOException;
DifferentiateResult differentiate(Delta delta, DifferentiateParameters params);

View File

@@ -26,11 +26,16 @@ public final class DeltaImpl extends GraphImpl implements Delta {
private final Set<NodeSource> myBaseSources;
private final Set<NodeSource> myDeletedSources;
public DeltaImpl(Set<NodeSource> baseSources, Iterable<NodeSource> deletedSources) throws IOException {
DeltaImpl(Iterable<NodeSource> baseSources, Iterable<NodeSource> deletedSources) throws IOException {
super(Containers.MEMORY_CONTAINER_FACTORY);
addIndex(new SubclassesIndex(Containers.MEMORY_CONTAINER_FACTORY));
myBaseSources = Collections.unmodifiableSet(baseSources);
myDeletedSources = Collections.unmodifiableSet(Iterators.collect(deletedSources, new HashSet<>()));
myBaseSources = Collections.unmodifiableSet(baseSources instanceof Set? (Set<? extends NodeSource>)baseSources : Iterators.collect(baseSources, new HashSet<>()));
myDeletedSources = Collections.unmodifiableSet(deletedSources instanceof Set? (Set<? extends NodeSource>)deletedSources : Iterators.collect(deletedSources, new HashSet<>()));
}
@Override
public boolean isSourceOnly() {
return false;
}
@Override

View File

@@ -28,8 +28,8 @@ public final class DependencyGraphImpl extends GraphImpl implements DependencyGr
}
@Override
public Delta createDelta(Iterable<NodeSource> compiledSources, Iterable<NodeSource> deletedSources) throws IOException {
DeltaImpl delta = new DeltaImpl(completeSourceSet(compiledSources, deletedSources), deletedSources);
public Delta createDelta(Iterable<NodeSource> compiledSources, Iterable<NodeSource> deletedSources, boolean isSourceOnly) throws IOException {
Delta delta = isSourceOnly? new SourceOnlyDelta(myRegisteredIndices, compiledSources, deletedSources) : new DeltaImpl(compiledSources, deletedSources);
Set<String> deltaIndices = collect(map(delta.getIndices(), index -> index.getName()), new HashSet<>());
if (!myRegisteredIndices.equals(deltaIndices)) {
@@ -44,9 +44,9 @@ public final class DependencyGraphImpl extends GraphImpl implements DependencyGr
String sessionName = params.getSessionName();
Iterable<NodeSource> deltaSources = delta.getSources();
Set<NodeSource> allProcessedSources = collect(flat(Arrays.asList(delta.getBaseSources(), deltaSources, delta.getDeletedSources())), new HashSet<>());
Set<NodeSource> allProcessedSources = delta.isSourceOnly()? delta.getDeletedSources() : collect(flat(Arrays.asList(delta.getBaseSources(), deltaSources, delta.getDeletedSources())), new HashSet<>());
Set<Node<?, ?>> nodesBefore = collect(flat(map(allProcessedSources, this::getNodes)), Containers.createCustomPolicySet(DiffCapable::isSame, DiffCapable::diffHashCode));
Set<Node<?, ?>> nodesAfter = collect(flat(map(deltaSources, delta::getNodes)), Containers.createCustomPolicySet(DiffCapable::isSame, DiffCapable::diffHashCode));
Set<Node<?, ?>> nodesAfter = delta.isSourceOnly()? Collections.emptySet() : collect(flat(map(deltaSources, delta::getNodes)), Containers.createCustomPolicySet(DiffCapable::isSame, DiffCapable::diffHashCode));
// do not process 'removed' per-source file. This works when a class comes from exactly one source, but might not work, if a class can be associated with several sources
// better make a node-diff over all compiled sources => the sets of removed, added, deleted _nodes_ will be more accurate and reflecting reality
@@ -209,6 +209,26 @@ public final class DependencyGraphImpl extends GraphImpl implements DependencyGr
}
}
}
if (delta.isSourceOnly()) {
// Some nodes may be associated with multiple sources. In this case ensure that all these sources are sent to compilation
Set<NodeSource> inputSources = delta.getBaseSources();
Set<NodeSource> deleted = delta.getDeletedSources();
Predicate<? super NodeSource> srcFilter = diffContext.getParams().belongsToCurrentCompilationChunk().and(s -> !deleted.contains(s));
for (var node : flat(map(flat(inputSources, deleted), this::getNodes))) {
Iterable<NodeSource> nodeSources = getSources(node.getReferenceID());
if (count(nodeSources) > 1) {
List<NodeSource> filteredNodeSources = collect(filter(nodeSources, srcFilter::test), new SmartList<>());
// all sources associated with the node should be either marked 'dirty' or deleted
if (find(filteredNodeSources, s -> !inputSources.contains(s)) != null) {
for (NodeSource s : filteredNodeSources) {
diffContext.affectNodeSource(s);
}
}
}
}
}
// do not include sources that were already compiled
affectedSources.removeAll(allProcessedSources);
// ensure sources explicitly marked by strategies are affected, even if these sources were compiled initially
@@ -303,27 +323,6 @@ public final class DependencyGraphImpl extends GraphImpl implements DependencyGr
}
}
/**
* Returns a complete set of node sources based on the input set of node sources.
* Some nodes may be associated with multiple sources. If a source from the input set is associated with such a node,
* the method makes sure the output set contains the rest of the sources, the node is associated with
*
* @param sources set of node sources to be completed.
* @param deletedSources registered deleted sources
* @return complete set of node sources, containing all sources associated with nodes affected by the sources from the input set.
*/
private Set<NodeSource> completeSourceSet(Iterable<NodeSource> sources, Iterable<NodeSource> deletedSources) {
// ensure initial sources are in the result
Set<NodeSource> result = collect(sources, new HashSet<>()); // todo: check if a special hashing-policy set is required here
Set<NodeSource> deleted = collect(deletedSources, new HashSet<>());
Set<Node<?, ?>> affectedNodes = collect(flat(map(flat(result, deleted), s -> getNodes(s))), new HashSet<>());
for (var node : affectedNodes) {
collect(filter(getSources(node.getReferenceID()), s -> !result.contains(s) && !deleted.contains(s) && filter(getNodes(s).iterator(), affectedNodes::contains).hasNext()), result);
}
return result;
}
private static final class DiffChangeAdapter implements Difference.Change<Node<?, ?>, Difference> {
private final Difference.Change<Node, ?> myDelegate;

View File

@@ -30,8 +30,8 @@ public final class LoggingDependencyGraph extends LoggingGraph implements Depend
}
@Override
public Delta createDelta(Iterable<NodeSource> sourcesToProcess, Iterable<NodeSource> deletedSources) throws IOException {
return getDelegate().createDelta(sourcesToProcess, deletedSources);
public Delta createDelta(Iterable<NodeSource> sourcesToProcess, Iterable<NodeSource> deletedSources, boolean isSourceOnly) throws IOException {
return getDelegate().createDelta(sourcesToProcess, deletedSources, isSourceOnly);
}
@Override

View File

@@ -0,0 +1,78 @@
// 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.dependency.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.dependency.*;
import org.jetbrains.jps.javac.Iterators;
import java.util.*;
final class SourceOnlyDelta implements Delta {
private final Set<NodeSource> myBaseSources;
private final Set<NodeSource> myDeletedSources;
private final Map<String, BackDependencyIndex> myIndices = new HashMap<>();
SourceOnlyDelta(Iterable<String> indexNames, Iterable<NodeSource> baseSources, Iterable<NodeSource> deletedSources) {
myBaseSources = Collections.unmodifiableSet(baseSources instanceof Set? (Set<? extends NodeSource>)baseSources : Iterators.collect(baseSources, new HashSet<>()));
myDeletedSources = Collections.unmodifiableSet(deletedSources instanceof Set? (Set<? extends NodeSource>)deletedSources : Iterators.collect(deletedSources, new HashSet<>()));
for (String name : indexNames) {
myIndices.put(name, BackDependencyIndex.createEmpty(name));
}
}
@Override
public boolean isSourceOnly() {
return true;
}
@Override
public Set<NodeSource> getBaseSources() {
return myBaseSources;
}
@Override
public Set<NodeSource> getDeletedSources() {
return myDeletedSources;
}
@Override
public void associate(@NotNull Node<?, ?> node, @NotNull Iterable<NodeSource> sources) {
// nothing here todo: throw exception?
}
@Override
public Iterable<BackDependencyIndex> getIndices() {
return myIndices.values();
}
@Override
public @Nullable BackDependencyIndex getIndex(String name) {
return myIndices.get(name);
}
@Override
public @NotNull Iterable<ReferenceID> getDependingNodes(@NotNull ReferenceID id) {
return Collections.emptyList();
}
@Override
public Iterable<NodeSource> getSources(@NotNull ReferenceID id) {
return Collections.emptyList();
}
@Override
public Iterable<ReferenceID> getRegisteredNodes() {
return Collections.emptyList();
}
@Override
public Iterable<NodeSource> getSources() {
return Collections.emptyList();
}
@Override
public Iterable<Node<?, ?>> getNodes(@NotNull NodeSource source) {
return Collections.emptyList();
}
}

View File

@@ -1,19 +1,21 @@
// 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.dependency.java;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.SmartList;
import org.jetbrains.jps.dependency.DifferentiateContext;
import org.jetbrains.jps.dependency.DifferentiateStrategy;
import org.jetbrains.jps.dependency.Graph;
import org.jetbrains.jps.dependency.Node;
import org.jetbrains.jps.dependency.*;
import org.jetbrains.jps.dependency.diff.Difference;
import java.util.Collections;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Predicate;
import static org.jetbrains.jps.javac.Iterators.collect;
import static org.jetbrains.jps.javac.Iterators.*;
public final class GeneralJvmDifferentiateStrategy implements DifferentiateStrategy {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.dependency.java.GeneralJvmDifferentiateStrategy");
private static final Iterable<JvmDifferentiateStrategy> ourExtensions = collect(
ServiceLoader.load(JvmDifferentiateStrategy.class, GeneralJvmDifferentiateStrategy.class.getClassLoader()),
new SmartList<>()
@@ -30,10 +32,52 @@ public final class GeneralJvmDifferentiateStrategy implements DifferentiateStrat
}
@Override
public boolean differentiate(DifferentiateContext context, Iterable<Node<?, ?>> nodesBefore, Iterable<Node<?, ?>> nodesAfter) {
public boolean
differentiate(DifferentiateContext context, Iterable<Node<?, ?>> nodesBefore, Iterable<Node<?, ?>> nodesAfter) {
Utils future = new Utils(context, true);
Utils present = new Utils(context, false);
Delta delta = context.getDelta();
if (delta.isSourceOnly()) {
new Object() {
private final Predicate<? super NodeSource> inCurrentChunk = context.getParams().belongsToCurrentCompilationChunk();
private final Set<NodeSource> baseSources = delta.getBaseSources();
private boolean isMarked(NodeSource src) {
return isMarked(Collections.singleton(src));
}
private boolean isMarked(Iterable<NodeSource> sources) {
return find(sources, baseSources::contains) != null;
}
boolean traverse(JvmClass cl, boolean isRoot) {
boolean parentsMarked = false;
for (JvmClass superCl : present.allDirectSupertypes(cl)) {
parentsMarked |= traverse(superCl, false);
}
if (isRoot) {
return true;
}
Iterable<NodeSource> nodeSources = present.getNodeSources(cl.getReferenceID());
if (parentsMarked) {
for (NodeSource source : filter(nodeSources, s -> !isMarked(s) && inCurrentChunk.test(s))) {
LOG.debug("Intermediate class in a class hierarchy is not marked for compilation, while one of its subclasses and superclasses are going to be recompiled. Affecting " + source.toString());
context.affectNodeSource(source);
}
}
return parentsMarked || isMarked(nodeSources);
}
void markSources() {
Graph graph = context.getGraph();
for (JvmClass cls : flat(map(baseSources, s -> graph.getNodes(s, JvmClass.class)))) {
traverse(cls, true);
}
}
}.markSources();
}
Difference.Specifier<JvmClass, JvmClass.Diff> classesDiff = Difference.deepDiff(
Graph.getNodesOfType(nodesBefore, JvmClass.class), Graph.getNodesOfType(nodesAfter, JvmClass.class)
);

View File

@@ -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.incremental.storage;
import com.intellij.openapi.diagnostic.Logger;
@@ -521,10 +521,10 @@ public final class BuildDataManager {
private final ReadWriteLock lock = new ReentrantReadWriteLock();
@Override
public Delta createDelta(Iterable<NodeSource> sourcesToProcess, Iterable<NodeSource> deletedSources) throws IOException {
public Delta createDelta(Iterable<NodeSource> sourcesToProcess, Iterable<NodeSource> deletedSources, boolean isSourceOnly) throws IOException {
lock.readLock().lock();
try {
return delegate.createDelta(sourcesToProcess, deletedSources);
return delegate.createDelta(sourcesToProcess, deletedSources, isSourceOnly);
}
finally {
lock.readLock().unlock();

View File

@@ -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.dependency;
import com.intellij.openapi.util.io.FileUtil;
@@ -26,7 +26,7 @@ public class NodeGraphPersistentTest extends BasePlatformTestCase {
NodeSource bSrc = createNodeSource("B");
// This should be executed before compiler run
Delta delta = graph.createDelta(Arrays.asList(aSrc, bSrc), null);
Delta delta = graph.createDelta(Arrays.asList(aSrc, bSrc), null, false);
JvmClass jvmClassNode = JvmClassTestUtil.createJvmClassNode();
// Analyze after compiler
@@ -58,7 +58,7 @@ public class NodeGraphPersistentTest extends BasePlatformTestCase {
NodeSource aSrc = createNodeSource("A");
NodeSource bSrc = createNodeSource("B");
Delta initialDelta = graph.createDelta(Arrays.asList(aSrc, bSrc), null);
Delta initialDelta = graph.createDelta(Arrays.asList(aSrc, bSrc), null, false);
JvmClass clsNodeA = new JvmClass(JVMFlags.EMPTY, "", "com.ppp.aClass", "out/modA/cls", "", "", Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), null, Collections.emptyList(), Collections.emptyList());
initialDelta.associate(clsNodeA, List.of(aSrc));
JvmClass clsNodeB = new JvmClass(JVMFlags.EMPTY, "", "com.ppp.aClass", "out/modB/cls", "", "", Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), null, Collections.emptyList(), Collections.emptyList());
@@ -82,7 +82,7 @@ public class NodeGraphPersistentTest extends BasePlatformTestCase {
assertEquals(new HashSet<>(List.of(aSrc, bSrc)), associatedSources);
// emulate contents of aSrc changed and now a node with different changeID is associated with this source
Delta delta = graph.createDelta(Arrays.asList(aSrc), null);
Delta delta = graph.createDelta(Arrays.asList(aSrc), null, false);
JvmClass clsNodeAChanged = new JvmClass(JVMFlags.EMPTY, "", "com.ppp.aChangedClass", "out/modA/cls", "", "", Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), null, Collections.emptyList(), Collections.emptyList());
delta.associate(clsNodeAChanged, List.of(aSrc));
DifferentiateResult changes = graph.differentiate(delta, DifferentiateParametersBuilder.create().calculateAffected(false).get());

View File

@@ -4,8 +4,10 @@ Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/foo/DirectBase.class
out/production/module/foo/DirectChild.class
out/production/module/foo/DirectInter.class
End of files
Compiling files:
src/DirectInter.kt
src/direct.kt
End of files
Exit code: OK
@@ -17,8 +19,10 @@ Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/foo/ReverseBase.class
out/production/module/foo/ReverseChild.class
out/production/module/foo/ReverseInter.class
End of files
Compiling files:
src/ReverseInter.kt
src/reverse.kt
End of files
Exit code: OK