logging deleted paths for tests on full rebuild should not break normal compilation flow if output artifacts are corrupted

- use lighter ZipInputStream and ignore errors from possibly corrupted or non-existing output artifacts (=> means outputs won't be logged and test's expectations won't be met)

drop custom KmType equals checks in favor of ones from kotlin-metadata library

housekeeping: adjust code to higher language level

- drop custom functional interfaces in favor of standard ones, use lambdas where possible


Merge-request: IJ-MR-181593
Merged-by: Eugene Zhuravlev <eugene.zhuravlev@jetbrains.com>

GitOrigin-RevId: 7372a8a5b46bc79ad33e6fb2f420672cab4dcb60
This commit is contained in:
Eugene Zhuravlev
2025-11-07 18:55:39 +00:00
committed by intellij-monorepo-bot
parent b9ea76639f
commit 42c097c4bf
24 changed files with 265 additions and 550 deletions
@@ -5,6 +5,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.util.Iterators;
import java.util.Objects;
public interface Graph {
Iterable<BackDependencyIndex> getIndices();
@@ -47,6 +49,6 @@ public interface Graph {
}
static <T extends Node<T, ?>> Iterable<T> getNodesOfType(Iterable<? extends Node<?, ?>> nodes, Class<T> nodeSelector) {
return Iterators.filter(Iterators.map(nodes, n -> nodeSelector.isInstance(n)? nodeSelector.cast(n) : null), Iterators.notNullFilter());
return Iterators.filter(Iterators.map(nodes, n -> nodeSelector.isInstance(n)? nodeSelector.cast(n) : null), Objects::nonNull);
}
}
@@ -3,7 +3,6 @@ package org.jetbrains.jps.dependency.diff;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.dependency.impl.Containers;
import org.jetbrains.jps.util.Iterators;
import java.util.*;
import java.util.function.BiFunction;
@@ -101,8 +100,8 @@ public interface Difference {
Set<T> pastSet = past instanceof Set? (Set<T>)past : collect(past, new HashSet<>());
Set<T> nowSet = now instanceof Set? (Set<T>)now : collect(now, new HashSet<>());
Iterable<T> added = lazy(() -> collect(filter(nowSet, elem -> !pastSet.contains(elem)), new ArrayList<>()));
Iterable<T> removed = lazy(() -> collect(filter(pastSet, elem -> !nowSet.contains(elem)), new ArrayList<>()));
Iterable<T> added = lazyIterable(() -> collect(filter(nowSet, elem -> !pastSet.contains(elem)), new ArrayList<>()));
Iterable<T> removed = lazyIterable(() -> collect(filter(pastSet, elem -> !nowSet.contains(elem)), new ArrayList<>()));
return new Specifier<>() {
private Boolean isUnchanged;
@@ -124,7 +123,7 @@ public interface Difference {
}
static <T, D extends Difference> Specifier<T, D> deepDiff(@Nullable Iterable<T> past, @Nullable Iterable<T> now, BiPredicate<? super T, ? super T> isSameImpl, Function<? super T, Integer> diffHashImpl, BiFunction<? super T, ? super T, ? extends D> diffImpl) {
Iterators.Function<T, DiffCapable.Adapter<T, D>> mapper = obj -> DiffCapable.wrap(obj, isSameImpl, diffHashImpl, diffImpl);
Function<T, DiffCapable.Adapter<T, D>> mapper = obj -> DiffCapable.wrap(obj, isSameImpl, diffHashImpl, diffImpl);
Specifier<DiffCapable.Adapter<T, D>, D> adapterDiff = deepDiff(map(past, mapper), map(now, mapper));
return new Specifier<>() {
@Override
@@ -203,10 +202,10 @@ public interface Difference {
Set<T> pastSet = collect(past, Containers.createCustomPolicySet(T::isSame, T::diffHashCode));
Set<T> nowSet = collect(now, Containers.createCustomPolicySet(T::isSame, T::diffHashCode));
Iterable<T> added = lazy(() -> collect(filter(nowSet, obj -> !pastSet.contains(obj)), new ArrayList<>()));
Iterable<T> removed = lazy(() -> collect(filter(pastSet, obj -> !nowSet.contains(obj)), new ArrayList<>()));
Iterable<T> added = lazyIterable(() -> collect(filter(nowSet, obj -> !pastSet.contains(obj)), new ArrayList<>()));
Iterable<T> removed = lazyIterable(() -> collect(filter(pastSet, obj -> !nowSet.contains(obj)), new ArrayList<>()));
Iterable<Change<T, D>> changed = lazy(() -> {
Iterable<Change<T, D>> changed = lazyIterable(() -> {
final Map<T, T> nowMap = Containers.createCustomPolicyMap(T::isSame, T::diffHashCode);
for (T s : nowSet) {
if (pastSet.contains(s)) {
@@ -308,7 +308,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
continue;
}
Iterable<JvmNodeReferenceID> propagated = lazy(() -> {
Iterable<JvmNodeReferenceID> propagated = lazyIterable(() -> {
return future.collectSubclassesWithoutMethod(changedClass.getReferenceID(), changedMethod);
});
@@ -429,7 +429,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
for (JvmMethod removedMethod : removed) {
debug(context, "Method ", removedMethod.getName());
Iterable<JvmNodeReferenceID> propagated = lazy(() -> {
Iterable<JvmNodeReferenceID> propagated = lazyIterable(() -> {
return future.collectSubclassesWithoutMethod(changedClass.getReferenceID(), removedMethod);
});
@@ -449,7 +449,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
}
}
else {
Iterable<Pair<JvmClass, JvmMethod>> overridden = removedMethod.isConstructor()? Collections.emptyList() : lazy(() -> {
Iterable<Pair<JvmClass, JvmMethod>> overridden = removedMethod.isConstructor()? Collections.emptyList() : lazyIterable(() -> {
return future.getOverriddenMethods(changedClass, removedMethod::isSameByJavaRules);
});
boolean isClearlyOverridden = removedMethod.getSignature().isEmpty() && !extendsLibraryClass.get() && !isEmpty(overridden) && isEmpty(
@@ -510,7 +510,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
continue;
}
Iterable<JvmNodeReferenceID> propagated = lazy(() -> {
Iterable<JvmNodeReferenceID> propagated = lazyIterable(() -> {
return future.collectSubclassesWithoutMethod(changedClass.getReferenceID(), addedMethod);
});
@@ -529,7 +529,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
}
Predicate<JvmMethod> lessSpecificCond = future.lessSpecific(addedMethod);
for (JvmMethod lessSpecific : filter(changedClass.getMethods(), lessSpecificCond::test)) {
for (JvmMethod lessSpecific : filter(changedClass.getMethods(), lessSpecificCond)) {
debug(context, "Found less specific method, affecting method usages; ", lessSpecific.getName(), lessSpecific.getDescriptor());
affectMemberUsages(context, changedClass.getReferenceID(), lessSpecific, present.collectSubclassesWithoutMethod(changedClass.getReferenceID(), lessSpecific));
}
@@ -573,7 +573,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
return future.getNodes(new JvmNodeReferenceID(cl.getOuterFqName()), JvmClass.class);
}))) {
if (future.isMethodVisible(outerClass, addedMethod) || future.inheritsFromLibraryClass(outerClass)) {
for (NodeSource source : filter(sources, context.getParams().affectionFilter()::test)) {
for (NodeSource source : filter(sources, context.getParams().affectionFilter())) {
debug(context, "Affecting file due to local overriding: ", source);
context.affectNodeSource(source);
}
@@ -696,7 +696,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
debug(context, "Field: ", changedField.getName());
Iterable<JvmNodeReferenceID> propagated = lazy(() -> {
Iterable<JvmNodeReferenceID> propagated = lazyIterable(() -> {
return future.collectSubclassesWithoutField(changedClass.getReferenceID(), changedField);
});
JVMFlags addedFlags = diff.getAddedFlags();
@@ -22,7 +22,7 @@ public abstract class JvmDifferentiateStrategyImpl implements JvmDifferentiateSt
protected final <T extends AnnotationInstance, D extends AnnotationInstance.Diff<T>> boolean isAffectedByAnnotations(
Proto element, Difference.Specifier<T, D> annotationsDiff, Set<AnnotationGroup.AffectionKind> affectionKinds, Predicate<? super TypeRepr.ClassType> annotationSelector
) {
return !element.isPrivate() && find(getAffectedAnnotations(annotationsDiff, affectionKinds), annotationSelector::test) != null;
return !element.isPrivate() && find(getAffectedAnnotations(annotationsDiff, affectionKinds), annotationSelector) != null;
}
protected final <T extends AnnotationInstance, D extends AnnotationInstance.Diff<T>> Iterable<TypeRepr.ClassType> getAffectedAnnotations(
@@ -268,7 +268,7 @@ public abstract class JvmDifferentiateStrategyImpl implements JvmDifferentiateSt
protected void affectSources(DifferentiateContext context, Iterable<NodeSource> sources, String affectReason, boolean forceAffect) {
Set<NodeSource> deletedSources = context.getDelta().getDeletedSources();
Predicate<? super NodeSource> affectionFilter = context.getParams().affectionFilter();
for (NodeSource source : filter(sources, affectionFilter::test)) {
for (NodeSource source : filter(sources, affectionFilter)) {
if ((forceAffect || !context.isCompiled(source)) && !deletedSources.contains(source)) {
context.affectNodeSource(source);
debug(context, affectReason, source);
@@ -193,25 +193,6 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
return null;
}
private static boolean kmTypeProjectionEquals(KmTypeProjection p1, KmTypeProjection p2) {
if (p1 == null) {
return p2 == null;
}
return p2 != null && Objects.equals(p1.getVariance(), p2.getVariance()) && kmTypesEqual(p1.getType(), p2.getType());
}
private static boolean kmTypesEqual(KmType t1, KmType t2) {
// todo: can be removed when KmType properly defines equals() and hashCode()
if (t1 == null) {
return t2 == null;
}
return t2 != null
&& Attributes.isNullable(t1) == Attributes.isNullable(t2)
&& Objects.equals(t1.getClassifier(), t2.getClassifier())
&& kmTypesEqual(t1.getOuterType(), t2.getOuterType())
&& Iterators.equals(t1.getArguments(), t2.getArguments(), KotlinMeta::kmTypeProjectionEquals);
}
public final class Diff implements Difference {
private final KotlinMeta myPast;
@@ -364,7 +345,7 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
public boolean receiverParameterChanged() {
// for example 'fun foo(param: Bar): Any' => 'fun Bar.foo(): Any'
// both declarations will have the same JvmSignature in bytecode so functions will be considered the same by this criterion
return !kmTypesEqual(past.getReceiverParameterType(), now.getReceiverParameterType());
return !Objects.equals(past.getReceiverParameterType(), now.getReceiverParameterType());
}
public boolean hasDefaultDeclarationChanges() {
@@ -377,7 +358,7 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
}
public boolean parameterArgumentsChanged() {
return !Iterators.equals(getParameterTypes(past), getParameterTypes(now), (pastType, nowType) -> Iterators.equals(pastType.getArguments(), nowType.getArguments(), KotlinMeta::kmTypeProjectionEquals));
return !Iterators.equals(getParameterTypes(past), getParameterTypes(now), (pastType, nowType) -> Iterators.equals(pastType.getArguments(), nowType.getArguments()));
}
private static Iterable<KmType> getParameterTypes(KmFunction f) {
@@ -410,7 +391,7 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
}
public boolean underlyingTypeChanged() {
return !kmTypesEqual(past.getUnderlyingType(), now.getUnderlyingType());
return !Objects.equals(past.getUnderlyingType(), now.getUnderlyingType());
}
}
@@ -481,7 +462,7 @@ public final class KotlinMeta implements JvmMetadata<KotlinMeta, KotlinMeta.Diff
}
public boolean typeChanged() {
return !kmTypesEqual(past.getReturnType(), now.getReturnType());
return !Objects.equals(past.getReturnType(), now.getReturnType());
}
public boolean becameNullable() {
@@ -74,7 +74,7 @@ public final class Utils {
Set<NodeSource> deleted = myDelta.getDeletedSources();
return flat(deltaSources, filter(myGraph.getSources(nodeId), src -> !contains(deltaSources, src) && !deleted.contains(src) && mySourcesFilter.test(src)));
}
return filter(myGraph.getSources(nodeId), mySourcesFilter::test);
return filter(myGraph.getSources(nodeId), mySourcesFilter);
}
public Iterable<JvmClass> getClassesByName(@NotNull String name) {
@@ -168,17 +168,17 @@ public final class Utils {
}
}
else {
allNodes = fromDeltaOnly? Collections.emptyList() : flat(map(filter(myGraph.getSources(id), mySourcesFilter::test), src -> myGraph.getNodes(src, selector)));
allNodes = fromDeltaOnly? Collections.emptyList() : flat(map(filter(myGraph.getSources(id), mySourcesFilter), src -> myGraph.getNodes(src, selector)));
}
return filter(allNodes, n -> id.equals(n.getReferenceID()));
}
public static <T> @NotNull Iterable<T> uniqueBy(Iterable<? extends T> it, final BiFunction<? super T, ? super T, Boolean> equalsImpl, final Function<? super T, Integer> hashCodeImpl) {
return Iterators.uniqueBy(it, () -> new BooleanFunction<>() {
return Iterators.uniqueBy(it, () -> new Predicate<>() {
Set<T> visited;
@Override
public boolean fun(T t) {
public boolean test(T t) {
if (visited == null) {
visited = Containers.createCustomPolicySet(equalsImpl, hashCodeImpl);
}
@@ -216,7 +216,7 @@ public final class Utils {
public @NotNull Iterable<ReferenceID> directSubclasses(ReferenceID from) {
if (myDeltaDirectSubclasses != null) {
BooleanFunction<ReferenceID> subClassFilter = sub -> {
Predicate<ReferenceID> subClassFilter = sub -> {
if (myIsNodeDeleted.test(sub)) {
return false;
}
@@ -240,7 +240,7 @@ public final class Utils {
// propagateMemberAccess
private <T extends ProtoMember> Set<JvmNodeReferenceID> collectSubclassesWithoutMember(JvmNodeReferenceID classId, Predicate<? super T> isSame, Function<JvmClass, Iterable<T>> membersGetter) {
Predicate<ReferenceID> containsMember = id -> find(getJvmClassNodes(id), cls -> find(membersGetter.apply(cls), isSame::test) == null) == null;
Predicate<ReferenceID> containsMember = id -> find(getJvmClassNodes(id), cls -> find(membersGetter.apply(cls), isSame) == null) == null;
//stop further traversal, if nodes corresponding to the subclassName contain matching member
Iterable<JvmNodeReferenceID> result = getNodesData(
classId,
@@ -249,7 +249,7 @@ public final class Utils {
Objects::nonNull,
false
);
return collect(filter(result, notNullFilter()), new HashSet<>());
return collect(filter(result, Objects::nonNull), new HashSet<>());
}
public Iterable<Pair<JvmClass, JvmField>> getOverriddenFields(JvmClass fromCls, JvmField field) {
@@ -276,7 +276,7 @@ public final class Utils {
Function<JvmClass, Iterable<JvmMethod>> matchingMethodsGetter = cachingFunction(
cl -> fromCls.isSame(cl)?
List.of() :
collect(filter(cl.getMethods(), searchCond::test), new ArrayList<>())
collect(filter(cl.getMethods(), searchCond), new ArrayList<>())
);
Function<JvmClass, Iterable<Pair<JvmClass, JvmMethod>>> dataGetter = cls -> isVisibleInHierarchy(fromCls, method, cls)? collect(
@@ -309,11 +309,11 @@ public final class Utils {
Function<JvmClass, Iterable<OverloadDescriptor>> mapper = c -> filter(map(c.getMethods(), m -> {
JVMFlags accessScope = correspondenceFinder.apply(m);
return accessScope != null? new OverloadDescriptor(accessScope, m, c) : null;
}), notNullFilter());
}), Objects::nonNull);
return flat(
flat(map(recurse(cls, cl -> flat(map(cl.getSuperTypes(), this::getClassesByName)), true), mapper::apply)),
flat(map(allSubclasses(cls.getReferenceID()), id -> flat(map(getJvmClassNodes(id), mapper::apply))))
flat(map(recurse(cls, cl -> flat(map(cl.getSuperTypes(), this::getClassesByName)), true), mapper)),
flat(map(allSubclasses(cls.getReferenceID()), id -> flat(map(getJvmClassNodes(id), mapper))))
);
}
@@ -326,7 +326,7 @@ public final class Utils {
N fromNode, Function<? super N, ? extends Iterable<? extends N>> step, Function<N, V> dataGetter, Predicate<V> continuationCond, boolean includeHead
) {
Function<N, V> mapper = cachingFunction(dataGetter);
return map(recurseDepth(fromNode, node -> fromNode.equals(node) || continuationCond.test(mapper.apply(node))? step.apply(node): Collections.emptyList(), includeHead), mapper::apply);
return map(recurseDepth(fromNode, node -> fromNode.equals(node) || continuationCond.test(mapper.apply(node))? step.apply(node): Collections.emptyList(), includeHead), mapper);
}
public boolean hasOverriddenMethods(JvmClass cls, JvmMethod method) {
@@ -8,11 +8,11 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.dependency.Node;
import org.jetbrains.jps.dependency.ReferenceID;
import org.jetbrains.jps.dependency.java.*;
import org.jetbrains.jps.util.Iterators;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Objects;
import java.util.function.Function;
import static org.jetbrains.jps.util.Iterators.*;
@@ -117,7 +117,7 @@ final class KJvmUtils {
}
static Iterable<ReferenceID> withAllSubclassesIfSealed(Utils utils, ReferenceID sealedClassId) {
Iterators.Function<ReferenceID, Iterable<? extends ReferenceID>> withSubclassesIfSealed =
Function<ReferenceID, Iterable<? extends ReferenceID>> withSubclassesIfSealed =
id -> flat(map(utils.getNodes(id, JvmClass.class), n -> isSealed(n)? utils.directSubclasses(n.getReferenceID()) : Collections.emptyList()));
return recurse(sealedClassId, withSubclassesIfSealed, true);
}
@@ -10,6 +10,7 @@ import org.jetbrains.jps.dependency.java.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -64,7 +65,7 @@ public final class KotlinSourceOnlyDifferentiateStrategy implements Differentiat
Set<NodeSource> affectedSources = new HashSet<>();
if (!affectedUsages.isEmpty()) {
BooleanFunction<NodeSource> unmodifiedKtSources = s -> !baseSources.contains(s) && !isEmpty(filter(graph.getNodes(s, JvmClass.class), KJvmUtils::isKotlinNode));
Predicate<NodeSource> unmodifiedKtSources = s -> !baseSources.contains(s) && !isEmpty(filter(graph.getNodes(s, JvmClass.class), KJvmUtils::isKotlinNode));
Iterable<NodeSource> supertypeSources = unique(flat(map(unique(filter(flat(map(baseNodes, present::allSupertypes)), id -> !baseNodes.contains(id))), present::getNodeSources)));
@@ -13,6 +13,7 @@ import org.jetbrains.jps.dependency.java.JvmNodeReferenceID;
import org.jetbrains.jps.util.Iterators;
import java.util.Collections;
import java.util.function.Function;
public final class TypealiasesIndex extends BackDependencyIndexImpl {
public static final String NAME = "type-aliases";
@@ -29,7 +30,7 @@ public final class TypealiasesIndex extends BackDependencyIndexImpl {
}
String pkgName = ((JvmClass)node).getPackageName();
Iterators.Function<KmTypeAlias, ReferenceID> mapper =
Function<KmTypeAlias, ReferenceID> mapper =
pkgName.isBlank()?
alias -> new JvmNodeReferenceID(alias.getName()) :
alias -> new JvmNodeReferenceID(pkgName + "." + alias.getName());
+11 -19
View File
@@ -131,12 +131,12 @@ f:org.jetbrains.jps.util.Iterators
- s:contains(java.lang.Iterable,java.lang.Object):Z
- s:count(java.lang.Iterable):I
- s:equals(java.lang.Iterable,java.lang.Iterable):Z
- s:equals(java.lang.Iterable,java.lang.Iterable,org.jetbrains.jps.util.Iterators$BiFunction):Z
- s:filter(java.lang.Iterable,org.jetbrains.jps.util.Iterators$BooleanFunction):java.lang.Iterable
- s:filter(java.util.Iterator,org.jetbrains.jps.util.Iterators$BooleanFunction):java.util.Iterator
- s:equals(java.lang.Iterable,java.lang.Iterable,java.util.function.BiFunction):Z
- s:filter(java.lang.Iterable,java.util.function.Predicate):java.lang.Iterable
- s:filter(java.util.Iterator,java.util.function.Predicate):java.util.Iterator
- s:filterWithOrder(java.lang.Iterable,java.lang.Iterable):java.lang.Iterable
- s:filterWithOrder(java.util.Iterator,java.util.Iterator):java.util.Iterator
- s:find(java.lang.Iterable,org.jetbrains.jps.util.Iterators$BooleanFunction):java.lang.Object
- s:find(java.lang.Iterable,java.util.function.Predicate):java.lang.Object
- s:flat(java.lang.Iterable):java.lang.Iterable
- s:flat(java.lang.Iterable,java.lang.Iterable):java.lang.Iterable
- s:flat(java.util.Collection):java.lang.Iterable
@@ -145,24 +145,16 @@ f:org.jetbrains.jps.util.Iterators
- s:hashCode(java.lang.Iterable):I
- s:isEmpty(java.lang.Iterable):Z
- s:isEmptyCollection(java.lang.Iterable):Z
- s:lazy(org.jetbrains.jps.util.Iterators$Provider):java.lang.Iterable
- s:map(java.lang.Iterable,org.jetbrains.jps.util.Iterators$Function):java.lang.Iterable
- s:map(java.util.Iterator,org.jetbrains.jps.util.Iterators$Function):java.util.Iterator
- s:notNullFilter():org.jetbrains.jps.util.Iterators$BooleanFunction
- s:recurse(java.lang.Object,org.jetbrains.jps.util.Iterators$Function,Z):java.lang.Iterable
- s:recurseDepth(java.lang.Object,org.jetbrains.jps.util.Iterators$Function,Z):java.lang.Iterable
- s:lazyIterable(java.util.function.Supplier):java.lang.Iterable
- s:lazyIterator(java.util.function.Supplier):java.util.Iterator
- s:map(java.lang.Iterable,java.util.function.Function):java.lang.Iterable
- s:map(java.util.Iterator,java.util.function.Function):java.util.Iterator
- s:recurse(java.lang.Object,java.util.function.Function,Z):java.lang.Iterable
- s:recurseDepth(java.lang.Object,java.util.function.Function,Z):java.lang.Iterable
- s:reverse(java.util.List):java.lang.Iterable
- s:unique(java.lang.Iterable):java.lang.Iterable
- s:unique(java.util.Iterator):java.util.Iterator
- s:uniqueBy(java.lang.Iterable,org.jetbrains.jps.util.Iterators$Provider):java.lang.Iterable
org.jetbrains.jps.util.Iterators$BiFunction
- a:fun(java.lang.Object,java.lang.Object):java.lang.Object
org.jetbrains.jps.util.Iterators$BooleanFunction
- a:fun(java.lang.Object):Z
org.jetbrains.jps.util.Iterators$Function
- a:fun(java.lang.Object):java.lang.Object
org.jetbrains.jps.util.Iterators$Provider
- a:get():java.lang.Object
- s:uniqueBy(java.lang.Iterable,java.util.function.Supplier):java.lang.Iterable
c:org.jetbrains.jps.util.Pair
- f:first:java.lang.Object
- f:second:java.lang.Object
@@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.util.Iterators;
import org.jetbrains.jps.util.Iterators.Function;
import org.jetbrains.jps.util.Pair;
import org.jetbrains.jps.util.Ref;
@@ -25,6 +24,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
public final class APIWrappers {
@@ -86,12 +87,7 @@ public final class APIWrappers {
}
Iterable<Processor> wrapProcessors(Iterable<? extends Processor> processors) {
return myAllProcessors = Iterators.map(processors, new Function<Processor, Processor>() {
@Override
public Processor fun(Processor processor) {
return wrap(Processor.class, new ProcessorWrapper(processor, ProcessingContext.this));
}
});
return myAllProcessors = Iterators.map(processors, proc -> wrap(Processor.class, new ProcessorWrapper(proc, this)));
}
@Nullable
@@ -366,7 +362,7 @@ public final class APIWrappers {
private void addMapping(CharSequence resourceName, final Collection<? extends Element> elements) {
if (resourceName != null && resourceName.length() > 0 && !elements.isEmpty()) {
myFileManager.addAnnotationProcessingClassMapping(resourceName.toString(), Iterators.filter(Iterators.map(elements, convertToClassName), Iterators.notNullFilter()));
myFileManager.addAnnotationProcessingClassMapping(resourceName.toString(), Iterators.filter(Iterators.map(elements, convertToClassName), (Predicate<? super String>) Objects::nonNull));
}
}
}
@@ -447,7 +443,7 @@ public final class APIWrappers {
}
@Override
public String fun(Element element) {
public String apply(Element element) {
Name qName = null;
while (element != null) {
if (element instanceof TypeElement) {
@@ -5,8 +5,6 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.util.Iterators;
import org.jetbrains.jps.util.Iterators.BooleanFunction;
import org.jetbrains.jps.util.Iterators.Function;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
@@ -15,6 +13,7 @@ import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.function.Function;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -55,39 +54,23 @@ final class DefaultFileOperations implements FileOperations {
@Override
@NotNull
public Iterable<File> listFiles(final File file, final boolean recursively) {
final Iterable<File> childrenIterable = Iterators.lazy(new Iterators.Provider<Iterable<File>>() {
@Override
public Iterable<File> get() {
final Iterable<File> children = listChildren(file);
return children == null? Collections.<File>emptyList() : children;
}
final Iterable<File> childrenIterable = Iterators.lazyIterable(() -> {
final Iterable<File> children = listChildren(file);
return children == null? Collections.emptyList() : children;
});
return !recursively? childrenIterable : Iterators.flat(Iterators.map(childrenIterable, new Function<File, Iterable<File>>() {
@Override
public Iterable<File> fun(File ff) {
return asRecursiveIterable(ff);
}
}));
return !recursively? childrenIterable : Iterators.flat(Iterators.map(childrenIterable, this::asRecursiveIterable));
}
private Iterable<File> asRecursiveIterable(final File file) {
return Iterators.flat(Iterators.map(Iterators.asIterable(file), new Function<File, Iterable<File>>() {
@Override
public Iterable<File> fun(File f) {
final Iterable<File> children = listChildren(f);
if (children == null) { // not a dir
return Iterators.asIterable(f);
}
if (Iterators.isEmptyCollection(children)) {
return children;
}
return Iterators.flat(Iterators.map(children, new Function<File, Iterable<File>>() {
@Override
public Iterable<File> fun(File ff) {
return asRecursiveIterable(ff);
}
}));
return Iterators.flat(Iterators.map(Iterators.asIterable(file), f -> {
final Iterable<File> children = listChildren(f);
if (children == null) { // not a dir
return Iterators.asIterable(f);
}
if (Iterators.isEmptyCollection(children)) {
return children;
}
return Iterators.flat(Iterators.map(children, ff -> asRecursiveIterable(ff)));
}));
}
@@ -232,12 +215,7 @@ final class DefaultFileOperations implements FileOperations {
private final ZipFile myZip;
private final Map<String, Collection<ZipEntry>> myPaths = new HashMap<>();
private final Function<ZipEntry, JavaFileObject> myToFileObjectConverter;
private static final FileObjectKindFilter<ZipEntry> ourEntryFilter = new FileObjectKindFilter<>(new Function<ZipEntry, String>() {
@Override
public String fun(ZipEntry zipEntry) {
return zipEntry.getName();
}
});
private static final FileObjectKindFilter<ZipEntry> ourEntryFilter = new FileObjectKindFilter<>(ZipEntry::getName);
ZipArchive(final File root, final String encodingName, final JavaFileManager.Location location) throws IOException {
myZip = new ZipFile(root, ZipFile.OPEN_READ);
@@ -254,12 +232,7 @@ final class DefaultFileOperations implements FileOperations {
children.add(entry);
}
}
myToFileObjectConverter = new Function<ZipEntry, JavaFileObject>() {
@Override
public JavaFileObject fun(ZipEntry zipEntry) {
return new ZipFileObject(root, myZip, zipEntry, encodingName, location);
}
};
myToFileObjectConverter = zipEntry -> new ZipFileObject(root, myZip, zipEntry, encodingName, location);
}
@NotNull
@@ -275,19 +248,11 @@ final class DefaultFileOperations implements FileOperations {
entriesIterable = Iterators.flat(myPaths.values());
}
else {
final Iterable<Map.Entry<String, Collection<ZipEntry>>> baseIterable = Iterators.filter(myPaths.entrySet(), new BooleanFunction<Map.Entry<String, Collection<ZipEntry>>>() {
@Override
public boolean fun(Map.Entry<String, Collection<ZipEntry>> e) {
final String dir = e.getKey();
return dir.startsWith(relPath) && (dir.length() == relPath.length() || dir.charAt(relPath.length()) == '/');
}
final Iterable<Map.Entry<String, Collection<ZipEntry>>> baseIterable = Iterators.filter(myPaths.entrySet(), e -> {
final String dir = e.getKey();
return dir.startsWith(relPath) && (dir.length() == relPath.length() || dir.charAt(relPath.length()) == '/');
});
entriesIterable = Iterators.flat(Iterators.map(baseIterable, new Function<Map.Entry<String, Collection<ZipEntry>>, Iterable<ZipEntry>>() {
@Override
public Iterable<ZipEntry> fun(Map.Entry<String, Collection<ZipEntry>> e) {
return e.getValue();
}
}));
entriesIterable = Iterators.flat(Iterators.map(baseIterable, Map.Entry::getValue));
}
}
return Iterators.map(Iterators.filter(entriesIterable, ourEntryFilter.getFor(kinds)), myToFileObjectConverter);
@@ -1,42 +1,33 @@
// Copyright 2000-2025 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.jps.util.Iterators.BooleanFunction;
import org.jetbrains.jps.util.Iterators.Function;
import javax.tools.JavaFileObject;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
final class FileObjectKindFilter<T> {
private final Function<? super T, String> myToNameConverter;
private final Map<JavaFileObject.Kind, BooleanFunction<T>> myFilterMap;
private final Map<JavaFileObject.Kind, Predicate<T>> myFilterMap;
FileObjectKindFilter(Function<? super T, String> toNameConverter) {
myToNameConverter = toNameConverter;
final Map<JavaFileObject.Kind, BooleanFunction<T>> filterMap = new EnumMap<>(JavaFileObject.Kind.class);
final Map<JavaFileObject.Kind, Predicate<T>> filterMap = new EnumMap<>(JavaFileObject.Kind.class);
for (final JavaFileObject.Kind kind : JavaFileObject.Kind.values()) {
if (kind == JavaFileObject.Kind.OTHER) {
filterMap.put(kind, new BooleanFunction<T>() {
@Override
public boolean fun(T data) {
return JpsFileObject.findKind(myToNameConverter.fun(data)) == JavaFileObject.Kind.OTHER;
}
});
filterMap.put(kind, data -> JpsFileObject.findKind(myToNameConverter.apply(data)) == JavaFileObject.Kind.OTHER);
}
else {
filterMap.put(kind, new BooleanFunction<T>() {
@Override
public boolean fun(T data) {
final String name = myToNameConverter.fun(data);
return name.regionMatches(true, name.length() - kind.extension.length(), kind.extension, 0, kind.extension.length());
}
filterMap.put(kind, data -> {
final String name = myToNameConverter.apply(data);
return name.regionMatches(true, name.length() - kind.extension.length(), kind.extension, 0, kind.extension.length());
});
}
}
myFilterMap = Collections.unmodifiableMap(filterMap);
}
public BooleanFunction<T> getFor(final Set<JavaFileObject.Kind> kinds) {
public Predicate<T> getFor(final Set<JavaFileObject.Kind> kinds) {
// optimization for a single-element collection
final Iterator<JavaFileObject.Kind> it = kinds.iterator();
if (it.hasNext()) {
@@ -46,16 +37,13 @@ final class FileObjectKindFilter<T> {
}
}
// OR-filter, quite rare case
return new BooleanFunction<T>() {
@Override
public boolean fun(T data) {
for (JavaFileObject.Kind kind : kinds) {
if (myFilterMap.get(kind).fun(data)) {
return true;
}
return data -> {
for (JavaFileObject.Kind kind : kinds) {
if (myFilterMap.get(kind).test(data)) {
return true;
}
return false;
}
return false;
};
}
@@ -12,8 +12,6 @@ import org.jetbrains.jps.builders.java.JavaCompilingTool;
import org.jetbrains.jps.builders.java.JavaSourceTransformer;
import org.jetbrains.jps.incremental.LineOutputWriter;
import org.jetbrains.jps.util.Iterators;
import org.jetbrains.jps.util.Iterators.BooleanFunction;
import org.jetbrains.jps.util.Iterators.Function;
import javax.annotation.processing.Processor;
import javax.tools.*;
@@ -22,6 +20,7 @@ import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Predicate;
@ApiStatus.Internal
public final class JavacMain {
@@ -199,12 +198,7 @@ public final class JavacMain {
getLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH") == null &&
fileManager.getLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH) == null) {
// default annotation processing discovery path to module path if not explicitly set
setLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH", Iterators.filter(modulePath.getPath(), new BooleanFunction<File>() {
@Override
public boolean fun(File file) {
return !outputDirToRoots.containsKey(file);
}
}));
setLocation(fileManager, "ANNOTATION_PROCESSOR_MODULE_PATH", Iterators.filter(modulePath.getPath(), file -> !outputDirToRoots.containsKey(file)));
}
}
catch (IOException e) {
@@ -343,17 +337,7 @@ public final class JavacMain {
procContext.getFileManager(), StandardLocation.locationFor("ANNOTATION_PROCESSOR_MODULE_PATH"), Processor.class
);
if (processorNames != null) {
processors = Iterators.filterWithOrder(processors, Iterators.map(processorNames, new Function<String, BooleanFunction<? super Processor>>() {
@Override
public BooleanFunction<? super Processor> fun(final String procName) {
return new BooleanFunction<Processor>() {
@Override
public boolean fun(Processor processor) {
return procName.equals(processor.getClass().getName());
}
};
}
}));
processors = Iterators.filterWithOrder(processors, Iterators.map(processorNames, procName -> proc -> procName.equals(proc.getClass().getName())));
}
}
else {
@@ -428,13 +412,8 @@ public final class JavacMain {
private static JavaCompiler.CompilationTask tryInstallClientCodeWrapperCallDispatcher(JavaCompiler.CompilationTask task, StandardJavaFileManager delegateTo) {
try {
final Class<? extends JavaCompiler.CompilationTask> taskClass = task.getClass();
final Field contextField = findField(taskClass, new BooleanFunction<Field>() {
private final Class<?> contextClass = Class.forName("com.sun.tools.javac.util.Context", true, taskClass.getClassLoader());
@Override
public boolean fun(Field field) {
return contextClass.equals(field.getType());
}
});
final Class<?> contextClass = Class.forName("com.sun.tools.javac.util.Context", true, taskClass.getClassLoader());
final Field contextField = findField(taskClass, field -> contextClass.equals(field.getType()));
if (contextField != null) {
final Object contextObject = contextField.get(task);
final Method getMethod = contextObject.getClass().getMethod("get", Class.class);
@@ -456,65 +435,56 @@ public final class JavacMain {
private static void installCallDispatcherRecursively(final Object obj, final StandardJavaFileManager delegateTo, final Set<Object> visited) {
if (obj instanceof JavaFileManager && visited.add(obj)) {
forEachField(obj.getClass(), new BooleanFunction<Field>() {
@Override
public boolean fun(Field field) {
try {
if (JavaFileManager.class.isAssignableFrom(field.getType())) {
final Object value = field.get(obj);
if (isClientCodeWrapper(value, delegateTo)) {
field.set(obj, APIWrappers.wrap(StandardJavaFileManager.class, value, Object.class, delegateTo));
}
else {
installCallDispatcherRecursively(value, delegateTo, visited);
}
forEachField(obj.getClass(), field -> {
try {
if (JavaFileManager.class.isAssignableFrom(field.getType())) {
final Object value = field.get(obj);
if (isClientCodeWrapper(value, delegateTo)) {
field.set(obj, APIWrappers.wrap(StandardJavaFileManager.class, value, Object.class, delegateTo));
}
else {
installCallDispatcherRecursively(value, delegateTo, visited);
}
}
catch (Throwable ignored) {
}
return true;
}
catch (Throwable ignored) {
}
return true;
});
}
}
private static boolean isClientCodeWrapper(final Object obj, final StandardJavaFileManager delegateTo) {
return obj instanceof StandardJavaFileManager && findField(obj.getClass(), new BooleanFunction<Field>() {
@Override
public boolean fun(Field f) {
try {
return f.get(obj) == delegateTo;
}
catch (Throwable ignored) {
return false;
}
return obj instanceof StandardJavaFileManager && findField(obj.getClass(), f -> {
try {
return f.get(obj) == delegateTo;
}
catch (Throwable ignored) {
return false;
}
}) != null;
}
private static Field findField(final Class<?> aClass, final BooleanFunction<? super Field> cond) {
private static Field findField(final Class<?> aClass, final Predicate<? super Field> cond) {
final Field[] res = new Field[]{null};
forEachField(aClass, new BooleanFunction<Field>() {
@Override
public boolean fun(Field field) {
if (!cond.fun(field)) {
return true; // continue
}
res[0] = field;
return false; // stop
forEachField(aClass, field -> {
if (!cond.test(field)) {
return true; // continue
}
res[0] = field;
return false; // stop
});
return res[0];
}
private static void forEachField(final Class<?> aClass, final BooleanFunction<? super Field> func) {
private static void forEachField(final Class<?> aClass, final Predicate<? super Field> func) {
for (Class<?> from = aClass; from != null && !Object.class.equals(from); from = from.getSuperclass()) {
for (Field field : from.getDeclaredFields()) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
if (!func.fun(field)) {
if (!func.test(field)) {
return;
}
}
@@ -7,8 +7,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.java.JavaSourceTransformer;
import org.jetbrains.jps.util.Iterators;
import org.jetbrains.jps.util.Iterators.BooleanFunction;
import org.jetbrains.jps.util.Iterators.Function;
import org.jetbrains.jps.util.SystemInfo;
import javax.tools.*;
@@ -20,6 +18,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
@ApiStatus.Internal
public final class JpsJavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> implements StandardJavaFileManager {
@@ -32,12 +32,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
StandardLocation.SOURCE_PATH,
StandardLocation.ANNOTATION_PROCESSOR_PATH
);
private static final FileObjectKindFilter<File> ourKindFilter = new FileObjectKindFilter<>(new Function<File, String>() {
@Override
public String fun(File file) {
return file.getName();
}
});
private static final FileObjectKindFilter<File> ourKindFilter = new FileObjectKindFilter<>(File::getName);
private final Context myContext;
private final @Nullable JpsJavacFileProvider myJpsJavacFileProvider; // todo: replace with InputFileDataProvider
@@ -49,22 +44,17 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
private final Function<File, JavaFileObject> myFileToInputFileObjectConverter = new Function<File, JavaFileObject>() {
@Override
public JavaFileObject fun(File file) {
public JavaFileObject apply(File file) {
return new InputFileObject(file, myEncodingName, false);
}
};
private final Function<File, JavaFileObject> myFileToCachingInputFileObjectConverter = new Function<File, JavaFileObject>() {
@Override
public JavaFileObject fun(File file) {
public JavaFileObject apply(File file) {
return new InputFileObject(file, myEncodingName, true);
}
};
private static final Function<String, File> ourPathToFileConverter = new Function<String, File>() {
@Override
public File fun(String s) {
return new File(s);
}
};
private static final Function<String, File> ourPathToFileConverter = File::new;
private Map<File, Set<File>> myOutputsMap = Collections.emptyMap();
@Nullable
@@ -137,12 +127,9 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
}
private Iterable<? extends JavaFileObject> wrapJavaFileObjects(final Iterable<? extends JavaFileObject> originalObjects) {
return mySourceTransformers.isEmpty()? originalObjects : Iterators.map(originalObjects, new Function<JavaFileObject, JavaFileObject>() {
@Override
public JavaFileObject fun(JavaFileObject fo) {
return JavaFileObject.Kind.SOURCE.equals(fo.getKind())? new TransformableJavaFileObject(fo, mySourceTransformers) : fo;
}
});
return mySourceTransformers.isEmpty()? originalObjects : Iterators.map(
originalObjects, fo -> JavaFileObject.Kind.SOURCE.equals(fo.getKind())? new TransformableJavaFileObject(fo, mySourceTransformers) : fo
);
}
public Iterable<? extends JavaFileObject> setInputSources(Iterable<? extends File> sources) {
@@ -533,12 +520,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
Iterable<JavaFileObject> providersContent = Iterators.flat(
myJpsJavacFileProvider != null? myJpsJavacFileProvider.list(location, packageName, kinds, recurse) : Collections.emptyList(),
Iterators.map(myInputFileDataProvider != null? myInputFileDataProvider.list(location, packageName, kinds, recurse) : null, new Function<InputFileDataProvider.FileData, JavaFileObject>() {
@Override
public JavaFileObject fun(InputFileDataProvider.FileData fd) {
return new ExtInputFileObject(location, fd.getPath(), myEncodingName, fd.getContent());
}
}));
Iterators.map(myInputFileDataProvider != null? myInputFileDataProvider.list(location, packageName, kinds, recurse) : null, fd -> new ExtInputFileObject(location, fd.getPath(), myEncodingName, fd.getContent())));
final Iterable<? extends File> locationRoots = getLocation(location);
if (Iterators.isEmpty(locationRoots)) {
@@ -546,56 +528,48 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
}
result = Iterators.flat(
providersContent,
Iterators.flat(Iterators.map(locationRoots, new Function<File, Iterable<JavaFileObject>>() {
@Override
public Iterable<JavaFileObject> fun(File root) {
try {
final boolean isFile;
Iterators.flat(Iterators.map(locationRoots, root -> {
try {
final boolean isFile;
FileOperations.Archive archive = myFileOperations.lookupArchive(root);
if (archive != null) {
isFile = true;
}
else {
isFile = myFileOperations.isFile(root);
}
if (isFile) {
// Not a directory; either a file or non-existent, create the archive
try {
if (archive == null) {
archive = myFileOperations.openArchive(root, myEncodingName, location);
}
if (archive != null) {
return archive.list(packageName.replace('.', '/'), kinds, recurse);
}
// fallback to default implementation
return JpsJavacFileManager.super.list(location, packageName, kinds, recurse);
}
catch (IOException ex) {
throw new IOException("Error reading file " + root + ": " + ex.getMessage(), ex);
}
}
// is a directory or does not exist
final File dir = new File(root, packageName.replace('.', '/'));
// Generally, no directories should be included in result. If recurse:= false,
// the fileOperations.listFiles(dir, recurse) output may contain children directories, so the filter should skip them too
final BooleanFunction<File> kindsMatcher = ourKindFilter.getFor(kinds);
final BooleanFunction<File> filter = recurse || !kinds.contains(JavaFileObject.Kind.OTHER)? kindsMatcher : new BooleanFunction<File>() {
@Override
public boolean fun(File file) {
return kindsMatcher.fun(file) && (
!(kinds.size() == 1 || JpsFileObject.findKind(file.getName()) == JavaFileObject.Kind.OTHER) /* the kind != OTHER */ || myFileOperations.isFile(file)
);
}
};
return Iterators.map(Iterators.filter(myFileOperations.listFiles(dir, recurse), filter), location.isOutputLocation()? myFileToInputFileObjectConverter : myFileToCachingInputFileObjectConverter);
FileOperations.Archive archive = myFileOperations.lookupArchive(root);
if (archive != null) {
isFile = true;
}
catch (IOException e) {
throw new RuntimeException(e);
else {
isFile = myFileOperations.isFile(root);
}
if (isFile) {
// Not a directory; either a file or non-existent, create the archive
try {
if (archive == null) {
archive = myFileOperations.openArchive(root, myEncodingName, location);
}
if (archive != null) {
return archive.list(packageName.replace('.', '/'), kinds, recurse);
}
// fallback to default implementation
return JpsJavacFileManager.super.list(location, packageName, kinds, recurse);
}
catch (IOException ex) {
throw new IOException("Error reading file " + root + ": " + ex.getMessage(), ex);
}
}
// is a directory or does not exist
final File dir = new File(root, packageName.replace('.', '/'));
// Generally, no directories should be included in result. If recurse:= false,
// the fileOperations.listFiles(dir, recurse) output may contain children directories, so the filter should skip them too
final Predicate<File> kindsMatcher = ourKindFilter.getFor(kinds);
final Predicate<File> filter = recurse || !kinds.contains(JavaFileObject.Kind.OTHER)? kindsMatcher : file -> kindsMatcher.test(file) && (
!(kinds.size() == 1 || JpsFileObject.findKind(file.getName()) == JavaFileObject.Kind.OTHER) /* the kind != OTHER */ || myFileOperations.isFile(file)
);
return Iterators.map(Iterators.filter(myFileOperations.listFiles(dir, recurse), filter), location.isOutputLocation()? myFileToInputFileObjectConverter : myFileToCachingInputFileObjectConverter);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}))
);
@@ -3,7 +3,6 @@ package org.jetbrains.jps.javac;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.util.Iterators;
import org.jetbrains.jps.util.Iterators.Function;
import java.io.Closeable;
import java.io.File;
@@ -28,15 +27,12 @@ class LazyClassLoader extends ClassLoader implements Closeable {
@Nullable
static LazyClassLoader createFrom(@Nullable Iterable<? extends File> files, ClassLoader parent) {
return Iterators.isEmptyCollection(files)? null : new LazyClassLoader(Iterators.map(files, new Function<File, URL>() {
@Override
public URL fun(File f) {
try {
return f.toURI().toURL();
}
catch (MalformedURLException e) {
throw new AssertionError(e);
}
return Iterators.isEmptyCollection(files)? null : new LazyClassLoader(Iterators.map(files, f -> {
try {
return f.toURI().toURL();
}
catch (MalformedURLException e) {
throw new AssertionError(e);
}
}), parent);
}
@@ -47,7 +43,7 @@ class LazyClassLoader extends ClassLoader implements Closeable {
synchronized (myUrls) {
delegate = myDelegate;
if (delegate == null) {
myDelegate = delegate = new DelegateClassLoader(Iterators.collect(myUrls, new ArrayList<URL>()).toArray(EMPTY_URL_ARRAY), myParent);
myDelegate = delegate = new DelegateClassLoader(Iterators.collect(myUrls, new ArrayList<>()).toArray(EMPTY_URL_ARRAY), myParent);
}
}
}
@@ -5,11 +5,11 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.BinaryContent;
import org.jetbrains.jps.util.Iterators;
import org.jetbrains.jps.util.Iterators.Function;
import javax.tools.*;
import javax.tools.JavaFileManager;
import java.io.*;
import java.net.URI;
import java.util.Objects;
public final class OutputFileObject extends JpsFileObject {
@Nullable
@@ -73,12 +73,7 @@ public final class OutputFileObject extends JpsFileObject {
@NotNull
public Iterable<File> getSourceFiles() {
return Iterators.filter(Iterators.map(getSourceUris(), new Function<URI, File>() {
@Override
public File fun(URI uri) {
return "file".equalsIgnoreCase(uri.getScheme())? new File(uri) : null;
}
}), Iterators.notNullFilter());
return Iterators.filter(Iterators.map(getSourceUris(), uri -> "file".equalsIgnoreCase(uri.getScheme())? new File(uri) : null), Objects::nonNull);
}
@NotNull
@@ -4,15 +4,12 @@ package org.jetbrains.jps.util;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public final class Iterators {
@SuppressWarnings("rawtypes")
private static final BooleanFunction NOT_NULL_FILTER = new BooleanFunction() {
@Override
public boolean fun(Object s) {
return s != null;
}
};
public static boolean isEmpty(Iterable<?> iterable) {
return isEmptyCollection(iterable) || !iterable.iterator().hasNext();
@@ -47,10 +44,10 @@ public final class Iterators {
return count;
}
public static <T> T find(Iterable<? extends T> iterable, BooleanFunction<? super T> cond) {
public static <T> T find(Iterable<? extends T> iterable, Predicate<? super T> cond) {
if (iterable != null) {
for (T o : iterable) {
if (cond.fun(o)) {
if (cond.test(o)) {
return o;
}
}
@@ -71,37 +68,22 @@ public final class Iterators {
return acc;
}
public interface Provider<T> {
T get();
}
public interface Function<S, T> {
T fun(S s);
public static <T> Iterable<T> lazyIterable(final Supplier<? extends Iterable<T>> provider) {
final Supplier<? extends Iterable<T>> delegate = cachedValue(provider);
return () -> delegate.get().iterator();
}
public interface BiFunction<S1, S2, T> {
T fun(S1 s1, S2 s2);
}
public interface BooleanFunction<T> {
boolean fun(T t);
}
public static <T> Iterable<T> lazy(final Provider<? extends Iterable<T>> provider) {
return new Iterable<T>() {
private Iterable<T> myDelegate = null;
@NotNull
public static <T> Iterator<T> lazyIterator(final Supplier<? extends Iterator<T>> provider) {
return new Iterator<T>() {
private final Supplier<? extends Iterator<T>> delegate = cachedValue(provider);
@Override
public Iterator<T> iterator() {
return getDelegate().iterator();
public boolean hasNext() {
return delegate.get().hasNext();
}
private Iterable<T> getDelegate() {
Iterable<T> delegate = myDelegate;
if (delegate == null) {
myDelegate = delegate = provider.get();
}
return delegate;
@Override
public T next() {
return delegate.get().next();
}
};
}
@@ -114,17 +96,11 @@ public final class Iterators {
if (isEmptyCollection(second)) {
return (Iterable<T>)first;
}
return new Iterable<T>() {
@Override
@NotNull
public Iterator<T> iterator() {
return flat(first.iterator(), second.iterator());
}
};
return () -> flat(first.iterator(), second.iterator());
}
public static <T> Iterator<T> flat(final Iterator<? extends T> first, final Iterator<? extends T> second) {
return new BaseIterator<T>() {
return new Iterator<T>() {
@Override
public boolean hasNext() {
return first.hasNext() || second.hasNext();
@@ -149,22 +125,11 @@ public final class Iterators {
}
public static <T> Iterable<T> flat(final Iterable<? extends Iterable<? extends T>> parts) {
return isEmptyCollection(parts) ? Collections.emptyList() : new Iterable<T>() {
@NotNull
@Override
public Iterator<T> iterator() {
return flat(map(parts.iterator(), new Function<Iterable<? extends T>, Iterator<T>>() {
@Override
public Iterator<T> fun(Iterable<? extends T> itr) {
return asIterator(itr);
}
}));
}
};
return isEmptyCollection(parts) ? Collections.emptyList() : () -> flat(map(parts.iterator(), Iterators::asIterator));
}
public static <T> Iterator<T> flat(final Iterator<? extends Iterator<T>> groupsIterator) {
return new BaseIterator<T>() {
return new Iterator<T>() {
private Iterator<T> currentGroup;
@Override
@@ -199,13 +164,7 @@ public final class Iterators {
}
public static <T> Iterable<T> asIterable(final T elem) {
return new Iterable<T>() {
@NotNull
@Override
public Iterator<T> iterator() {
return asIterator(elem);
}
};
return () -> asIterator(elem);
}
public static <T> Iterable<T> asIterable(final T[] elem) {
@@ -218,7 +177,7 @@ public final class Iterators {
@Override
public Iterator<T> iterator() {
final ListIterator<T> li = list.listIterator(list.size());
return new BaseIterator<T>() {
return new Iterator<T>() {
@Override
public boolean hasNext() {
return li.hasPrevious();
@@ -234,7 +193,7 @@ public final class Iterators {
}
public static <T> Iterator<T> asIterator(final T elem) {
return new BaseIterator<T>() {
return new Iterator<T>() {
private boolean available = true;
@Override
@@ -254,17 +213,11 @@ public final class Iterators {
}
public static <I,O> Iterable<O> map(final Iterable<? extends I> from, final Function<? super I, ? extends O> mapper) {
return isEmptyCollection(from) ? Collections.emptyList() : new Iterable<O>() {
@NotNull
@Override
public Iterator<O> iterator() {
return map(from.iterator(), mapper);
}
};
return isEmptyCollection(from) ? Collections.emptyList() : () -> map(from.iterator(), mapper);
}
public static <I,O> Iterator<O> map(final Iterator<? extends I> it, final Function<? super I, ? extends O> mapper) {
return new BaseIterator<O>() {
return new Iterator<O>() {
@Override
public boolean hasNext() {
return it.hasNext();
@@ -272,23 +225,17 @@ public final class Iterators {
@Override
public O next() {
return mapper.fun(it.next());
return mapper.apply(it.next());
}
};
}
public static <T> Iterable<T> filter(final Iterable<? extends T> it, final BooleanFunction<? super T> predicate) {
return isEmptyCollection(it) ? Collections.emptyList() : new Iterable<T>() {
@NotNull
@Override
public Iterator<T> iterator() {
return filter(it.iterator(), predicate);
}
};
public static <T> Iterable<T> filter(final Iterable<? extends T> it, final Predicate<? super T> predicate) {
return isEmptyCollection(it) ? Collections.emptyList() : () -> filter(it.iterator(), predicate);
}
public static <T> Iterator<T> filter(final Iterator<? extends T> it, final BooleanFunction<? super T> predicate) {
return new BaseIterator<T>() {
public static <T> Iterator<T> filter(final Iterator<? extends T> it, final Predicate<? super T> predicate) {
return new Iterator<T>() {
private T current = null;
private boolean isPending = false;
@@ -322,7 +269,7 @@ public final class Iterators {
current = null;
while (it.hasNext()) {
final T next = it.next();
if (predicate.fun(next)) {
if (predicate.test(next)) {
isPending = true;
current = next;
break;
@@ -332,25 +279,19 @@ public final class Iterators {
};
}
public static <T> Iterable<T> filterWithOrder(final Iterable<? extends T> from, final Iterable<? extends BooleanFunction<? super T>> predicates) {
return isEmptyCollection(predicates) || isEmptyCollection(from) ? Collections.emptyList() : new Iterable<T>() {
@NotNull
@Override
public Iterator<T> iterator() {
return filterWithOrder(from.iterator(), predicates.iterator());
}
};
public static <T> Iterable<T> filterWithOrder(final Iterable<? extends T> from, final Iterable<? extends Predicate<? super T>> predicates) {
return isEmptyCollection(predicates) || isEmptyCollection(from)? Collections.emptyList() : () -> filterWithOrder(from.iterator(), predicates.iterator());
}
public static <T> Iterator<T> filterWithOrder(final Iterator<? extends T> from, final Iterator<? extends BooleanFunction<? super T>> predicates) {
return flat(map(predicates, new Function<BooleanFunction<? super T>, Iterator<T>>() {
public static <T> Iterator<T> filterWithOrder(final Iterator<? extends T> from, final Iterator<? extends Predicate<? super T>> predicates) {
return flat(map(predicates, new Function<Predicate<? super T>, Iterator<T>>() {
final List<T> buffer = new LinkedList<>();
@Override
public Iterator<T> fun(BooleanFunction<? super T> pred) {
public Iterator<T> apply(Predicate<? super T> pred) {
if (!buffer.isEmpty()) {
for (Iterator<T> it = buffer.iterator(); it.hasNext(); ) {
final T elem = it.next();
if (pred.fun(elem)) {
if (pred.test(elem)) {
it.remove();
return asIterator(elem);
}
@@ -358,7 +299,7 @@ public final class Iterators {
}
while(from.hasNext()) {
final T elem = from.next();
if (pred.fun(elem)) {
if (pred.test(elem)) {
return asIterator(elem);
}
buffer.add(elem);
@@ -370,50 +311,20 @@ public final class Iterators {
}
public static <T> Iterable<T> unique(final Iterable<? extends T> it) {
return isEmptyCollection(it) ? Collections.emptyList() : new Iterable<T>() {
@NotNull
@Override
public Iterator<T> iterator() {
return unique(it.iterator());
}
};
return isEmptyCollection(it) ? Collections.emptyList() : () -> unique(it.iterator());
}
public static <T> Iterator<T> unique(final Iterator<? extends T> it) {
return filter(it, new BooleanFunction<T>() {
private Set<T> processed;
@Override
public boolean fun(T t) {
if (processed == null) {
processed = new HashSet<>();
}
return processed.add(t);
}
});
Supplier<Set<Object>> processed = cachedValue(HashSet::new);
return filter(it, e -> processed.get().add(e));
}
public static <T> Iterable<T> uniqueBy(final Iterable<? extends T> it, final Provider<? extends BooleanFunction<T>> predicateFactory) {
return isEmptyCollection(it) ? Collections.emptyList() : new Iterable<T>() {
@NotNull
@Override
public Iterator<T> iterator() {
return filter(it.iterator(), predicateFactory.get());
}
};
}
@SuppressWarnings("unchecked")
public static <T> BooleanFunction<? super T> notNullFilter() {
return (BooleanFunction<T>)NOT_NULL_FILTER;
public static <T> Iterable<T> uniqueBy(final Iterable<? extends T> it, final Supplier<? extends Predicate<T>> predicateFactory) {
return isEmptyCollection(it) ? Collections.emptyList() : () -> filter(it.iterator(), predicateFactory.get());
}
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);
}
});
return equals(s1, s2, Object::equals);
}
public static <T> boolean equals(Iterable<? extends T> s1, Iterable<? extends T> s2, BiFunction<? super T, ? super T, Boolean> comparator) {
@@ -422,7 +333,7 @@ public final class Iterators {
if (!it2.hasNext()) {
return false;
}
if (!comparator.fun(elem, it2.next())) {
if (!comparator.apply(elem, it2.next())) {
return false;
}
}
@@ -454,28 +365,13 @@ public final class Iterators {
return tailOf(elem);
}
return flat(asIterator(elem), new LazyIterator<T>() {
@Override
protected Iterator<? extends T> create() {
return tailOf(elem);
}
});
return flat(asIterator(elem), lazyIterator(() -> tailOf(elem)));
}
@NotNull
private Iterator<T> tailOf(final T elem) {
final Iterable<? extends T> tail = filter(step.fun(elem), new BooleanFunction<T>() {
@Override
public boolean fun(T e) {
return !traversed.contains(e);
}
});
return flat(tail.iterator(), flat(map(tail.iterator(), new Function<T, Iterator<T>>() {
@Override
public Iterator<T> fun(T obj) {
return recurse(obj, false);
}
})));
final Iterable<? extends T> tail = filter(step.apply(elem), e -> !traversed.contains(e));
return flat(tail.iterator(), flat(map(tail.iterator(), e -> recurse(e, false))));
}
}.recurse(item, includeHead);
@@ -497,26 +393,11 @@ public final class Iterators {
}
if (!includeHead) {
return flat(map(step.fun(elem).iterator(), new Function<T, Iterator<T>>() {
@Override
public Iterator<T> fun(T obj) {
return recurse(obj, true);
}
}));
return flat(map(step.apply(elem).iterator(), e -> recurse(e, true)));
}
Iterator<? extends T> tail = new LazyIterator<T>() {
@Override
protected Iterator<? extends T> create() {
return step.fun(elem).iterator();
}
};
return flat(asIterator(elem), flat(map(tail, new Function<T, Iterator<T>>() {
@Override
public Iterator<T> fun(T obj) {
return recurse(obj, true);
}
})));
Iterator<? extends T> tail = lazyIterator(() -> step.apply(elem).iterator());
return flat(asIterator(elem), flat(map(tail, e -> recurse(e, true))));
}
}.recurse(item, includeHead);
@@ -524,39 +405,15 @@ public final class Iterators {
};
}
private abstract static class BaseIterator<T> implements Iterator<T> {
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private static <V> Supplier<V> cachedValue(Supplier<V> valueFactory) {
return new Supplier<V>() {
private Object[] computed;
private abstract static class LazyIterator<T> implements Iterator<T> {
private Iterator<? extends T> myDelegate;
protected abstract Iterator<? extends T> create();
@Override
public boolean hasNext() {
return getDelegate().hasNext();
}
@Override
public T next() {
return getDelegate().next();
}
@Override
public void remove() {
getDelegate().remove();
}
private Iterator<? extends T> getDelegate() {
Iterator<? extends T> delegate = myDelegate;
if (delegate == null) {
myDelegate = delegate = create();
@Override
public V get() {
//noinspection unchecked
return computed == null? (V)(computed = new Object[] {valueFactory.get()})[0] : (V)computed[0];
}
return delegate;
}
};
}
}
@@ -20,7 +20,9 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import static org.jetbrains.jps.util.Iterators.*;
@@ -56,13 +58,15 @@ public class StorageManager implements CloseableExt {
BuildProcessLogger logger = myContext.getBuildLogger();
if (logger.isEnabled() && !myContext.isRebuild()) {
// need this for tests
Set<String> deleted = new HashSet<>();
Path outBackup = DataPaths.getJarBackupStoreFile(myContext, output);
try (var out = new ZipOutputBuilderImpl(Files.exists(outBackup)? outBackup : output)) {
collect(out.getEntryNames(), deleted);
try (var is = new BufferedInputStream(Files.newInputStream(Files.exists(outBackup)? outBackup : output))) {
List<String> paths = collect(filter(map(new ZipEntryIterator(is), ze -> ze.getEntry().getName()), n -> !n.endsWith("/")), new ArrayList<>());
if (!paths.isEmpty()) {
logger.logDeletedPaths(paths);
}
}
if (!isEmpty(deleted)) {
logger.logDeletedPaths(deleted);
catch (IOException ignored) {
// ignore corrupted or non-existing zips
}
}
@@ -206,7 +210,7 @@ public class StorageManager implements CloseableExt {
GraphConfiguration config = myGraphConfig;
if (config != null) {
myGraphConfig = null;
writeKotlinCriData(config.getGraph(), saveChanges);
writeKotlinCriData(config.getGraph(), saveChanges);
safeClose(config.getGraph(), saveChanges);
}
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
@@ -116,8 +117,8 @@ public class BuildDiagnosticCollector {
var digestRenderer = new Object() {
void formatDigest(String label, ConfigurationState past, ConfigurationState present, Function<? super ConfigurationState, Long> dataAccessor) {
long pastValue = dataAccessor.fun(past);
long presentValue = dataAccessor.fun(present);
long pastValue = dataAccessor.apply(past);
long presentValue = dataAccessor.apply(present);
readme.format("%n%-20s digest %s => %s %s", label, Long.toHexString(pastValue), Long.toHexString(presentValue), (pastValue == presentValue ? "(unchanged)" : "(modified)"));
}
};
@@ -8,7 +8,6 @@ import org.jetbrains.jps.dependency.GraphDataOutput;
import org.jetbrains.jps.dependency.NodeSource;
import org.jetbrains.jps.dependency.NodeSourcePathMapper;
import org.jetbrains.jps.dependency.impl.*;
import org.jetbrains.jps.util.Iterators;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -18,6 +17,7 @@ import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Deflater;
@@ -143,7 +143,7 @@ public class ConfigurationState {
NodeSourceSnapshot deps = getLibraries();
// digest name, count and order of classpath entries as well as content digests of all non-abi deps
Iterators.Function<@NotNull NodeSource, Iterable<String>> digestMapper =
Function<@NotNull NodeSource, Iterable<String>> digestMapper =
src -> {
Path path = myPathMapper.toPath(src);
return DataPaths.isLibraryTracked(path)? List.of(DataPaths.getLibraryName(path)) : List.of(DataPaths.getLibraryName(path), deps.getDigest(src));
@@ -170,7 +170,7 @@ public class ConfigurationState {
};
return Utils.digest(
flat(map(filter(Arrays.asList(CLFlags.values()), flg -> flags.containsKey(flg) && !ourIgnoredFlags.contains(flg)), flg -> flat(asIterable(flg.name()), sorted.fun(flags.get(flg)))))
flat(map(filter(Arrays.asList(CLFlags.values()), flg -> flags.containsKey(flg) && !ourIgnoredFlags.contains(flg)), flg -> flat(asIterable(flg.name()), sorted.apply(flags.get(flg)))))
);
}
@@ -45,6 +45,7 @@ import java.io.FileFilter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.logging.Level;
@@ -449,7 +450,7 @@ public final class JavaBuilderUtil {
// some compilers (and compiler plugins) may produce different outputs for the same set of inputs.
// This might cause corresponding graph Nodes to be considered as always 'changed'. In some scenarios this may lead to endless build loops
// This fallback logic detects such loops and recompiles the whole module chunk instead.
Set<NodeSource> affectedForChunk = Iterators.collect(Iterators.filter(diffResult.getAffectedSources(), differentiateParams.belongsToCurrentCompilationChunk()::test), new HashSet<>());
Set<NodeSource> affectedForChunk = Iterators.collect(Iterators.filter(diffResult.getAffectedSources(), differentiateParams.belongsToCurrentCompilationChunk()), new HashSet<>());
if (!affectedForChunk.isEmpty() && !getOrCreate(context, ALL_AFFECTED_NODE_SOURCES_KEY, HashSet::new).addAll(affectedForChunk)) {
// all affected files in this round have already been affected in previous rounds. This might indicate a build cycle => recompiling whole chunk
LOG.info("Build cycle detected for " + chunk.getName() + "; recompiling whole module chunk");
@@ -738,12 +739,7 @@ public final class JavaBuilderUtil {
}
Set<BuildTarget<?>> targetOfFileWithDependencies = myCache.computeIfAbsent(
targetOfFile,
trg -> Iterators.collect(Iterators.recurseDepth(trg, new Iterators.Function<BuildTarget<?>, Iterable<? extends BuildTarget<?>>>() {
@Override
public Iterable<? extends BuildTarget<?>> fun(BuildTarget<?> t) {
return myBuildTargetIndex.getDependencies(t, myContext);
}
}, false), new HashSet<>())
trg -> Iterators.collect(Iterators.recurseDepth(trg, (Function<BuildTarget<?>, Iterable<? extends BuildTarget<?>>>) t -> myBuildTargetIndex.getDependencies(t, myContext), false), new HashSet<>())
);
return ContainerUtil.intersects(targetOfFileWithDependencies, myChunkTargets);
}
@@ -233,7 +233,7 @@ public class Mappings {
Iterators.map(
Iterators.flat(Iterators.map(myClassToRelativeSourceFilePath.get(qName), src -> myRelativeSourceFilePathToClasses.get(src))),
repr -> repr.name == qName && selector.isInstance(repr)? selector.cast(repr) : null
), Iterators.notNullFilter()
), Objects::nonNull
));
}
@@ -573,13 +573,13 @@ public class Mappings {
Function<ClassRepr, Iterable<OverloadDescriptor>> converter = c -> Iterators.filter(Iterators.map(c.getMethods(), m -> {
Integer accessScope = correspondenceFinder.apply(m);
return accessScope != null? new OverloadDescriptor(accessScope, m, c) : null;
}), Iterators.notNullFilter());
}), Objects::nonNull);
return Iterators.flat(Iterators.flat(
collectRecursively(cls, converter),
Iterators.map(
Iterators.flat(Iterators.map(getAllSubclasses(cls.name), subName -> subName != cls.name? reprsByName(subName, ClassRepr.class) : Collections.emptyList())),
repr -> converter.apply(repr)
converter
)
));
}
@@ -2348,7 +2348,7 @@ public class Mappings {
}
}
return null;
}), Iterators.notNullFilter());
}), Objects::nonNull);
for (Pair<ClassFileRepr, File> pair : dependentReprs) {
if (!dependentReprProcessor.apply(pair.getFirst(), pair.getSecond())) {
@@ -30,10 +30,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
public final class GroovyBuilder extends ModuleLevelBuilder {
private static final Logger LOG = Logger.getInstance(GroovyBuilder.class);
@@ -167,7 +164,7 @@ public final class GroovyBuilder extends ModuleLevelBuilder {
public void process(CompileContext context, OutputFileObject out) {
final Map<String, String> stubToSrc = STUB_TO_SRC.get(context);
if (stubToSrc != null) {
for (String groovy : Iterators.filter(Iterators.map(out.getSourceFiles(), file -> stubToSrc.get(FileUtil.toSystemIndependentName(file.getPath()))), Iterators.notNullFilter())) {
for (String groovy : Iterators.filter(Iterators.map(out.getSourceFiles(), file -> stubToSrc.get(FileUtil.toSystemIndependentName(file.getPath()))), Objects::nonNull)) {
try {
Path groovyFile = Path.of(groovy);
if (!FSOperations.isMarkedDirty(context, CompilationRound.CURRENT, groovyFile)) {