/******************************************************************************* * Copyright (c) 2020 Microsoft Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * Microsoft Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.ls.core.internal.handlers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.File; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.google.common.io.Files; import org.apache.commons.io.FileUtils; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.manipulation.CoreASTProvider; import org.eclipse.jdt.ls.core.internal.JDTUtils; import org.eclipse.jdt.ls.core.internal.JavaClientConnection; import org.eclipse.jdt.ls.core.internal.ProjectUtils; import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; import org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences; import org.eclipse.lsp4j.DidChangeWatchedFilesParams; import org.eclipse.lsp4j.DidOpenTextDocumentParams; import org.eclipse.lsp4j.FileChangeType; import org.eclipse.lsp4j.FileEvent; import org.eclipse.lsp4j.PublishDiagnosticsParams; import org.eclipse.lsp4j.TextDocumentItem; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; public class WorkspaceEventHandlerTest extends AbstractProjectsManagerBasedTest { private CoreASTProvider sharedASTProvider; private DocumentLifeCycleHandler lifeCycleHandler; private JavaClientConnection javaClient; private WorkspaceDiagnosticsHandler handler; @Mock private ClientPreferences clientPreferences; @Before public void setup() throws Exception { sharedASTProvider = CoreASTProvider.getInstance(); sharedASTProvider.disposeAST(); javaClient = new JavaClientConnection(client); lifeCycleHandler = new DocumentLifeCycleHandler(javaClient, preferenceManager, projectsManager, false); handler = new WorkspaceDiagnosticsHandler(javaClient, projectsManager, preferenceManager.getClientPreferences()); handler.addResourceChangeListener(); } @After public void tearDown() throws Exception { javaClient.disconnect(); handler.removeResourceChangeListener(); for (ICompilationUnit cu : JavaCore.getWorkingCopies(null)) { cu.discardWorkingCopy(); } } @Test public void testDiscardStaleWorkingCopies() throws Exception { IJavaProject javaProject = newEmptyProject(); IFolder src = javaProject.getProject().getFolder("src"); IPackageFragmentRoot srcRoot = javaProject.getPackageFragmentRoot(src); IPackageFragment mypack = srcRoot.createPackageFragment("mypack", true, null); // @formatter:off String contents = "package mypack;\n" + "public class Foo {" + "}\n"; // @formatter:on ICompilationUnit unit = mypack.createCompilationUnit("Foo.java", contents, true, null); openDocument(unit, contents, 1); assertTrue(unit.isWorkingCopy()); String oldUri = JDTUtils.getFileURI(srcRoot.getResource()); String parentUri = JDTUtils.getFileURI(src); String newUri = oldUri.replace("mypack", "mynewpack"); File oldPack = mypack.getResource().getLocation().toFile(); File newPack = new File(oldPack.getParent(), "mynewpack"); Files.move(oldPack, newPack); assertTrue(unit.isWorkingCopy()); DidChangeWatchedFilesParams params = new DidChangeWatchedFilesParams(Arrays.asList( new FileEvent(newUri, FileChangeType.Created), new FileEvent(parentUri, FileChangeType.Changed), new FileEvent(oldUri, FileChangeType.Deleted) )); new WorkspaceEventsHandler(projectsManager, javaClient, lifeCycleHandler).didChangeWatchedFiles(params); assertFalse(unit.isWorkingCopy()); } @Test public void testDeleteProjectFolder() throws Exception { importProjects("maven/multimodule3"); IProject module2 = ProjectUtils.getProject("module2"); assertTrue(module2 != null && module2.exists()); String projectUri = JDTUtils.getFileURI(module2); FileUtils.deleteDirectory(module2.getLocation().toFile()); assertTrue(module2.exists()); clientRequests.clear(); DidChangeWatchedFilesParams params = new DidChangeWatchedFilesParams(Arrays.asList( new FileEvent(projectUri, FileChangeType.Deleted) )); new WorkspaceEventsHandler(projectsManager, javaClient, lifeCycleHandler).didChangeWatchedFiles(params); waitForBackgroundJobs(); assertFalse(module2.exists()); List<PublishDiagnosticsParams> diags = getClientRequests("publishDiagnostics"); assertEquals(9L, diags.size()); assertEndsWith(diags.get(0).getUri(), "/module2"); assertEndsWith(diags.get(1).getUri(), "/multimodule3"); assertEndsWith(diags.get(2).getUri(), "/multimodule3/pom.xml"); assertEndsWith(diags.get(3).getUri(), "/module2/pom.xml"); assertEquals(0L, diags.get(3).getDiagnostics().size()); assertEndsWith(diags.get(4).getUri(), "/module2"); assertEquals(0L, diags.get(4).getDiagnostics().size()); assertEndsWith(diags.get(5).getUri(), "/App.java"); assertEquals(0L, diags.get(5).getDiagnostics().size()); assertEndsWith(diags.get(6).getUri(), "/AppTest.java"); assertEquals(0L, diags.get(6).getDiagnostics().size()); assertEndsWith(diags.get(7).getUri(), "/multimodule3"); assertEndsWith(diags.get(8).getUri(), "/multimodule3/pom.xml"); } private void assertEndsWith(String target, String suffix) { if (target.endsWith("/")) { target = target.substring(0, target.length() - 1); } assertTrue(target.endsWith(suffix)); } private void openDocument(ICompilationUnit cu, String content, int version) { openDocument(JDTUtils.toURI(cu), content, version); } private void openDocument(String uri, String content, int version) { DidOpenTextDocumentParams openParms = new DidOpenTextDocumentParams(); TextDocumentItem textDocument = new TextDocumentItem(); textDocument.setLanguageId("java"); textDocument.setText(content); textDocument.setUri(uri); textDocument.setVersion(version); openParms.setTextDocument(textDocument); lifeCycleHandler.didOpen(openParms); } private <T> List<T> getClientRequests(String name) { List<?> requests = clientRequests.get(name); return requests != null ? (List<T>) requests : Collections.emptyList(); } }