diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandler.java index 30c2db7492..4b78e71342 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandler.java @@ -13,6 +13,7 @@ import static org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin.logError; import static org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin.logException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -40,12 +41,10 @@ public class BuildWorkspaceHandler { private JavaClientConnection connection; private final ProjectsManager projectsManager; - private final WorkspaceDiagnosticsHandler workspaceDiagnosticsHandler; - public BuildWorkspaceHandler(JavaClientConnection connection, ProjectsManager projectsManager, WorkspaceDiagnosticsHandler workspaceDiagnosticHandler) { + public BuildWorkspaceHandler(JavaClientConnection connection, ProjectsManager projectsManager) { this.connection = connection; this.projectsManager = projectsManager; - this.workspaceDiagnosticsHandler = workspaceDiagnosticHandler; } public BuildWorkspaceStatus buildWorkspace(boolean forceReBuild, IProgressMonitor monitor) { @@ -61,8 +60,17 @@ public BuildWorkspaceStatus buildWorkspace(boolean forceReBuild, IProgressMonito connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), Collections.emptyList())); } } + ResourcesPlugin.getWorkspace().build(forceReBuild ? IncrementalProjectBuilder.CLEAN_BUILD : IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor); ResourcesPlugin.getWorkspace().build(forceReBuild ? IncrementalProjectBuilder.FULL_BUILD : IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor); - List problemMarkers = workspaceDiagnosticsHandler.publishDiagnostics(monitor); + List problemMarkers = new ArrayList<>(); + for (IProject project : projects) { + if (!project.equals(projectsManager.getDefaultProject())) { + List markers = ResourceUtils.getErrorMarkers(project); + if (markers != null) { + problemMarkers.addAll(markers); + } + } + } List errors = problemMarkers.stream().filter(m -> m.getAttribute(IMarker.SEVERITY, 0) == IMarker.SEVERITY_ERROR).map(e -> convertMarker(e)).collect(Collectors.toList()); if (errors.isEmpty()) { return BuildWorkspaceStatus.SUCCEED; diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java index 0d5bf7f1df..95afe2c0a8 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java @@ -215,15 +215,6 @@ public void initialized(InitializedParams params) { workspaceDiagnosticsHandler = new WorkspaceDiagnosticsHandler(this.client, pm); workspaceDiagnosticsHandler.addResourceChangeListener(); - - computeAsync((monitor) -> { - try { - workspaceDiagnosticsHandler.publishDiagnostics(monitor); - } catch (CoreException e) { - logException(e.getMessage(), e); - } - return new Object(); - }); } /** @@ -710,7 +701,7 @@ public void projectConfigurationUpdate(TextDocumentIdentifier param) { @Override public CompletableFuture buildWorkspace(boolean forceReBuild) { logInfo(">> java/buildWorkspace (" + (forceReBuild ? "full)" : "incremental)")); - BuildWorkspaceHandler handler = new BuildWorkspaceHandler(client, pm, workspaceDiagnosticsHandler); + BuildWorkspaceHandler handler = new BuildWorkspaceHandler(client, pm); return computeAsync((monitor) -> handler.buildWorkspace(forceReBuild, monitor)); } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java index 2e576c8e28..09d4c1b88b 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -29,12 +28,9 @@ import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.ls.core.internal.JDTUtils; import org.eclipse.jdt.ls.core.internal.JavaClientConnection; import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; @@ -121,10 +117,6 @@ public boolean visit(IResourceDelta delta) throws CoreException { String uri = JDTUtils.getFileURI(project); IFile pom = project.getFile("pom.xml"); List pomMarkers = new ArrayList<>(); - if (pom.exists()) { - pomMarkers.addAll(Arrays.asList(pom.findMarkers(null, true, 1))); - } - for (IMarker marker : markers) { if (!marker.exists() || CheckMissingNaturesListener.MARKER_TYPE.equals(marker.getType())) { continue; @@ -135,11 +127,11 @@ public boolean visit(IResourceDelta delta) throws CoreException { projectMarkers.add(marker); } } - List diagnostics = toDiagnosticArray(range, projectMarkers); String clientUri = ResourceUtils.toClientUri(uri); connection.publishDiagnostics(new PublishDiagnosticsParams(clientUri, diagnostics)); if (pom.exists()) { + pomMarkers.addAll(Arrays.asList(pom.findMarkers(null, true, 1))); diagnostics = toDiagnosticArray(range, pomMarkers); connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(clientUri + "/pom.xml"), diagnostics)); } @@ -150,7 +142,6 @@ public boolean visit(IResourceDelta delta) throws CoreException { return false; } IFile file = (IFile) resource; - String uri = JDTUtils.getFileURI(resource); IDocument document = null; IMarker[] markers = null; // Check if it is a Java ... @@ -168,71 +159,12 @@ else if (projectsManager.isBuildFile(file)) { document = JsonRpcHelpers.toDocument(file); } if (document != null) { + String uri = JDTUtils.getFileURI(resource); this.connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), toDiagnosticsArray(document, markers))); } return false; } - public List publishDiagnostics(IProgressMonitor monitor) throws CoreException { - List problemMarkers = getProblemMarkers(monitor); - publishDiagnostics(problemMarkers); - return problemMarkers; - } - - private List getProblemMarkers(IProgressMonitor monitor) throws CoreException { - IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); - List markers = new ArrayList<>(); - for (IProject project : projects) { - if (monitor != null && monitor.isCanceled()) { - throw new OperationCanceledException(); - } - markers.addAll(Arrays.asList(project.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE))); - markers.addAll(Arrays.asList(project.findMarkers(IJavaModelMarker.TASK_MARKER, true, IResource.DEPTH_INFINITE))); - } - return markers; - } - - private void publishDiagnostics(List markers) { - Map> map = markers.stream().collect(Collectors.groupingBy(IMarker::getResource)); - for (Map.Entry> entry : map.entrySet()) { - IResource resource = entry.getKey(); - // ignore problems caused by standalone files - if (JavaLanguageServerPlugin.getProjectsManager().getDefaultProject().equals(resource.getProject())) { - continue; - } - if (resource instanceof IProject) { - String uri = JDTUtils.getFileURI(resource); - Range range = new Range(new Position(0, 0), new Position(0, 0)); - List diagnostics = WorkspaceDiagnosticsHandler.toDiagnosticArray(range, entry.getValue()); - connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), diagnostics)); - continue; - } - IFile file = resource.getAdapter(IFile.class); - if (file == null) { - continue; - } - IDocument document = null; - String uri = JDTUtils.getFileURI(resource); - if (JavaCore.isJavaLikeFileName(file.getName())) { - ICompilationUnit cu = JDTUtils.resolveCompilationUnit(uri); - try { - document = JsonRpcHelpers.toDocument(cu.getBuffer()); - } catch (JavaModelException e) { - JavaLanguageServerPlugin.logException("Failed to publish diagnostics.", e); - } - } else if (projectsManager.isBuildFile(file)) { - document = JsonRpcHelpers.toDocument(file); - } - - if (document != null) { - List diagnostics = WorkspaceDiagnosticsHandler.toDiagnosticsArray(document, entry.getValue().toArray(new IMarker[0])); - connection.publishDiagnostics(new PublishDiagnosticsParams(ResourceUtils.toClientUri(uri), diagnostics)); - } - } - } - - - /** * Transforms {@link IMarker}s into a list of {@link Diagnostic}s * diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandlerTest.java index 37428f6b69..b0490126bf 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/BuildWorkspaceHandlerTest.java @@ -19,6 +19,8 @@ import java.nio.charset.StandardCharsets; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jdt.ls.core.internal.BuildWorkspaceStatus; import org.eclipse.jdt.ls.core.internal.JavaClientConnection; import org.eclipse.jdt.ls.core.internal.JavaClientConnection.JavaLanguageClient; @@ -31,34 +33,35 @@ public class BuildWorkspaceHandlerTest extends AbstractProjectsManagerBasedTest private JavaClientConnection javaClient = new JavaClientConnection(client); private BuildWorkspaceHandler handler; - private IFile file; + private IProject project; @Before public void setUp() throws Exception { - handler = new BuildWorkspaceHandler(javaClient, projectsManager, new WorkspaceDiagnosticsHandler(javaClient, projectsManager)); + handler = new BuildWorkspaceHandler(javaClient, projectsManager); importProjects("maven/salut2"); - file = linkFilesToDefaultProject("singlefile/Single.java"); + project = ResourcesPlugin.getWorkspace().getRoot().getProject("salut2"); } @Test public void testSucceedCase() throws Exception { BuildWorkspaceStatus result = handler.buildWorkspace(false, monitor); - waitForBackgroundJobs(); assertTrue(String.format("BuildWorkspaceStatus is: %s.", result.toString()), result == BuildWorkspaceStatus.SUCCEED); } @Test public void testFailedCase() throws Exception { - String codeWithError = "public class Single2 {\n" + + //@formatter:off + String codeWithError = "package foo;\n" + + " public class Single2 {\n" + " public static void main(String[] args){\n"+ " int ss = 1;;\n"+ " }\n"+ "}"; + //@formatter:on + IFile file = project.getFile("src/main/java/foo/Bar.java"); try (InputStream stream = new ByteArrayInputStream(codeWithError.getBytes(StandardCharsets.UTF_8))) { file.setContents(stream, true, false, monitor); - waitForBackgroundJobs(); BuildWorkspaceStatus result = handler.buildWorkspace(false, monitor); - waitForBackgroundJobs(); assertEquals(result, BuildWorkspaceStatus.WITH_ERROR); } } @@ -67,7 +70,6 @@ public void testFailedCase() throws Exception { public void testCanceledCase() throws Exception { monitor.setCanceled(true); BuildWorkspaceStatus result = handler.buildWorkspace(false, monitor); - waitForBackgroundJobs(); assertEquals(result, BuildWorkspaceStatus.CANCELLED); } } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java index 0ffc235268..e7ade5a47d 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandlerTest.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -30,6 +31,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.ls.core.internal.JavaClientConnection; import org.eclipse.jdt.ls.core.internal.ResourceUtils; import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; @@ -82,7 +84,7 @@ public void testToDiagnosticsArray() throws Exception { when(d.getLineOffset(9)).thenReturn(1000); when(d.getLineOffset(99)).thenReturn(10000); - List diags = handler.toDiagnosticsArray(d, new IMarker[]{m1, m2, m3}); + List diags = WorkspaceDiagnosticsHandler.toDiagnosticsArray(d, new IMarker[]{m1, m2, m3}); assertEquals(3, diags.size()); Range r; @@ -166,7 +168,7 @@ public void testMavenMarkers() throws Exception { IDocument d = mock(IDocument.class); when(d.getLineOffset(1)).thenReturn(90); - List diags = handler.toDiagnosticsArray(d, new IMarker[]{m1, null}); + List diags = WorkspaceDiagnosticsHandler.toDiagnosticsArray(d, new IMarker[]{m1, null}); assertEquals(1, diags.size()); Range r; @@ -291,6 +293,64 @@ public void testProjectConfigurationIsNotUpToDate() throws Exception { assertEquals(diag.getSeverity(), DiagnosticSeverity.Warning); } + @Test + public void testMissingDependencies() throws Exception { + importProjects("maven/salut"); + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("salut"); + IFile pom = project.getFile("/pom.xml"); + assertTrue(pom.exists()); + ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.CLEAN_BUILD, monitor); + assertNoErrors(project); + // edit pom.xml + ResourceUtils.setContent(pom, ResourceUtils.getContent(pom).replaceAll("3.5", "3.5xx")); + waitForBackgroundJobs(); + ArgumentCaptor captor = ArgumentCaptor.forClass(PublishDiagnosticsParams.class); + verify(connection, atLeastOnce()).publishDiagnostics(captor.capture()); + List allCalls = captor.getAllValues(); + Collections.reverse(allCalls); + projectsManager.setConnection(client); + testDiagnostic(allCalls); + // update project + reset(connection); + captor = ArgumentCaptor.forClass(PublishDiagnosticsParams.class); + projectsManager.updateProject(project, true); + waitForBackgroundJobs(); + verify(connection, atLeastOnce()).publishDiagnostics(captor.capture()); + allCalls = captor.getAllValues(); + Collections.reverse(allCalls); + testDiagnostic(allCalls); + // build workspace + reset(connection); + captor = ArgumentCaptor.forClass(PublishDiagnosticsParams.class); + BuildWorkspaceHandler bwh = new BuildWorkspaceHandler(connection, projectsManager); + bwh.buildWorkspace(true, new NullProgressMonitor()); + verify(connection, atLeastOnce()).publishDiagnostics(captor.capture()); + allCalls = captor.getAllValues(); + Collections.reverse(allCalls); + testDiagnostic(allCalls); + } + + private void testDiagnostic(List allCalls) { + List projectDiags = new ArrayList<>(); + List pomDiags = new ArrayList<>(); + for (PublishDiagnosticsParams diag : allCalls) { + if (diag.getUri().endsWith("maven/salut")) { + projectDiags.addAll(diag.getDiagnostics()); + } else if (diag.getUri().endsWith("pom.xml")) { + pomDiags.addAll(diag.getDiagnostics()); + } + } + assertTrue("No maven/salut errors were found", projectDiags.size() > 0); + Optional projectDiag = projectDiags.stream().filter(p -> p.getMessage().startsWith("Missing artifact")).findFirst(); + assertTrue("No missing artifact diagnostic", projectDiag.isPresent()); + assertEquals(projectDiag.get().getSeverity(), DiagnosticSeverity.Error); + assertTrue("No pom.xml errors were found", pomDiags.size() > 0); + Optional pomDiag = pomDiags.stream().filter(p -> p.getMessage().startsWith("Missing artifact")).findFirst(); + assertTrue("No missing artifact diagnostic", pomDiag.isPresent()); + assertTrue(pomDiag.get().getMessage().startsWith("Missing artifact")); + assertEquals(pomDiag.get().getSeverity(), DiagnosticSeverity.Error); + } + @Test public void testResetPomDiagnostics() throws Exception { //import project diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java index c32ebf414b..6ae227c3d4 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManagerTest.java @@ -26,7 +26,6 @@ import org.eclipse.jdt.ls.core.internal.JavaClientConnection.JavaLanguageClient; import org.eclipse.jdt.ls.core.internal.WorkspaceHelper; import org.eclipse.jdt.ls.core.internal.handlers.BuildWorkspaceHandler; -import org.eclipse.jdt.ls.core.internal.handlers.WorkspaceDiagnosticsHandler; import org.junit.Test; /** @@ -58,7 +57,7 @@ public void testCleanupDefaultProject() throws Exception { java.io.File physicalFile = new java.io.File(file.getLocationURI()); physicalFile.delete(); - BuildWorkspaceHandler handler = new BuildWorkspaceHandler(javaClient, projectsManager, new WorkspaceDiagnosticsHandler(javaClient, projectsManager)); + BuildWorkspaceHandler handler = new BuildWorkspaceHandler(javaClient, projectsManager); BuildWorkspaceStatus result = handler.buildWorkspace(true, monitor); waitForBackgroundJobs();