CompletableFuture<Void> (@Nullable Type type, Function<? super Type, ? extends CompletableFuture<Boolean>> checker, CompletableFuture<Type> res) { if (type == null || res.isDone()) { return completedFuture(null); } // check self CompletableFuture<Void> self = checker.apply(type).thenAccept(r -> { if (r) { res.complete(type); } }); // check base types if (type instanceof ClassType) { return allOf( self, superclass((ClassType)type).thenCompose(s -> findAnyBaseType(s, checker, res)), interfaces((ClassType)type).thenCompose( interfaces -> allOf(interfaces.stream().map(i -> findAnyBaseType(i, checker, res)).toArray(CompletableFuture[]::new)))); } if (type instanceof InterfaceType) { return allOf( self, superinterfaces((InterfaceType)type).thenCompose( interfaces -> allOf(interfaces.stream().map(i -> findAnyBaseType(i, checker, res)).toArray(CompletableFuture[]::new)))); } return self; }