Check priming on each subproject.
diff --git a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
index 2faf221..ea7db73 100644
--- a/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
+++ b/java/java.lsp.server/src/org/netbeans/modules/java/lsp/server/protocol/Server.java
@@ -52,6 +52,7 @@
import java.util.concurrent.CompletionException;
import java.util.stream.Collectors;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import org.eclipse.lsp4j.CallHierarchyRegistrationOptions;
import org.eclipse.lsp4j.CodeActionKind;
@@ -644,13 +645,11 @@
f.completeExceptionally(ex);
}
}
-
- private void asyncOpenSelectedProjects1(CompletableFuture<Project[]> f, Project[] previouslyOpened, Project[] candidateMapping, List<Project> projects, boolean addToWorkspace) {
- int id = this.openRequestId.getAndIncrement();
-
- List<CompletableFuture> primingBuilds = new ArrayList<>();
+
+ CompletableFuture<Void>[] primeProjects(Collection<Project> projects, int id, Map<Project, CompletableFuture<Void>> local) {
List<Project> toOpen = new ArrayList<>();
- Map<Project, CompletableFuture<Void>> local = new HashMap<>();
+ List<CompletableFuture<Void>> primingBuilds = new ArrayList<>();
+
synchronized (this) {
LOG.log(Level.FINER, "{0}: Opening project(s): {1}", new Object[]{ id, Arrays.asList(projects) });
for (Project p : projects) {
@@ -664,7 +663,7 @@
}
beingOpened.putAll(local);
}
- long t = System.currentTimeMillis();
+
LOG.log(Level.FINER, id + ": Opening projects: {0}", Arrays.asList(toOpen));
// before the projects are officialy 'opened', try to prime the projects
@@ -698,9 +697,20 @@
pap.invokeAction(ActionProvider.COMMAND_PRIME, Lookups.fixed(progress));
}
}
+ return primingBuilds.toArray(new CompletableFuture[0]);
+ }
+
+ private void asyncOpenSelectedProjects1(CompletableFuture<Project[]> f, Project[] previouslyOpened, Project[] candidateMapping, List<Project> initialProjects, boolean addToWorkspace) {
+ long t = System.currentTimeMillis();
+ int id = this.openRequestId.getAndIncrement();
+ Map<Project, CompletableFuture<Void>> local = new HashMap<>();
- // Wait for all priming builds, even those already pending, to finish:
- CompletableFuture.allOf(primingBuilds.toArray(new CompletableFuture[0])).thenRun(() -> {
+ CompletableFuture[] primingBuilds = primeProjects(initialProjects, id, local);
+
+ AtomicReference<Consumer<Collection<Project>>> subprojectProcessor = new AtomicReference();
+ Set<Project> processedProjects = new HashSet<>();
+ AtomicInteger level = new AtomicInteger(1);
+ subprojectProcessor.set((projects) -> {
Set<Project> additionalProjects = new LinkedHashSet<>();
for (Project prj : projects) {
Set<Project> containedProjects = ProjectUtils.getContainedProjects(prj, true);
@@ -709,53 +719,75 @@
additionalProjects.addAll(containedProjects);
}
}
- projects.addAll(additionalProjects);
- OpenProjects.getDefault().open(projects.toArray(new Project[0]), false);
- try {
- LOG.log(Level.FINER, "{0}: Calling openProjects() for : {1}", new Object[]{id, Arrays.asList(projects)});
- OpenProjects.getDefault().openProjects().get();
- } catch (InterruptedException | ExecutionException ex) {
- throw new IllegalStateException(ex);
- }
- for (Project prj : projects) {
- //init source groups/FileOwnerQuery:
- ProjectUtils.getSources(prj).getSourceGroups(Sources.TYPE_GENERIC);
- final CompletableFuture<Void> prjF = local.get(prj);
- if (prjF != null) {
- prjF.complete(null);
+ additionalProjects.removeAll(processedProjects);
+ additionalProjects.removeAll(projects);
+
+ processedProjects.addAll(projects);
+
+ LOG.log(Level.FINE, "Processing subprojects, level {0}: {1}", new Object[] { level.getAndIncrement(), additionalProjects });
+
+ if (additionalProjects.isEmpty()) {
+ OpenProjects.getDefault().open(processedProjects.toArray(new Project[processedProjects.size()]), false);
+ try {
+ LOG.log(Level.FINER, "{0}: Calling openProjects() for : {1}", new Object[]{id, Arrays.asList(processedProjects)});
+ OpenProjects.getDefault().openProjects().get();
+ } catch (InterruptedException | ExecutionException ex) {
+ throw new IllegalStateException(ex);
}
- }
- Set<Project> projectSet = new HashSet<>(Arrays.asList(OpenProjects.getDefault().getOpenProjects()));
- projectSet.retainAll(openedProjects);
- projectSet.addAll(projects);
-
- Project[] prjsRequested = projects.toArray(new Project[0]);
- Project[] prjs = projects.toArray(new Project[0]);
- LOG.log(Level.FINER, "{0}: Finished opening projects: {1}", new Object[]{id, Arrays.asList(projects)});
- synchronized (this) {
- openedProjects = projectSet;
- if (addToWorkspace) {
- Set<Project> ns = new HashSet<>(projects);
- List<Project> current = Arrays.asList(workspaceProjects.getNow(new Project[0]));
- int s = current.size();
- ns.addAll(current);
- LOG.log(Level.FINER, "Current is: {0}, ns: {1}", new Object[] { current, ns });
- if (s != ns.size()) {
- prjs = ns.toArray(new Project[0]);
- workspaceProjects = CompletableFuture.completedFuture(prjs);
+ for (Project prj : processedProjects) {
+ //init source groups/FileOwnerQuery:
+ ProjectUtils.getSources(prj).getSourceGroups(Sources.TYPE_GENERIC);
+ final CompletableFuture<Void> prjF = local.get(prj);
+ if (prjF != null) {
+ prjF.complete(null);
}
}
- for (Project p : prjs) {
- // override flag in opening cache, no further questions asked.
- openingFileOwners.put(p, f.thenApply(unused -> p));
+ Set<Project> projectSet = new HashSet<>(Arrays.asList(OpenProjects.getDefault().getOpenProjects()));
+ projectSet.retainAll(openedProjects);
+ projectSet.addAll(processedProjects);
+
+ Project[] prjsRequested = projects.toArray(new Project[processedProjects.size()]);
+ Project[] prjs = projects.toArray(new Project[processedProjects.size()]);
+ LOG.log(Level.FINER, "{0}: Finished opening projects: {1}", new Object[]{id, Arrays.asList(processedProjects)});
+ synchronized (this) {
+ openedProjects = projectSet;
+ if (addToWorkspace) {
+ Set<Project> ns = new HashSet<>(processedProjects);
+ List<Project> current = Arrays.asList(workspaceProjects.getNow(new Project[0]));
+ int s = current.size();
+ ns.addAll(current);
+ LOG.log(Level.FINER, "Current is: {0}, ns: {1}", new Object[] { current, ns });
+ if (s != ns.size()) {
+ prjs = ns.toArray(new Project[ns.size()]);
+ workspaceProjects = CompletableFuture.completedFuture(prjs);
+ }
+ }
+ for (Project p : prjs) {
+ // override flag in opening cache, no further questions asked.
+ openingFileOwners.put(p, f.thenApply(unused -> p));
+ }
}
+ f.complete(candidateMapping);
+ LOG.log(Level.INFO, "{0} projects opened in {1}ms", new Object[] { prjsRequested.length, (System.currentTimeMillis() - t) });
+ } else {
+ LOG.log(Level.FINER, "{0}: Collecting projects to prime from: {1}", new Object[]{id, Arrays.asList(additionalProjects)});
+ CompletableFuture[] nextPrimingBuilds = primeProjects(additionalProjects, id, local);
+ CompletableFuture.allOf(nextPrimingBuilds).thenRun(() -> {
+ subprojectProcessor.get().accept(additionalProjects);
+ }).exceptionally(e -> {
+ f.completeExceptionally(e);
+ return null;
+ });
}
- f.complete(candidateMapping);
- LOG.log(Level.INFO, "{0} projects opened in {1}ms", new Object[] { prjsRequested.length, (System.currentTimeMillis() - t) });
+ });
+
+ // Wait for all priming builds, even those already pending, to finish:
+ CompletableFuture.allOf(primingBuilds).thenRun(() -> {
+ subprojectProcessor.get().accept(initialProjects);
}).exceptionally(e -> {
f.completeExceptionally(e);
return null;
- });
+ });
}
private JavaSource checkJavaSupport() {