diff --git a/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenLemminxWorkspaceReader.java b/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenLemminxWorkspaceReader.java index 8944d65f..bb1857ce 100644 --- a/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenLemminxWorkspaceReader.java +++ b/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenLemminxWorkspaceReader.java @@ -72,7 +72,11 @@ public void run() { skipFlushBeforeResult.set(true); // avoid deadlock as building project will go through this workspace reader Optional snapshotProject = Optional.empty(); try { - snapshotProject = plugin.getProjectCache().getSnapshotProject(pomFile); + // Just getting a snapshot project using `getSnapshotProject` is not enough here + // because it doesn't adds the read projects to the projects cache. + // So we need to parse and cache the project here + // + snapshotProject = Optional.of(plugin.getProjectCache().getLastSuccessfulMavenProject(pomFile)); } catch (Exception e) { // We shouldn't fail here, otherwise, the pomFile will never be processed // causing a possible deadlock in "Flush Before Result" loops @@ -296,7 +300,7 @@ public void addToWorkspace(Collection uris) { .filter(File::isFile) .filter(file -> !workspaceArtifacts.values().contains(file)) // ignore already processed .forEach(toProcess::add); - for (File file : toProcess.stream().collect(Collectors.toSet())) { + for (File file : toProcess.stream().collect(Collectors.toList())) { executor.execute(new ResolveArtifactsAndPopulateWorkspaceRunnable(file)); } } diff --git a/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenProjectCache.java b/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenProjectCache.java index 66151a89..4e8c06c4 100644 --- a/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenProjectCache.java +++ b/lemminx-maven/src/main/java/org/eclipse/lemminx/extensions/maven/MavenProjectCache.java @@ -77,8 +77,10 @@ public MavenProjectCache(MavenLemminxExtension lemminxMavenPlugin) { } /** - * - * @param document + * Returns the last successfully parsed and cached Maven Project for the + * given document + * + * @param document A given Document * @return the last MavenDocument that could be build for the more recent * version of the provided document. If document fails to build a * MavenProject, a former version will be returned. Can be @@ -89,6 +91,21 @@ public MavenProject getLastSuccessfulMavenProject(DOMDocument document) { return projectCache.get(URI.create(document.getTextDocument().getUri()).normalize()); } + /** + * Returns the last successfully parsed and cached Maven Project for the + * given POM file + * + * @param pomFile A given POM File + * @return the last MavenDocument that could be build for the more recent + * version of the provided document. If document fails to build a + * MavenProject, a former version will be returned. Can be + * null. + */ + public MavenProject getLastSuccessfulMavenProject(File pomFile) { + check(pomFile); + return projectCache.get(pomFile.toURI().normalize()); + } + /** * * @param document @@ -107,6 +124,13 @@ private void check(DOMDocument document) { } } + private void check(File pomFile) { + Integer last = lastCheckedVersion.get(pomFile.toURI().normalize()); + if (last == null || last.intValue() < 1) { + parseAndCache(pomFile); + } + } + public Optional getSnapshotProject(File file) { MavenProject lastKnownVersionMavenProject = projectCache.get(file.toURI().normalize()); if (lastKnownVersionMavenProject != null) { @@ -129,16 +153,10 @@ public Optional getSnapshotProject(File file) { return Optional.empty(); } - private void parseAndCache(DOMDocument document) { - URI uri = URI.create(document.getDocumentURI()).normalize(); + private void parseAndCache(URI uri, int version, FileModelSource source) { Collection problems = new ArrayList<>(); try { - ProjectBuildingResult buildResult = projectBuilder.build(new FileModelSource(new File(uri)) { - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(document.getText().getBytes()); - } - }, newProjectBuildingRequest()); + ProjectBuildingResult buildResult = projectBuilder.build(source, newProjectBuildingRequest()); problems.addAll(buildResult.getProblems()); if (buildResult.getProject() != null) { // setFile should ideally be invoked during project build, but related methods @@ -147,7 +165,7 @@ public InputStream getInputStream() throws IOException { projectCache.put(uri, buildResult.getProject()); projectParsedListeners.forEach(listener -> listener.accept(buildResult.getProject())); } - lastCheckedVersion.put(uri, document.getTextDocument().getVersion()); + lastCheckedVersion.put(uri, version); problemCache.put(uri, problems); } catch (ProjectBuildingException e) { if (e.getResults() == null) { @@ -156,8 +174,7 @@ public InputStream getInputStream() throws IOException { // errors and to have something usable in cache for most basic operations problems.addAll(modelBuildingException.getProblems()); File file = new File(uri); - try (ByteArrayInputStream documentStream = new ByteArrayInputStream( - document.getText().getBytes())) { + try (InputStream documentStream = source.getInputStream()) { Model model = mavenReader.read(documentStream); MavenProject project = new MavenProject(model); project.setRemoteArtifactRepositories(model.getRepositories().stream() @@ -195,7 +212,7 @@ public InputStream getInputStream() throws IOException { } } } - lastCheckedVersion.put(uri, document.getTextDocument().getVersion()); + lastCheckedVersion.put(uri, version); problemCache.put(uri, problems); } catch (Exception e) { // Do not add any info, like lastCheckedVersion or problems, to the cache @@ -205,6 +222,24 @@ public InputStream getInputStream() throws IOException { } } + private void parseAndCache(DOMDocument document) { + URI uri = URI.create(document.getDocumentURI()).normalize(); + int version = document.getTextDocument().getVersion(); + FileModelSource source = new FileModelSource(new File(uri)) { + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(document.getText().getBytes()); + } + }; + parseAndCache(uri, version, source); + } + + private void parseAndCache(File pomFile) { + URI uri = pomFile.toURI().normalize(); + FileModelSource source = new FileModelSource(pomFile); + parseAndCache(uri, 1, source); + } + private ProjectBuildingRequest newProjectBuildingRequest() { return newProjectBuildingRequest(true); }