diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/DocumentAdapter.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/DocumentAdapter.java index 68dfbaba2c..787f13dbe5 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/DocumentAdapter.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/DocumentAdapter.java @@ -274,7 +274,9 @@ public void setContents(String contents) { ((ISynchronizable)fDocument).setLockObject(lock); } } - fDocument.set(contents); + if (!contents.equals(fDocument.get())) { + fDocument.set(contents); + } } @Override diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTUtils.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTUtils.java index 69c26cafa8..258a11a75c 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTUtils.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTUtils.java @@ -11,6 +11,7 @@ package org.eclipse.jdt.ls.core.internal; import java.io.File; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Paths; @@ -186,7 +187,7 @@ public static String getPackageName(IJavaProject javaProject, URI uri) { //FIXME need to determine actual charset from file String content = Files.toString(file, Charsets.UTF_8); return getPackageName(javaProject, content); - } catch (Exception e) { + } catch (IOException e) { JavaLanguageServerPlugin.logException("Failed to read package name from "+uri, e); } return ""; diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerWorkingCopyOwner.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerWorkingCopyOwner.java index fbe69a229c..760619a598 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerWorkingCopyOwner.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerWorkingCopyOwner.java @@ -48,10 +48,7 @@ public IBuffer createBuffer(ICompilationUnit workingCopy) { * @see org.eclipse.jdt.core.WorkingCopyOwner#getProblemRequestor(org.eclipse.jdt.core.ICompilationUnit) */ @Override - public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) { - final IResource resource = workingCopy.getPrimary().getResource(); - return new DiagnosticsHandler(connection, - resource, - resource.getProject().equals(JavaLanguageServerPlugin.getProjectsManager().getDefaultProject())); + public IProblemRequestor getProblemRequestor(ICompilationUnit cu) { + return new DiagnosticsHandler(connection, cu); } } \ No newline at end of file diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/SharedASTProvider.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/SharedASTProvider.java index 80ae4170d1..9e367cc996 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/SharedASTProvider.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/SharedASTProvider.java @@ -10,6 +10,10 @@ *******************************************************************************/ package org.eclipse.jdt.ls.core.internal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -21,28 +25,31 @@ import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.ITypeRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; +import org.eclipse.jdt.core.dom.ASTRequestor; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.internal.corext.dom.IASTSharedValues; /** - * AST provider that caches the AST generated for - * files that are known to be open. - * - * @author Gorkem Ercan - * + * AST provider that caches the AST generated for files that are known to be + * open. */ @SuppressWarnings("restriction") public final class SharedASTProvider { - private ConcurrentMap cache = new ConcurrentHashMap<>(); private static SharedASTProvider instance = new SharedASTProvider(); - private SharedASTProvider(){ + private ConcurrentMap cache = new ConcurrentHashMap<>(); + private int astCreationCount; // to testing purposes + + + private SharedASTProvider() { + astCreationCount = 0; } public void dispose() { @@ -65,10 +72,61 @@ public CompilationUnit getAST(final ITypeRoot input, IProgressMonitor progressMo final String identifier = input.getHandleIdentifier(); return cache.computeIfAbsent(identifier, k -> { JavaLanguageServerPlugin.logInfo("Caching AST for " + input.getPath().toString()); - return createAST(input, progressMonitor); + CompilationUnit astRoot = createAST(input, progressMonitor); + astCreationCount++; + return astRoot; }); } + public List getASTs(List inputs, IProgressMonitor progressMonitor) { + if (progressMonitor != null && progressMonitor.isCanceled() || inputs.isEmpty()) { + return Collections.emptyList(); + } + HashMap> cuByProject = new HashMap<>(); + List result = new ArrayList<>(); + + for (ICompilationUnit input : inputs) { + final String identifier = input.getHandleIdentifier(); + CompilationUnit cu = cache.get(identifier); + if (cu != null) { + result.add(cu); + } else { + IJavaProject project = input.getJavaProject(); + List list = cuByProject.get(project); + if (list == null) { + list = new ArrayList<>(); + cuByProject.put(project, list); + } + list.add(input); + } + } + + for (IJavaProject project: cuByProject.keySet()) { + final ASTParser parser = newASTParser(); + parser.setProject(project); + + List cus = cuByProject.get(project); + + ASTRequestor requestor = new ASTRequestor() { + @Override + public void acceptAST(ICompilationUnit cu, CompilationUnit astRoot) { + result.add(astRoot); + setAST(astRoot); + } + }; + parser.createASTs(cus.toArray(new ICompilationUnit[cus.size()]), new String[0], requestor, progressMonitor); + astCreationCount += cus.size(); + } + return result; + } + + public void setAST(CompilationUnit astRoot) { + ITypeRoot typeRoot = astRoot.getTypeRoot(); + if (shouldCache(typeRoot)) { + cache.put(typeRoot.getHandleIdentifier(), astRoot); + } + } + /** * Only cache ASTs for compilation units in working copy mode (open in a * buffer) @@ -111,16 +169,9 @@ private static CompilationUnit createAST(final ITypeRoot input, final IProgressM return null; } - final ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); - parser.setResolveBindings(true); - parser.setStatementsRecovery(IASTSharedValues.SHARED_AST_STATEMENT_RECOVERY); - parser.setBindingsRecovery(IASTSharedValues.SHARED_BINDING_RECOVERY); + final ASTParser parser = newASTParser(); parser.setSource(input); - if (progressMonitor != null && progressMonitor.isCanceled()) { - return null; - } - final CompilationUnit root[]= new CompilationUnit[1]; SafeRunner.run(new ISafeRunnable() { @@ -130,7 +181,7 @@ public void run() { if (progressMonitor != null && progressMonitor.isCanceled()) { return; } - root[0]= (CompilationUnit)parser.createAST(progressMonitor); + root[0] = (CompilationUnit) parser.createAST(progressMonitor); //mark as unmodifiable ASTNodes.setFlagsToAST(root[0], ASTNode.PROTECT); @@ -147,6 +198,14 @@ public void handleException(Throwable ex) { return root[0]; } + public static ASTParser newASTParser() { + final ASTParser parser = ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL); + parser.setResolveBindings(true); + parser.setStatementsRecovery(IASTSharedValues.SHARED_AST_STATEMENT_RECOVERY); + parser.setBindingsRecovery(IASTSharedValues.SHARED_BINDING_RECOVERY); + return parser; + } + /** * Checks whether the given Java element has accessible source. * @@ -167,5 +226,31 @@ private static boolean hasSource(ITypeRoot je) { return false; } + /** + * For testing purposes + * + * @return the number of elements currently in the cache + */ + public int getCacheSize() { + return cache.size(); + } + + /** + * For testing purposes + * + * @return the number of ASTs created + */ + public int getASTCreationCount() { + return astCreationCount; + } + + /** + * For testing purposes + * + * Sets the counter for ASTs created to 0 + */ + public void clearASTCreationCount() { + astCreationCount = 0; + } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java index 9f6b4152e0..ce21b91243 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DiagnosticsHandler.java @@ -15,7 +15,7 @@ import java.util.ArrayList; import java.util.List; -import org.eclipse.core.resources.IResource; +import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IProblemRequestor; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.problem.DefaultProblem; @@ -31,15 +31,15 @@ public class DiagnosticsHandler implements IProblemRequestor { private final List problems; - private final IResource resource; + private final String uri; private final JavaClientConnection connection; private boolean reportAllErrors = true; - public DiagnosticsHandler(JavaClientConnection conn, IResource resource, boolean reportOnlySyntaxErrors) { + public DiagnosticsHandler(JavaClientConnection conn, ICompilationUnit cu) { problems = new ArrayList<>(); - this.resource = resource; + this.uri = JDTUtils.getFileURI(cu); this.connection = conn; - this.reportAllErrors = !reportOnlySyntaxErrors; + this.reportAllErrors = !cu.getJavaProject().getProject().equals(JavaLanguageServerPlugin.getProjectsManager().getDefaultProject()); } @Override @@ -98,14 +98,13 @@ private String getError(IProblem problem) { @Override public void beginReporting() { - JavaLanguageServerPlugin.logInfo("begin problem for " + this.resource.getName()); + JavaLanguageServerPlugin.logInfo("begin problem for " + this.uri.substring(this.uri.lastIndexOf('/'))); problems.clear(); } @Override public void endReporting() { - JavaLanguageServerPlugin.logInfo("end reporting for "+ this.resource.getName()); - String uri = JDTUtils.getFileURI(this.resource); + JavaLanguageServerPlugin.logInfo(problems.size() + " problems reported for " + this.uri.substring(this.uri.lastIndexOf('/'))); PublishDiagnosticsParams $ = new PublishDiagnosticsParams(uri, toDiagnosticsArray(problems)); this.connection.publishDiagnostics($); } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandler.java index ea33a3bd8b..98c7c33ac0 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandler.java @@ -10,20 +10,32 @@ *******************************************************************************/ package org.eclipse.jdt.ls.core.internal.handlers; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import org.eclipse.core.filebuffers.FileBuffers; +import org.eclipse.core.filebuffers.IFileBuffer; +import org.eclipse.core.filebuffers.LocationKind; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jdt.core.IBuffer; import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.core.WorkingCopyOwner; +import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.ls.core.internal.ActionableNotification; import org.eclipse.jdt.ls.core.internal.JDTUtils; import org.eclipse.jdt.ls.core.internal.JavaClientConnection; @@ -54,8 +66,75 @@ public class DocumentLifeCycleHandler { private JavaClientConnection connection; private PreferenceManager preferenceManager; private ProjectsManager projectsManager; - private WorkingCopyOwner wcOwner; + private SharedASTProvider sharedASTProvider; + private WorkspaceJob validationTimer; + + private Set toReconcile = new HashSet<>(); + + public DocumentLifeCycleHandler(JavaClientConnection connection, PreferenceManager preferenceManager, ProjectsManager projectsManager, boolean delayValidation) { + this.connection = connection; + this.preferenceManager = preferenceManager; + this.projectsManager = projectsManager; + this.sharedASTProvider = SharedASTProvider.getInstance(); + if (delayValidation) { + this.validationTimer = new WorkspaceJob("Validate documents") { + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + return performValidation(monitor); + } + }; + this.validationTimer.setRule(ResourcesPlugin.getWorkspace().getRoot()); + } + } + + private void triggerValidation(ICompilationUnit cu) throws JavaModelException { + synchronized (toReconcile) { + toReconcile.add(cu); + } + if (validationTimer != null) { + validationTimer.cancel(); + validationTimer.schedule(400); + } else { + performValidation(new NullProgressMonitor()); + } + + } + + private IStatus performValidation(IProgressMonitor monitor) throws JavaModelException { + long start = System.currentTimeMillis(); + + List cusToReconcile = new ArrayList<>(); + synchronized (toReconcile) { + cusToReconcile.addAll(toReconcile); + toReconcile.clear(); + } + if (cusToReconcile.isEmpty()) { + return Status.OK_STATUS; + } + + // first reconcile all units with content changes + SubMonitor progress = SubMonitor.convert(monitor, cusToReconcile.size() + 1); + for (ICompilationUnit cu : cusToReconcile) { + cu.reconcile(ICompilationUnit.NO_AST, true, null, progress.newChild(1)); + } + this.sharedASTProvider.invalidateAll(); + + List toValidate = Arrays.asList(JavaCore.getWorkingCopies(null)); + List astRoots = this.sharedASTProvider.getASTs(toValidate, monitor); + for (CompilationUnit astRoot : astRoots) { + // report errors, even if there are no problems in the file: The client need to know that they got fixed. + DiagnosticsHandler handler = new DiagnosticsHandler(connection, (ICompilationUnit) astRoot.getTypeRoot()); + handler.beginReporting(); + + for (IProblem problem : astRoot.getProblems()) { + handler.acceptProblem(problem); + } + handler.endReporting(); + } + JavaLanguageServerPlugin.logInfo("Reconciled " + toReconcile.size() + ", validated: " + toValidate.size() + ". Took " + (System.currentTimeMillis() - start) + " ms"); + return Status.OK_STATUS; + } public void didClose(DidCloseTextDocumentParams params) { try { @@ -109,13 +188,6 @@ public void run(IProgressMonitor monitor) throws CoreException { } } - public DocumentLifeCycleHandler(JavaClientConnection connection, PreferenceManager preferenceManager, ProjectsManager projectsManager, WorkingCopyOwner wcOwner) { - this.connection = connection; - this.preferenceManager = preferenceManager; - this.projectsManager = projectsManager; - this.wcOwner = wcOwner; - } - public void handleOpen(DidOpenTextDocumentParams params) { String uri = params.getTextDocument().getUri(); ICompilationUnit unit = JDTUtils.resolveCompilationUnit(uri); @@ -154,26 +226,25 @@ public void handleOpen(DidOpenTextDocumentParams params) { // DiagnosticsHandler problemRequestor = new DiagnosticsHandler(connection, unit.getResource(), reportOnlySyntaxErrors); unit.becomeWorkingCopy(new NullProgressMonitor()); IBuffer buffer = unit.getBuffer(); - if(buffer != null) { - buffer.setContents(params.getTextDocument().getText()); + String newContent = params.getTextDocument().getText(); + if (buffer != null && !buffer.getContents().equals(newContent)) { + buffer.setContents(newContent); } - - // TODO: wire up cancellation. - unit.reconcile(ICompilationUnit.NO_AST, true/*don't force problem detection*/, false, wcOwner, null/*no progress monitor*/); + triggerValidation(unit); } catch (JavaModelException e) { - JavaLanguageServerPlugin.logException("Creating working copy ",e); + JavaLanguageServerPlugin.logException("Error while opening document", e); } } public void handleChanged(DidChangeTextDocumentParams params) { ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri()); - if (unit == null || !unit.isWorkingCopy()) { + if (unit == null || !unit.isWorkingCopy() || params.getContentChanges().isEmpty()) { return; } try { - SharedASTProvider.getInstance().invalidate(unit); + sharedASTProvider.invalidate(unit); List contentChanges = params.getContentChanges(); for (TextDocumentContentChangeEvent changeEvent : contentChanges) { @@ -193,30 +264,33 @@ public void handleChanged(DidChangeTextDocumentParams params) { IDocument document = JsonRpcHelpers.toDocument(unit.getBuffer()); edit.apply(document, TextEdit.NONE); } - unit.reconcile(ICompilationUnit.NO_AST, true, false, wcOwner, null); + triggerValidation(unit); } catch (JavaModelException | MalformedTreeException | BadLocationException e) { - JavaLanguageServerPlugin.logException("Failed to apply changes",e); + JavaLanguageServerPlugin.logException("Error while handling document change", e); } } public void handleClosed(DidCloseTextDocumentParams params) { - JavaLanguageServerPlugin.logInfo("DocumentLifeCycleHandler.handleClosed"); String uri = params.getTextDocument().getUri(); ICompilationUnit unit = JDTUtils.resolveCompilationUnit(uri); if (unit == null) { return; } try { - SharedASTProvider.getInstance().invalidate(unit); + sharedASTProvider.invalidate(unit); unit.discardWorkingCopy(); } catch (CoreException e) { + JavaLanguageServerPlugin.logException("Error while handling document close", e); } } public void handleSaved(DidSaveTextDocumentParams params) { - JavaLanguageServerPlugin.logInfo("DocumentLifeCycleHandler.handleSaved"); String uri = params.getTextDocument().getUri(); ICompilationUnit unit = JDTUtils.resolveCompilationUnit(uri); + IFileBuffer fileBuffer = FileBuffers.getTextFileBufferManager().getFileBuffer(unit.getPath(), LocationKind.IFILE); + if (fileBuffer != null) { + fileBuffer.setDirty(false); + } if (unit != null && unit.isWorkingCopy()) { projectsManager.fileChanged(uri, CHANGE_TYPE.CHANGED); } 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 96f9d3154d..123bbaddcb 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 @@ -81,11 +81,12 @@ public class JDTLanguageServer implements LanguageServer, TextDocumentService, W private ProjectsManager pm; private LanguageServerWorkingCopyOwner workingCopyOwner; private PreferenceManager preferenceManager; + private DocumentLifeCycleHandler documentLifeCycleHandler; public LanguageServerWorkingCopyOwner getWorkingCopyOwner() { return workingCopyOwner; } - + public JDTLanguageServer(ProjectsManager projects, PreferenceManager preferenceManager) { this.pm = projects; this.preferenceManager = preferenceManager; @@ -96,6 +97,7 @@ public void connectClient(JavaLanguageClient client) { this.workingCopyOwner = new LanguageServerWorkingCopyOwner(this.client); pm.setConnection(client); WorkingCopyOwner.setPrimaryBufferProvider(this.workingCopyOwner); + this.documentLifeCycleHandler = new DocumentLifeCycleHandler(this.client, preferenceManager, pm, true); } /* (non-Javadoc) @@ -345,8 +347,7 @@ public CompletableFuture rename(RenameParams params) { @Override public void didOpen(DidOpenTextDocumentParams params) { logInfo(">> document/didOpen"); - DocumentLifeCycleHandler handler = new DocumentLifeCycleHandler(client, preferenceManager, pm, workingCopyOwner); - handler.didOpen(params); + documentLifeCycleHandler.didOpen(params); } /* (non-Javadoc) @@ -355,8 +356,7 @@ public void didOpen(DidOpenTextDocumentParams params) { @Override public void didChange(DidChangeTextDocumentParams params) { logInfo(">> document/didChange"); - DocumentLifeCycleHandler handler = new DocumentLifeCycleHandler(client, preferenceManager, pm, workingCopyOwner); - handler.didChange(params); + documentLifeCycleHandler.didChange(params); } /* (non-Javadoc) @@ -365,8 +365,7 @@ public void didChange(DidChangeTextDocumentParams params) { @Override public void didClose(DidCloseTextDocumentParams params) { logInfo(">> document/didClose"); - DocumentLifeCycleHandler handler = new DocumentLifeCycleHandler(client, preferenceManager, pm, workingCopyOwner); - handler.didClose(params); + documentLifeCycleHandler.didClose(params); } /* (non-Javadoc) @@ -375,8 +374,7 @@ public void didClose(DidCloseTextDocumentParams params) { @Override public void didSave(DidSaveTextDocumentParams params) { logInfo(">> document/didSave"); - DocumentLifeCycleHandler handler = new DocumentLifeCycleHandler(client, preferenceManager, pm, workingCopyOwner); - handler.didSave(params); + documentLifeCycleHandler.didSave(params); } /* (non-Javadoc) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java index 9c68bb077c..8373b6c5a8 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/managers/ProjectsManager.java @@ -66,7 +66,7 @@ public ProjectsManager(PreferenceManager preferenceManager) { public IStatus initializeProjects(final String projectPath, IProgressMonitor monitor) { SubMonitor subMonitor = SubMonitor.convert(monitor, 100); try { - createJavaProject(subMonitor.split(10)); + createJavaProject(getDefaultProject(), subMonitor.split(10)); if (projectPath != null) { File userProjectRoot = new File(projectPath); @@ -158,8 +158,7 @@ private Collection importers() { return Arrays.asList(new GradleProjectImporter(), new MavenProjectImporter(), new EclipseProjectImporter()); } - private IProject createJavaProject(IProgressMonitor monitor) throws CoreException, OperationCanceledException, InterruptedException { - IProject project = getDefaultProject(); + public IProject createJavaProject(IProject project, IProgressMonitor monitor) throws CoreException, OperationCanceledException, InterruptedException { if (project.exists()) { return project; } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandlerTest.java new file mode 100644 index 0000000000..1ffdc8143f --- /dev/null +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifeCycleHandlerTest.java @@ -0,0 +1,440 @@ +/******************************************************************************* + * Copyright (c) 2017 Red Hat Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.ls.core.internal.handlers; + +import static org.eclipse.jdt.ls.core.internal.Lsp4jAssertions.assertRange; +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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.JavaModelException; +import org.eclipse.jdt.ls.core.internal.JDTUtils; +import org.eclipse.jdt.ls.core.internal.JavaClientConnection; +import org.eclipse.jdt.ls.core.internal.JavaClientConnection.JavaLanguageClient; +import org.eclipse.jdt.ls.core.internal.SharedASTProvider; +import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; +import org.eclipse.jdt.ls.core.internal.preferences.Preferences; +import org.eclipse.jdt.ls.core.internal.preferences.Preferences.Severity; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DidChangeTextDocumentParams; +import org.eclipse.lsp4j.DidCloseTextDocumentParams; +import org.eclipse.lsp4j.DidOpenTextDocumentParams; +import org.eclipse.lsp4j.DidSaveTextDocumentParams; +import org.eclipse.lsp4j.PublishDiagnosticsParams; +import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.TextDocumentContentChangeEvent; +import org.eclipse.lsp4j.TextDocumentIdentifier; +import org.eclipse.lsp4j.TextDocumentItem; +import org.eclipse.lsp4j.VersionedTextDocumentIdentifier; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class DocumentLifeCycleHandlerTest extends AbstractProjectsManagerBasedTest { + + private SharedASTProvider sharedASTProvider; + private Map> clientRequests = new HashMap<>(); + private JavaLanguageClient client=(JavaLanguageClient)Proxy.newProxyInstance(getClass().getClassLoader(),new Class[]{JavaLanguageClient.class},new InvocationHandler(){ + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (args.length == 1) { + String name = method.getName(); + List params = clientRequests.get(name); + if (params == null) { + params = new ArrayList<>(); + clientRequests.put(name, params); + } + params.add(args[0]); + } + return null; + } + }); + + private DocumentLifeCycleHandler lifeCycleHandler; + + @Before + public void setup() throws Exception { + mockPreferences(); + clientRequests.clear(); + + sharedASTProvider = SharedASTProvider.getInstance(); + sharedASTProvider.invalidateAll(); + sharedASTProvider.clearASTCreationCount(); + + lifeCycleHandler = new DocumentLifeCycleHandler(new JavaClientConnection(client), preferenceManager, projectsManager, false); + } + + @After + public void tearDown() throws Exception { + for (ICompilationUnit cu : JavaCore.getWorkingCopies(null)) { + cu.discardWorkingCopy(); + } + } + + private Preferences mockPreferences() { + Preferences mockPreferences = Mockito.mock(Preferences.class); + Mockito.when(preferenceManager.getPreferences()).thenReturn(mockPreferences); + Mockito.when(preferenceManager.getPreferences(Mockito.any())).thenReturn(mockPreferences); + Mockito.when(mockPreferences.getIncompleteClasspathSeverity()).thenReturn(Severity.ignore); + return mockPreferences; + } + + @Test + public void testBasicBufferLifeCycle() throws Exception { + IJavaProject javaProject = newEmptyProject(); + IPackageFragmentRoot sourceFolder = javaProject.getPackageFragmentRoot(javaProject.getProject().getFolder("src")); + IPackageFragment pack1 = sourceFolder.createPackageFragment("test1", false, null); + + StringBuilder buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("public class E123 {\n"); + buf.append("}\n"); + ICompilationUnit cu1 = pack1.createCompilationUnit("E123.java", buf.toString(), false, null); + + assertEquals(false, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertNewProblemReported(); + assertEquals(0, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(0); + + openDocument(cu1, cu1.getSource(), 1); + + assertEquals(true, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertNewProblemReported(new ExpectedProblemReport(cu1, 0)); + assertEquals(1, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(1); + + buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("public class E123 {\n"); + buf.append(" X x;\n"); + buf.append("}\n"); + + changeDocument(cu1, buf.toString(), 2); + + assertEquals(true, cu1.isWorkingCopy()); + assertEquals(true, cu1.hasUnsavedChanges()); + assertNewProblemReported(new ExpectedProblemReport(cu1, 1)); + assertEquals(1, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(1); + + saveDocument(cu1); + + assertEquals(true, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertNewProblemReported(); + assertEquals(1, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(0); + + closeDocument(cu1); + + assertEquals(false, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertNewProblemReported(); + assertEquals(0, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(0); + } + + @Test + public void testFixInDependencyScenario() throws Exception { + IJavaProject javaProject = newEmptyProject(); + IPackageFragmentRoot sourceFolder = javaProject.getPackageFragmentRoot(javaProject.getProject().getFolder("src")); + IPackageFragment pack1 = sourceFolder.createPackageFragment("test1", false, null); + + StringBuilder buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("public class F123 {\n"); + buf.append("}\n"); + ICompilationUnit cu1 = pack1.createCompilationUnit("F123.java", buf.toString(), false, null); + + buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("public class F456 {\n"); + buf.append(" { F123.foo(); }\n"); + buf.append("}\n"); + ICompilationUnit cu2 = pack1.createCompilationUnit("F456.java", buf.toString(), false, null); + + assertEquals(false, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertEquals(false, cu2.isWorkingCopy()); + assertEquals(false, cu2.hasUnsavedChanges()); + assertNewProblemReported(); + assertEquals(0, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(0); + + openDocument(cu2, cu2.getSource(), 1); + + assertEquals(false, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertEquals(true, cu2.isWorkingCopy()); + assertEquals(false, cu2.hasUnsavedChanges()); + assertNewProblemReported(new ExpectedProblemReport(cu2, 1)); + assertEquals(1, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(1); + + openDocument(cu1, cu1.getSource(), 1); + + assertEquals(true, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertEquals(true, cu2.isWorkingCopy()); + assertEquals(false, cu2.hasUnsavedChanges()); + assertNewProblemReported(new ExpectedProblemReport(cu2, 1), new ExpectedProblemReport(cu1, 0)); + assertEquals(2, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(2); + + buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("public class F123 {\n"); + buf.append(" public static void foo() {}\n"); + buf.append("}\n"); + + changeDocument(cu1, buf.toString(), 2); + + assertEquals(true, cu1.isWorkingCopy()); + assertEquals(true, cu1.hasUnsavedChanges()); + assertEquals(true, cu2.isWorkingCopy()); + assertEquals(false, cu2.hasUnsavedChanges()); + assertNewProblemReported(new ExpectedProblemReport(cu2, 0), new ExpectedProblemReport(cu1, 0)); + assertEquals(2, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(2); + + saveDocument(cu1); + + assertEquals(true, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertEquals(true, cu2.isWorkingCopy()); + assertEquals(false, cu2.hasUnsavedChanges()); + assertNewProblemReported(); + assertEquals(2, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(0); + + closeDocument(cu1); + + assertEquals(false, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertEquals(true, cu2.isWorkingCopy()); + assertEquals(false, cu2.hasUnsavedChanges()); + assertNewProblemReported(); + assertEquals(1, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(0); + + closeDocument(cu2); + + assertEquals(false, cu1.isWorkingCopy()); + assertEquals(false, cu1.hasUnsavedChanges()); + assertEquals(false, cu2.isWorkingCopy()); + assertEquals(false, cu2.hasUnsavedChanges()); + assertNewProblemReported(); + assertEquals(0, sharedASTProvider.getCacheSize()); + assertNewASTsCreated(0); + } + + @Test + public void testDidOpenStandaloneFile() throws Exception { + IJavaProject javaProject = newDefaultProject(); + IPackageFragmentRoot sourceFolder = javaProject.getPackageFragmentRoot(javaProject.getProject().getFolder("src")); + IPackageFragment pack1 = sourceFolder.createPackageFragment("java", false, null); + + // @formatter:off + String standaloneFileContent = + "package java;\n"+ + "public class Foo extends UnknownType {"+ + " public void method1(){\n"+ + " super.whatever();"+ + " }\n"+ + "}"; + // @formatter:on + ICompilationUnit cu1 = pack1.createCompilationUnit("Foo.java", standaloneFileContent, false, null); + + openDocument(cu1, cu1.getSource(), 1); + + List diagnosticReports = getClientRequests("publishDiagnostics"); + assertEquals(1, diagnosticReports.size()); + PublishDiagnosticsParams diagParam = diagnosticReports.get(0); + assertEquals(0, diagParam.getDiagnostics().size()); + } + + @Test + public void testDidOpenStandaloneFileWithSyntaxError() throws Exception { + IJavaProject javaProject = newDefaultProject(); + IPackageFragmentRoot sourceFolder = javaProject.getPackageFragmentRoot(javaProject.getProject().getFolder("src")); + IPackageFragment pack1 = sourceFolder.createPackageFragment("java", false, null); + + // @formatter:off + String standaloneFileContent = + "package java;\n"+ + "public class Foo extends UnknownType {\n"+ + " public void method1(){\n"+ + " super.whatever()\n"+ + " }\n"+ + "}"; + // @formatter:on + + ICompilationUnit cu1 = pack1.createCompilationUnit("Foo.java", standaloneFileContent, false, null); + + openDocument(cu1, cu1.getSource(), 1); + + List diagnosticReports = getClientRequests("publishDiagnostics"); + assertEquals(1, diagnosticReports.size()); + PublishDiagnosticsParams diagParam = diagnosticReports.get(0); + assertEquals("Unexpected number of errors " + diagParam.getDiagnostics(), 1, diagParam.getDiagnostics().size()); + Diagnostic d = diagParam.getDiagnostics().get(0); + assertEquals("Syntax error, insert \";\" to complete BlockStatements", d.getMessage()); + assertRange(3, 17, 18, d.getRange()); + } + + @Test + public void testDidOpenStandaloneFileWithNonSyntaxErrors() throws Exception { + IJavaProject javaProject = newDefaultProject(); + IPackageFragmentRoot sourceFolder = javaProject.getPackageFragmentRoot(javaProject.getProject().getFolder("src")); + IPackageFragment pack1 = sourceFolder.createPackageFragment("java", false, null); + + // @formatter:off + String standaloneFileContent = + "package java;\n"+ + "public class Foo {\n"+ + " public static void notThis(){\n"+ + " System.out.println(this);\n"+ + " }\n"+ + " public void method1(){\n"+ + " }\n"+ + " public void method1(){\n"+ + " }\n"+ + "}"; + // @formatter:on + + ICompilationUnit cu1 = pack1.createCompilationUnit("Foo.java", standaloneFileContent, false, null); + + openDocument(cu1, cu1.getSource(), 1); + + List diagnosticReports = getClientRequests("publishDiagnostics"); + assertEquals(1, diagnosticReports.size()); + PublishDiagnosticsParams diagParam = diagnosticReports.get(0); + + assertEquals("Unexpected number of errors " + diagParam.getDiagnostics(), 3, diagParam.getDiagnostics().size()); + Diagnostic d = diagParam.getDiagnostics().get(0); + assertEquals("Cannot use this in a static context", d.getMessage()); + assertRange(3, 21, 25, d.getRange()); + + d = diagParam.getDiagnostics().get(1); + assertEquals("Duplicate method method1() in type Foo", d.getMessage()); + assertRange(5, 13, 22, d.getRange()); + + d = diagParam.getDiagnostics().get(2); + assertEquals("Duplicate method method1() in type Foo", d.getMessage()); + assertRange(7, 13, 22, d.getRange()); + } + + @SuppressWarnings("unchecked") + private List getClientRequests(String name) { + List requests = clientRequests.get(name); + return requests != null ? (List) requests : Collections.emptyList(); + } + + private void openDocument(ICompilationUnit cu, String content, int version) { + DidOpenTextDocumentParams openParms = new DidOpenTextDocumentParams(); + TextDocumentItem textDocument = new TextDocumentItem(); + textDocument.setLanguageId("java"); + textDocument.setText(content); + textDocument.setUri(JDTUtils.getFileURI(cu)); + textDocument.setVersion(version); + openParms.setTextDocument(textDocument); + lifeCycleHandler.didOpen(openParms); + } + + private void changeDocument(ICompilationUnit cu, String content, int version) throws JavaModelException { + DidChangeTextDocumentParams changeParms = new DidChangeTextDocumentParams(); + VersionedTextDocumentIdentifier textDocument = new VersionedTextDocumentIdentifier(); + textDocument.setUri(JDTUtils.getFileURI(cu)); + textDocument.setVersion(version); + changeParms.setTextDocument(textDocument); + TextDocumentContentChangeEvent event = new TextDocumentContentChangeEvent(); + Range range = JDTUtils.toRange(cu, 0, cu.getSource().length()); + event.setRange(range); + event.setRangeLength(cu.getSource().length()); + event.setText(content); + List contentChanges = new ArrayList<>(); + contentChanges.add(event); + changeParms.setContentChanges(contentChanges); + lifeCycleHandler.didChange(changeParms); + } + + private void saveDocument(ICompilationUnit cu) throws JavaModelException { + DidSaveTextDocumentParams saveParms = new DidSaveTextDocumentParams(); + TextDocumentIdentifier textDocument = new TextDocumentIdentifier(); + textDocument.setUri(JDTUtils.getFileURI(cu)); + saveParms.setTextDocument(textDocument); + saveParms.setText(cu.getSource()); + lifeCycleHandler.didSave(saveParms); + } + + private void closeDocument(ICompilationUnit cu) { + DidCloseTextDocumentParams closeParms = new DidCloseTextDocumentParams(); + TextDocumentIdentifier textDocument = new TextDocumentIdentifier(); + textDocument.setUri(JDTUtils.getFileURI(cu)); + closeParms.setTextDocument(textDocument); + lifeCycleHandler.didClose(closeParms); + } + + class ExpectedProblemReport { + ICompilationUnit cu; + int problemCount; + + ExpectedProblemReport(ICompilationUnit cu, int problemCount) { + this.cu = cu; + this.problemCount = problemCount; + } + + } + + private void assertNewProblemReported(ExpectedProblemReport... expectedReports) { + List diags = getClientRequests("publishDiagnostics"); + assertEquals(expectedReports.length, diags.size()); + + for (int i = 0; i < expectedReports.length; i++) { + PublishDiagnosticsParams diag = diags.get(i); + ExpectedProblemReport expected = expectedReports[i]; + assertEquals(JDTUtils.getFileURI(expected.cu), diag.getUri()); + if (expected.problemCount != diag.getDiagnostics().size()) { + String message = ""; + for (Diagnostic d : diag.getDiagnostics()) { + message += d.getMessage() + ", "; + } + assertEquals(message, expected.problemCount, diag.getDiagnostics().size()); + } + + } + diags.clear(); + } + + private void assertNewASTsCreated(int expected) { + assertEquals(expected, sharedASTProvider.getASTCreationCount()); + sharedASTProvider.clearASTCreationCount(); + } +} diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifecycleHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifecycleHandlerTest.java deleted file mode 100644 index 08e35f321a..0000000000 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/DocumentLifecycleHandlerTest.java +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2017 Red Hat Inc. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Red Hat Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.ls.core.internal.handlers; - -import static org.eclipse.jdt.ls.core.internal.Lsp4jAssertions.assertRange; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.nio.file.Paths; - -import org.eclipse.jdt.core.WorkingCopyOwner; -import org.eclipse.jdt.ls.core.internal.JavaClientConnection; -import org.eclipse.jdt.ls.core.internal.LanguageServerWorkingCopyOwner; -import org.eclipse.jdt.ls.core.internal.managers.AbstractProjectsManagerBasedTest; -import org.eclipse.jdt.ls.core.internal.preferences.Preferences; -import org.eclipse.lsp4j.Diagnostic; -import org.eclipse.lsp4j.DidCloseTextDocumentParams; -import org.eclipse.lsp4j.DidOpenTextDocumentParams; -import org.eclipse.lsp4j.PublishDiagnosticsParams; -import org.eclipse.lsp4j.TextDocumentIdentifier; -import org.eclipse.lsp4j.TextDocumentItem; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class DocumentLifecycleHandlerTest extends AbstractProjectsManagerBasedTest { - - @Mock - private JavaClientConnection connection; - - private DocumentLifeCycleHandler handler; - - private String uri; - - @Before - public void setUp() throws Exception { - LanguageServerWorkingCopyOwner workingCopyOwner = new LanguageServerWorkingCopyOwner(connection); - WorkingCopyOwner.setPrimaryBufferProvider(workingCopyOwner); - handler = new DocumentLifeCycleHandler(connection, preferenceManager, projectsManager, workingCopyOwner); - when(preferenceManager.getPreferences(any())).thenReturn(new Preferences()); - newEmptyProject(); - - uri = Paths.get("projects", "maven", "salut", "src", "main", "java", "java", "Foo.java").toUri().toString(); - } - - @After - public void invalidateAll() { - if (uri != null) { - handler.handleClosed(new DidCloseTextDocumentParams(new TextDocumentIdentifier(uri))); - } - } - - @Test - public void testDidOpenStandaloneFile() throws Exception { - // @formatter:off - String standaloneFileContent = - "package java;\n"+ - "public class Foo extends UnknownType {"+ - " public void method1(){\n"+ - " super.whatever();"+ - " }\n"+ - "}"; - // @formatter:on - - PublishDiagnosticsParams diagnostics = open(standaloneFileContent); - assertEquals("Unexpected number of errors " + diagnostics.getDiagnostics(), 0, diagnostics.getDiagnostics().size()); - } - - @Test - public void testDidOpenStandaloneFileWithSyntaxError() throws Exception { - // @formatter:off - String standaloneFileContent = - "package java;\n"+ - "public class Foo extends UnknownType {\n"+ - " public void method1(){\n"+ - " super.whatever()\n"+ - " }\n"+ - "}"; - // @formatter:on - - PublishDiagnosticsParams diagParam = open(standaloneFileContent); - assertEquals("Unexpected number of errors " + diagParam.getDiagnostics(), 1, diagParam.getDiagnostics().size()); - Diagnostic d = diagParam.getDiagnostics().get(0); - assertEquals("Syntax error, insert \";\" to complete BlockStatements", d.getMessage()); - assertRange(3, 17, 18, d.getRange()); - } - - @Test - public void testDidOpenStandaloneFileWithNonSyntaxErrors() throws Exception { - // @formatter:off - String standaloneFileContent = - "package java;\n"+ - "public class Foo {\n"+ - " public static void notThis(){\n"+ - " System.out.println(this);\n"+ - " }\n"+ - " public void method1(){\n"+ - " }\n"+ - " public void method1(){\n"+ - " }\n"+ - "}"; - // @formatter:on - - PublishDiagnosticsParams diagParam = open(standaloneFileContent); - assertEquals("Unexpected number of errors " + diagParam.getDiagnostics(), 3, diagParam.getDiagnostics().size()); - Diagnostic d = diagParam.getDiagnostics().get(0); - assertEquals("Cannot use this in a static context", d.getMessage()); - assertRange(3, 21, 25, d.getRange()); - - d = diagParam.getDiagnostics().get(1); - assertEquals("Duplicate method method1() in type Foo", d.getMessage()); - assertRange(5, 13, 22, d.getRange()); - - d = diagParam.getDiagnostics().get(2); - assertEquals("Duplicate method method1() in type Foo", d.getMessage()); - assertRange(7, 13, 22, d.getRange()); - } - - private PublishDiagnosticsParams open(String text) { - DidOpenTextDocumentParams params = new DidOpenTextDocumentParams(new TextDocumentItem(uri, "java", 0, text)); - handler.handleOpen(params); - ArgumentCaptor diagnosticsCaptor = ArgumentCaptor.forClass(PublishDiagnosticsParams.class); - verify(connection, times(1)).publishDiagnostics(diagnosticsCaptor.capture()); - PublishDiagnosticsParams diagnostics = diagnosticsCaptor.getValue(); - assertNotNull(diagnostics); - return diagnostics; - } -} diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/AbstractProjectsManagerBasedTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/AbstractProjectsManagerBasedTest.java index f75de0b35e..73343fbfe3 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/AbstractProjectsManagerBasedTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/managers/AbstractProjectsManagerBasedTest.java @@ -23,6 +23,7 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; @@ -48,7 +49,7 @@ */ public abstract class AbstractProjectsManagerBasedTest { - public static final String DEFAULT_PROJECT_NAME = "TestSetupProject"; + public static final String TEST_PROJECT_NAME = "TestProject"; protected IProgressMonitor monitor = new NullProgressMonitor(); protected ProjectsManager projectsManager; @@ -78,9 +79,18 @@ public IBuffer createBuffer(ICompilationUnit workingCopy) { } protected IJavaProject newEmptyProject() throws Exception { - projectsManager.initializeProjects(null, monitor); + IProject testProject = ResourcesPlugin.getWorkspace().getRoot().getProject(TEST_PROJECT_NAME); + assertEquals(false, testProject.exists()); + projectsManager.createJavaProject(testProject, new NullProgressMonitor()); waitForBackgroundJobs(); - return JavaCore.create(projectsManager.getDefaultProject()); + return JavaCore.create(testProject); + } + + protected IJavaProject newDefaultProject() throws Exception { + IProject testProject = projectsManager.getDefaultProject(); + projectsManager.createJavaProject(testProject, new NullProgressMonitor()); + waitForBackgroundJobs(); + return JavaCore.create(testProject); } protected List importProjects(String path) throws Exception {