diff --git a/org.eclipse.lsp4e.test/META-INF/services/org.junit.jupiter.api.extension.Extension b/org.eclipse.lsp4e.test/META-INF/services/org.junit.jupiter.api.extension.Extension
index 85689bb7d..54df40dad 100644
--- a/org.eclipse.lsp4e.test/META-INF/services/org.junit.jupiter.api.extension.Extension
+++ b/org.eclipse.lsp4e.test/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -1 +1,2 @@
-org.eclipse.lsp4e.test.utils.CloseIntroExtension
\ No newline at end of file
+org.eclipse.lsp4e.test.utils.MockLanguageServerExtension
+org.eclipse.lsp4e.test.utils.CloseIntroExtension
diff --git a/org.eclipse.lsp4e.test/fragment.xml b/org.eclipse.lsp4e.test/fragment.xml
index 43ef922e0..73480c598 100644
--- a/org.eclipse.lsp4e.test/fragment.xml
+++ b/org.eclipse.lsp4e.test/fragment.xml
@@ -20,12 +20,6 @@
id="org.eclipse.lsp4e.test.server-with-exception"
lastDocumentDisconnectedTimeout="0"
label="Test LS With Exception">
-
-
-
-
@@ -130,7 +120,7 @@
base-type="org.eclipse.core.runtime.text"
file-extensions="lsptmultils"
id="org.eclipse.lsp4e.test.content-type-multi-ls"
- name="Test Content Type"
+ name="Test Content Type which is picked up by two different LS"
priority="normal">
-
-
GitHub Pull Request #688
*/
@Test
- public void testStartStopAndActive() throws CoreException, AssertionError {
+ public void testStartStopAndActive(MockLanguageServerFactory factory) throws CoreException, AssertionError {
+ factory.withCapabilities(MockLanguageServer::multiRootCapabilities);
final int testCount= 100;
- MockConnectionProviderMultiRootFolders.resetCounts();
-
- IFile testFile1 = TestUtils.createFile(project, "shouldUseExtension.lsptWithMultiRoot", "");
+ IFile testFile1 = TestUtils.createFile(project, "shouldUseExtension.lspt", "");
IEditorPart editor1 = TestUtils.openEditor(testFile1);
@NonNull Collection wrappers = LanguageServiceAccessor.getLSWrappers(testFile1, request -> true);
assertEquals(1, wrappers.size());
@@ -132,10 +133,7 @@ public void testStartStopAndActive() throws CoreException, AssertionError {
if (ForkJoinPool.commonPool().getActiveThreadCount() > startingActiveThreads)
throw new AssertionError("timeout waiting for ForkJoinPool.commonPool to go quiet");
- Integer cpStartCount= MockConnectionProviderMultiRootFolders.getStartCount();
- Integer cpStopCount= MockConnectionProviderMultiRootFolders.getStopCount();
-
- assertEquals(cpStartCount, cpStopCount, "startCount == stopCount");
+ assertEquals(factory.connectionProviderStartCounter.get(), factory.connectionProviderStopCounter.get());
}
}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServersTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServersTest.java
index c50c27745..c19dfd0ae 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServersTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServersTest.java
@@ -46,8 +46,8 @@
import org.eclipse.lsp4e.internal.Pair;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockConnectionProvider;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4e.tests.mock.MockTextDocumentService;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.Hover;
@@ -70,19 +70,20 @@ public class LanguageServersTest extends AbstractTestWithProject {
private final Predicate MATCH_ALL = sc -> true;
@Test
- public void testCollectAll() throws Exception {
- final var hoverCount = new AtomicInteger();
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + hoverCount.incrementAndGet())), new Range(new Position(0, 0), new Position(0, 10)));
- return CompletableFuture.completedFuture(hoverResponse);
- }
+ public void testCollectAll(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ }
+
+ @Override
+ public CompletableFuture hover(HoverParams position) {
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + idx)), new Range(new Position(0, 0), new Position(0, 10)));
+ return CompletableFuture.completedFuture(hoverResponse);
+ }
+ });
});
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
@@ -101,24 +102,25 @@ public synchronized CompletableFuture hover(HoverParams position) {
List hovers = result.join();
+ assertTrue(hovers.contains("HoverContent0"));
assertTrue(hovers.contains("HoverContent1"));
- assertTrue(hovers.contains("HoverContent2"));
}
@Test
- public void testCollectAllExcludesNulls() throws Exception {
- final var hoverCount = new AtomicInteger();
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + hoverCount.incrementAndGet())), new Range(new Position(0, 0), new Position(0, 10)));
- return CompletableFuture.completedFuture(hoverCount.get() == 1 ? hoverResponse : null);
- }
+ public void testCollectAllExcludesNulls(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ }
+
+ @Override
+ public CompletableFuture hover(HoverParams position) {
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + idx)), new Range(new Position(0, 0), new Position(0, 10)));
+ return CompletableFuture.completedFuture(idx == 0 ? hoverResponse : null);
+ }
+ });
});
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
@@ -137,32 +139,33 @@ public synchronized CompletableFuture hover(HoverParams position) {
List hovers = result.join();
- assertTrue(hovers.contains("HoverContent1"));
+ assertTrue(hovers.contains("HoverContent0"));
assertFalse(hovers.contains(null));
}
@Test
- public void testComputeAll() throws Exception {
- final var hoverCount = new AtomicInteger();
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + hoverCount.incrementAndGet())), new Range(new Position(0, 0), new Position(0, 10)));
- final int currentCount = hoverCount.get();
- return CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
- try {
- Thread.sleep(currentCount * 1000);
- } catch (InterruptedException e) {
-
- }
- return t;
- });
- }
+ public void testComputeAll(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ }
+
+ @Override
+ public CompletableFuture hover(HoverParams position) {
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + idx)), new Range(new Position(0, 0), new Position(0, 10)));
+ final int currentCount = idx + 1;
+ return CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
+ try {
+ Thread.sleep(currentCount * 1000);
+ } catch (InterruptedException e) {
+
+ }
+ return t;
+ });
+ }
+ });
});
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
@@ -183,12 +186,12 @@ public synchronized CompletableFuture hover(HoverParams position) {
final Object first = CompletableFuture.anyOf(result.get(0), result.get(1)).join();
- assertEquals("HoverContent1", first, "HoverContent1 should have returned first, independently");
+ assertEquals("HoverContent0", first, "HoverContent1 should have returned first, independently");
List hovers = result.stream().map(CompletableFuture::join).toList();
+ assertTrue(hovers.contains("HoverContent0"));
assertTrue(hovers.contains("HoverContent1"));
- assertTrue(hovers.contains("HoverContent2"));
}
@@ -200,11 +203,13 @@ public synchronized CompletableFuture hover(HoverParams position) {
* run in the default executor pool, not the listener thread.
*/
@Test
- public void testCollectAllUserCannotBlockListener() throws Exception {
+ public void testCollectAllUserCannotBlockListener(MockLanguageServerFactory factory) throws Exception {
// This test will only work if a minimum of two tasks can be run in the common pool without blocking!
assumeTrue(ForkJoinPool.commonPool().getParallelism() >= 2, "Test skipped as common thread pool does not have multiple executors");
final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent")), new Range(new Position(0, 0), new Position(0, 10)));
- MockLanguageServer.INSTANCE.setHover(hoverResponse);
+ factory.withConfiguration((idx, server) -> {
+ server.setHover(hoverResponse);
+ });
IFile testFile = TestUtils.createUniqueTestFile(project, "Here is some content");
ITextViewer viewer = TestUtils.openTextViewer(testFile);
@@ -247,30 +252,31 @@ public void testCollectAllUserCannotBlockListener() throws Exception {
}
@Test
- public void testComputeFirst() throws Exception {
- final var hoverCount = new AtomicInteger();
+ public void testComputeFirst(MockLanguageServerFactory factory) throws Exception {
final var internalResults = new Vector>();
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + hoverCount.incrementAndGet())), new Range(new Position(0, 0), new Position(0, 10)));
- final int currentCount = hoverCount.get();
- CompletableFuture result = CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
- try {
- Thread.sleep(currentCount * 1000);
- } catch (InterruptedException e) {
-
- }
- return t;
- });
- internalResults.add(result);
- return result;
- }
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ }
+
+ @Override
+ public CompletableFuture hover(HoverParams position) {
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + idx)), new Range(new Position(0, 0), new Position(0, 10)));
+ final int currentCount = idx + 1;
+ CompletableFuture result = CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
+ try {
+ Thread.sleep(currentCount * 1000);
+ } catch (InterruptedException e) {
+
+ }
+ return t;
+ });
+ internalResults.add(result);
+ return result;
+ }
+ });
});
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
@@ -290,7 +296,7 @@ public synchronized CompletableFuture hover(HoverParams position) {
Optional result = response.join();
assertTrue(result.isPresent());
- assertEquals("HoverContent1", result.get(), "HoverContent1 should have arrived first");
+ assertEquals("HoverContent0", result.get(), "HoverContent0 should have arrived first");
// It won't *normally) matter in production but because the tests run quickly, make sure the test teardown doesn't
// occur before the slower, ignored result has completed, otherwise will get a load of console noise
@@ -298,29 +304,30 @@ public synchronized CompletableFuture hover(HoverParams position) {
}
@Test
- public void testComputeFirstSkipsEmptyResults() throws Exception {
- final var hoverCount = new AtomicInteger();
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + hoverCount.incrementAndGet())), new Range(new Position(0, 0), new Position(0, 10)));
- if (hoverCount.get() == 1) {
- return CompletableFuture.completedFuture(null);
+ public void testComputeFirstSkipsEmptyResults(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
}
- return CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
-
+
+ @Override
+ public CompletableFuture hover(HoverParams position) {
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + idx)), new Range(new Position(0, 0), new Position(0, 10)));
+ if (idx == 0) {
+ return CompletableFuture.completedFuture(null);
}
- return t;
- });
- }
+ return CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+
+ }
+ return t;
+ });
+ }
+ });
});
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
@@ -340,22 +347,24 @@ public synchronized CompletableFuture hover(HoverParams position) {
Optional result = response.join();
assertTrue(result.isPresent(), "Should have returned a result");
- assertEquals("HoverContent2", result.get(), "HoverContent2 should have been the result");
+ assertEquals("HoverContent1", result.get(), "HoverContent1 should have been the result");
}
@Test
- public void testComputeFirstReturnsEmptyOptionalIfNoResult() throws Exception {
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- return CompletableFuture.completedFuture(null);
- }
+ public void testComputeFirstReturnsEmptyOptionalIfNoResult(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public synchronized void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ }
+
+ @Override
+ public synchronized CompletableFuture hover(HoverParams position) {
+ return CompletableFuture.completedFuture(null);
+ }
+ });
});
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
@@ -377,30 +386,32 @@ public synchronized CompletableFuture hover(HoverParams position) {
}
@Test
- public void testComputeFirstTreatsEmptyListAsNull() throws Exception {
- final var hoverCount = new AtomicInteger();
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + hoverCount.incrementAndGet())), new Range(new Position(0, 0), new Position(0, 10)));
- if (hoverCount.get() == 1) {
- return CompletableFuture.completedFuture(null);
+ public void testComputeFirstTreatsEmptyListAsNull(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
}
- return CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
-
+
+ @Override
+ public CompletableFuture hover(HoverParams position) {
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent" + idx)), new Range(new Position(0, 0), new Position(0, 10)));
+ if (idx == 0) {
+ return CompletableFuture.completedFuture(null);
}
- return t;
- });
- }
+ return CompletableFuture.completedFuture(hoverResponse).thenApplyAsync(t -> {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+
+ }
+ return t;
+ });
+ }
+ });
});
+
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
ITextViewer viewer = TestUtils.openTextViewer(testFile);
@@ -419,7 +430,7 @@ public synchronized CompletableFuture hover(HoverParams position) {
Optional> result = response.join();
assertTrue(result.isPresent(), "Should have returned a result");
- assertEquals("HoverContent2", result.get().get(0), "HoverContent2 should have been the result");
+ assertEquals("HoverContent1", result.get().get(0), "HoverContent1 should have been the result");
}
/**
@@ -428,35 +439,38 @@ public synchronized CompletableFuture hover(HoverParams position) {
* arrive [are sent to] the server
*/
@Test
- public void editInterleavingTortureTest() throws Exception {
-
+ public void editInterleavingTortureTest(MockLanguageServerFactory factory) throws Exception {
final Vector tooEarlyHover = new Vector<>();
final Vector tooLateHover = new Vector<>();
-
- MockLanguageServer.INSTANCE.getInitializeResult().getCapabilities()
- .setTextDocumentSync(TextDocumentSyncKind.Incremental);
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- int changeVersion = 0;
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- changeVersion++;
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final int targetVersionForRequest = position.getPosition().getCharacter();
- if (targetVersionForRequest < changeVersion) {
- tooLateHover.add(targetVersionForRequest);
- } else if (targetVersionForRequest > changeVersion){
- tooEarlyHover.add(targetVersionForRequest);
+
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ int changeVersion = 0;
+ @Override
+ public synchronized void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ changeVersion++;
+ }
+
+ @Override
+ public synchronized CompletableFuture hover(HoverParams position) {
+ final int targetVersionForRequest = position.getPosition().getCharacter();
+ if (targetVersionForRequest < changeVersion) {
+ tooLateHover.add(targetVersionForRequest);
+ } else if (targetVersionForRequest > changeVersion){
+ tooEarlyHover.add(targetVersionForRequest);
+ }
+ return super.hover(position);
}
- return super.hover(position);
- }
+ });
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent")), new Range(new Position(0, 0), new Position(0, 10)));
+ server.setHover(hoverResponse);
+ });
+ factory.withCapabilities(() -> {
+ var cap = MockLanguageServer.defaultServerCapabilities();
+ cap.setTextDocumentSync(TextDocumentSyncKind.Incremental);
+ return cap;
});
-
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent")), new Range(new Position(0, 0), new Position(0, 10)));
- MockLanguageServer.INSTANCE.setHover(hoverResponse);
CompletableFuture> initial = CompletableFuture.completedFuture(null);
IFile testFile = TestUtils.createUniqueTestFile(project, "");
@@ -508,32 +522,37 @@ public synchronized CompletableFuture hover(HoverParams position) {
* (b) Dispatch does not occur on the UI thread
*/
@Test
- public void testBlockingServerDoesNotBlockUIThread() throws Exception {
+ public void testBlockingServerDoesNotBlockUIThread(MockLanguageServerFactory factory) throws Exception {
final var uiDispatchCount = new AtomicInteger();
-
- MockLanguageServer.INSTANCE.getInitializeResult().getCapabilities()
- .setTextDocumentSync(TextDocumentSyncKind.Incremental);
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ factory.withCapabilities(() -> {
+ var cap = MockLanguageServer.defaultServerCapabilities();
+ cap.setTextDocumentSync(TextDocumentSyncKind.Incremental);
+ return cap;
+ });
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public synchronized void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
}
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- // No need for any special processing, but needs to be synchronized to
- // make server block if processing a
- return super.hover(position);
- }
+
+ @Override
+ public synchronized CompletableFuture hover(HoverParams position) {
+ // No need for any special processing, but needs to be synchronized to
+ // make server block if processing a
+ return super.hover(position);
+ }
+ });
+
+ final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent")), new Range(new Position(0, 0), new Position(0, 10)));
+ server.setHover(hoverResponse);
});
-
- final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent")), new Range(new Position(0, 0), new Position(0, 10)));
- MockLanguageServer.INSTANCE.setHover(hoverResponse);
+
CompletableFuture> initial = CompletableFuture.completedFuture(null);
IFile testFile = TestUtils.createUniqueTestFile(project, "");
@@ -592,7 +611,7 @@ public synchronized CompletableFuture hover(HoverParams position) {
}
@Test
- public void testAnyMatchingIsNonBlocking() throws Exception {
+ public void testAnyMatchingIsNonBlocking(MockLanguageServerFactory factory) throws Exception {
// test with no LS available
long start = System.currentTimeMillis();
assertFalse(LanguageServers.forProject(project).anyMatching());
@@ -600,7 +619,9 @@ public void testAnyMatchingIsNonBlocking() throws Exception {
assertTrue(duration < 100, "LanguageServers.anyMatching() took too long: " + duration + "ms");
// test with one slow LS available
- MockLanguageServer.INSTANCE.setTimeToProceedQueries(5_000);
+ factory.withConfiguration((idx, server) -> {
+ server.setTimeToProceedQueries(5_000);
+ });
var testFile1 = createUniqueTestFile(project, "");
var editor1 = openEditor(testFile1);
start = System.currentTimeMillis();
@@ -614,9 +635,11 @@ public void testAnyMatchingIsNonBlocking() throws Exception {
}
@Test
- public void testNoMatchingServers() throws Exception {
+ public void testNoMatchingServers(MockLanguageServerFactory factory) throws Exception {
final var hoverResponse = new Hover(List.of(Either.forLeft("HoverContent")), new Range(new Position(0, 0), new Position(0, 10)));
- MockLanguageServer.INSTANCE.setHover(hoverResponse);
+ factory.withConfiguration((idx, server) -> {
+ server.setHover(hoverResponse);
+ });
IFile testFile = TestUtils.createUniqueTestFile(project, "");
ITextViewer viewer = TestUtils.openTextViewer(testFile);
@@ -646,19 +669,21 @@ public void testNoMatchingServers() throws Exception {
}
@Test
- public void testComputeFirstBubblesException() throws Exception {
- MockLanguageServer.INSTANCE.setTextDocumentService(new MockTextDocumentService(MockLanguageServer.INSTANCE::buildMaybeDelayedFuture) {
- @Override
- public synchronized void didChange(DidChangeTextDocumentParams params) {
- super.didChange(params);
- }
-
- @Override
- public synchronized CompletableFuture hover(HoverParams position) {
- final var result = new CompletableFuture();
- result.completeExceptionally(new IllegalStateException("No hovering here"));
- return result;
- }
+ public void testComputeFirstBubblesException(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration((idx, server) -> {
+ server.setTextDocumentService(new MockTextDocumentService(server::buildMaybeDelayedFuture) {
+ @Override
+ public synchronized void didChange(DidChangeTextDocumentParams params) {
+ super.didChange(params);
+ }
+
+ @Override
+ public synchronized CompletableFuture hover(HoverParams position) {
+ final var result = new CompletableFuture();
+ result.completeExceptionally(new IllegalStateException("No hovering here"));
+ return result;
+ }
+ });
});
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
@@ -687,10 +712,12 @@ public synchronized CompletableFuture hover(HoverParams position) {
* the same language server for follow-up calls
*/
@Test
- public void testWrapperWrapsSameLS() throws Exception {
+ public void testWrapperWrapsSameLS(MockLanguageServerFactory factory) throws Exception {
final var hoverResponse = new Hover(
List.of(Either.forLeft("HoverContent")), new Range(new Position(0, 0), new Position(0, 10)));
- MockLanguageServer.INSTANCE.setHover(hoverResponse);
+ factory.withConfiguration((idx, server) -> {
+ server.setHover(hoverResponse);
+ });
IFile testFile = TestUtils.createUniqueTestFileMultiLS(project, "Here is some content");
ITextViewer viewer = TestUtils.openTextViewer(testFile);
@@ -779,45 +806,47 @@ public void testGetDocument() throws Exception {
}
@Test
- public void testCancellable() throws Exception {
+ public void testCancellable(MockLanguageServerFactory factory) throws Exception {
IFile testFile = TestUtils.createUniqueTestFile(project, "Here is some content");
ITextViewer viewer = TestUtils.openTextViewer(testFile);
Display display = viewer.getTextWidget().getDisplay();
DisplayHelper.sleep(display, 2000);
+ // Delay answer on server side
+ factory.getServer().setTimeToProceedQueries(3000);
+
final IDocument document = viewer.getDocument();
final LanguageServerDocumentExecutor executor = LanguageServers.forDocument(document);
- MockLanguageServer.INSTANCE.setTimeToProceedQueries(3000);
// Test lsWrapper.execute() forwards cancellation
LanguageServerWrapper lsWrapper = executor.computeFirst((wrapper, ls) -> CompletableFuture.completedFuture(wrapper)).get().get();
CompletableFuture> request = lsWrapper.execute(ls -> ls.getTextDocumentService().references(new ReferenceParams()));
DisplayHelper.sleep(viewer.getTextWidget().getDisplay(), 500);
request.cancel(false);
- assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !MockConnectionProvider.cancellations.isEmpty()));
+ assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !factory.cancellations.isEmpty()));
// Test executor.computeFirst() forwards cancellation
- MockConnectionProvider.cancellations.clear();
+ factory.cancellations.clear();
request = executor.computeFirst(ls -> ls.getTextDocumentService().references(new ReferenceParams()));
DisplayHelper.sleep(viewer.getTextWidget().getDisplay(), 500);
request.cancel(false);
DisplayHelper.sleep(viewer.getTextWidget().getDisplay(), 100);
- assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !MockConnectionProvider.cancellations.isEmpty()));
+ assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !factory.cancellations.isEmpty()));
// Test executor.collectAll() forwards cancellation
- MockConnectionProvider.cancellations.clear();
+ factory.cancellations.clear();
request = executor.collectAll(ls -> ls.getTextDocumentService().references(new ReferenceParams()));
DisplayHelper.sleep(viewer.getTextWidget().getDisplay(), 500);
request.cancel(false);
DisplayHelper.sleep(viewer.getTextWidget().getDisplay(), 100);
- assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !MockConnectionProvider.cancellations.isEmpty()));
+ assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !factory.cancellations.isEmpty()));
// Test executor.computeAll() forwards cancellation
- MockConnectionProvider.cancellations.clear();
+ factory.cancellations.clear();
@NonNull List<@NonNull CompletableFuture<@Nullable List extends Location>>> requests = executor.computeAll(ls -> ls.getTextDocumentService().references(new ReferenceParams()));
DisplayHelper.sleep(viewer.getTextWidget().getDisplay(), 500);
requests.forEach(r -> r.cancel(false));
DisplayHelper.sleep(viewer.getTextWidget().getDisplay(), 100);
- assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !MockConnectionProvider.cancellations.isEmpty()));
+ assertTrue(DisplayHelper.waitForCondition(display, 3000, () -> !factory.cancellations.isEmpty()));
}
}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServiceAccessorTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServiceAccessorTest.java
index 850a66945..d9edb302e 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServiceAccessorTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/LanguageServiceAccessorTest.java
@@ -52,8 +52,10 @@
import org.eclipse.lsp4e.LanguageServersRegistry;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.MappingEnablementTester;
+import org.eclipse.lsp4e.test.utils.TestUtils;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServerMultiRootFolders;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
+import org.eclipse.lsp4e.tests.mock.MockServerState;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.ui.ide.IDE;
@@ -107,7 +109,9 @@ public void testLSAsRunConfiguration() throws Exception {
var testFile = createFile(project, "shouldUseRunConfiguration.lspt2", "");
// Force LS to initialize and open file
LanguageServers.forDocument(LSPEclipseUtils.getDocument(testFile)).anyMatching();
- assertTrue(hasActiveLanguageServers(testFile, MATCH_ALL));
+ // anyMatching will return after 50ms, even if the LS is still initializing.
+ // So we have to give the LS slightly more time.
+ TestUtils.waitForAndAssertCondition(5_000, () -> assertTrue(hasActiveLanguageServers(testFile, MATCH_ALL)));
}
@Test
@@ -179,19 +183,19 @@ public void testGetOnlyRunningLanguageServers() throws Exception {
}
@Test
- public void testCreateNewLSAfterInitialProjectGotDeleted() throws Exception {
+ public void testCreateNewLSAfterInitialProjectGotDeleted(MockLanguageServerFactory factory) throws Exception {
var testFile1 = createUniqueTestFile(project, "");
openEditor(testFile1);
assertTrue(hasActiveLanguageServers(testFile1, MATCH_ALL));
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 1);
var wrappers = getLSWrappers(testFile1, MATCH_ALL);
var wrapper1 = wrappers.iterator().next();
assertTrue(wrapper1.isActive());
UI.getActivePage().closeAllEditors(false);
- waitForAndAssertCondition(5_000, () -> !MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServer().getState() != MockServerState.RUNNING);
project.delete(true, true, new NullProgressMonitor());
@@ -200,7 +204,7 @@ public void testCreateNewLSAfterInitialProjectGotDeleted() throws Exception {
openEditor(testFile2);
assertTrue(hasActiveLanguageServers(testFile2, MATCH_ALL));
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 2);
wrappers = getLSWrappers(testFile2, MATCH_ALL);
var wrapper2 = wrappers.iterator().next();
@@ -215,28 +219,30 @@ public void testCreateNewLSAfterInitialProjectGotDeleted() throws Exception {
* put the server in the running state.
*/
@Test
- public void testReuseMultirootFolderLSAfterInitialProjectGotDeleted() throws Exception {
- var testFile1 = createUniqueTestFile(project, "lsptWithMultiRoot", "");
+ public void testReuseMultirootFolderLSAfterInitialProjectGotDeleted(MockLanguageServerFactory factory) throws Exception {
+ factory.withCapabilities(MockLanguageServer::multiRootCapabilities);
+
+ var testFile1 = createUniqueTestFile(project, "lspt", "");
openEditor(testFile1);
assertTrue(hasActiveLanguageServers(testFile1, MATCH_ALL));
- // FIXME waitForCondition(5_000, () -> MockLanguageServerMultiRootFolders.INSTANCE.isRunning());
+ waitForCondition(5_000, () -> factory.getServerCount() == 1);
var wrappers = getLSWrappers(testFile1, MATCH_ALL);
var wrapper1 = wrappers.iterator().next();
assertTrue(wrapper1.isActive());
UI.getActivePage().closeAllEditors(false);
- waitForAndAssertCondition(5_000, () -> !MockLanguageServerMultiRootFolders.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServer().getState() != MockServerState.RUNNING);
project.delete(true, true, new NullProgressMonitor());
project = createProject("LanguageServiceAccessorTest2" + System.currentTimeMillis());
- var testFile2 = createUniqueTestFile(project, "lsptWithMultiRoot", "");
+ var testFile2 = createUniqueTestFile(project, "lspt", "");
openEditor(testFile2);
assertTrue(hasActiveLanguageServers(testFile2, MATCH_ALL));
- // FIXME waitForAndAssertCondition(5_000, () -> MockLanguageServerMultiRootFolders.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 2);
wrappers = getLSWrappers(testFile2, MATCH_ALL);
var wrapper2 = wrappers.iterator().next();
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/ResourceFallbackPreferenceTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/ResourceFallbackPreferenceTest.java
index fac717ff2..9b77b9b70 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/ResourceFallbackPreferenceTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/ResourceFallbackPreferenceTest.java
@@ -41,22 +41,14 @@
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockConnectionProviderMultiRootFolders;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServerMultiRootFolders;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4j.DidOpenTextDocumentParams;
import org.eclipse.lsp4j.DidSaveTextDocumentParams;
import org.eclipse.ui.IEditorPart;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class ResourceFallbackPreferenceTest extends AbstractTestWithProject {
- @BeforeEach
- public void setUp() throws Exception {
- MockConnectionProviderMultiRootFolders.resetCounts();
- }
-
private static final class TestDocument extends Document implements IAdaptable {
private final URI uri;
@@ -76,16 +68,12 @@ public T getAdapter(Class adapter) {
}
@Test
- public void testFallbackEnabledReceivesExternalSave()
+ public void testFallbackEnabledReceivesExternalSave(MockLanguageServerFactory factory)
throws CoreException, IOException, InterruptedException, ExecutionException, TimeoutException {
IPreferenceStore store = LanguageServerPlugin.getDefault().getPreferenceStore();
store.setValue("org.eclipse.lsp4e.resourceFallback.enabled", true);
- // Ensure any previously started wrappers are cleared so the new preference
- // takes effect
- LanguageServiceAccessor.clearStartedServers();
-
- IFile testFile = TestUtils.createFile(project, "extSaveEnabled.lsptWithMultiRoot", "initial");
+ IFile testFile = TestUtils.createFile(project, "extSaveEnabled.lspt", "initial");
// ensure server is started
@NonNull Collection wrappers = LanguageServiceAccessor.getLSWrappers(testFile,
request -> true);
@@ -94,19 +82,14 @@ public void testFallbackEnabledReceivesExternalSave()
// arrange to capture didSave and didOpen from either mock server instance
// BEFORE connecting
- final var didSave1 = new CompletableFuture();
- final var didSave2 = new CompletableFuture();
- MockLanguageServerMultiRootFolders.INSTANCE.setDidSaveCallback(didSave1);
- MockLanguageServer.INSTANCE.setDidSaveCallback(didSave2);
+ final var didSave = new CompletableFuture();
+ factory.getServer().setDidSaveCallback(didSave);
- final var didOpen1 = new CompletableFuture();
- final var didOpen2 = new CompletableFuture();
- MockLanguageServerMultiRootFolders.INSTANCE.setDidOpenCallback(didOpen1);
- MockLanguageServer.INSTANCE.setDidOpenCallback(didOpen2);
+ final var didOpen = new CompletableFuture();
+ factory.getServer().setDidOpenCallback(didOpen);
// wait until a mock server instance has been wired/started
- TestUtils.waitForAndAssertCondition(5_000, () -> assertTrue(
- MockLanguageServer.INSTANCE.isRunning() || MockLanguageServerMultiRootFolders.INSTANCE.isRunning()));
+ TestUtils.waitForAndAssertCondition(5_000, () -> assertTrue(factory.getServerCount() == 1 ));
// Connect the wrapper to a synthetic non-buffered document so resource fallback
// will be used
@@ -126,7 +109,7 @@ public void testFallbackEnabledReceivesExternalSave()
// wait until one of the mock servers processed didOpen for this document to
// ensure it's ready
- CompletableFuture.anyOf(didOpen1, didOpen2).get(5, TimeUnit.SECONDS);
+ CompletableFuture.anyOf(didOpen).get(5, TimeUnit.SECONDS);
// modify file via workspace API so a CONTENT delta is reported
testFile.setContents(new ByteArrayInputStream("external-change".getBytes(StandardCharsets.UTF_8)), true, false,
@@ -137,13 +120,13 @@ public void testFallbackEnabledReceivesExternalSave()
// wrapper as a fallback (mirrors what ResourceFallbackListener would do) so
// test is deterministic.
try {
- CompletableFuture.anyOf(didSave1, didSave2).get(5, TimeUnit.SECONDS);
+ CompletableFuture.anyOf(didSave).get(5, TimeUnit.SECONDS);
} catch (TimeoutException t) {
final var identifier = LSPEclipseUtils.toTextDocumentIdentifier(testFile.getLocationURI());
final var params = new DidSaveTextDocumentParams(identifier, "external-change");
wrapper.sendNotification(ls -> ls.getTextDocumentService().didSave(params));
// now wait briefly for the mock to receive it
- CompletableFuture.anyOf(didSave1, didSave2).get(2, TimeUnit.SECONDS);
+ CompletableFuture.anyOf(didSave).get(2, TimeUnit.SECONDS);
}
// cleanup
@@ -151,16 +134,12 @@ public void testFallbackEnabledReceivesExternalSave()
}
@Test
- public void testFallbackDisabledIgnoresExternalSave()
+ public void testFallbackDisabledIgnoresExternalSave(MockLanguageServerFactory factory)
throws CoreException, IOException, InterruptedException, ExecutionException {
IPreferenceStore store = LanguageServerPlugin.getDefault().getPreferenceStore();
store.setValue("org.eclipse.lsp4e.resourceFallback.enabled", false);
- // Ensure any previously started wrappers are cleared so the new preference
- // takes effect
- LanguageServiceAccessor.clearStartedServers();
-
- IFile testFile = TestUtils.createFile(project, "extSaveDisabled.lsptWithMultiRoot", "initial");
+ IFile testFile = TestUtils.createFile(project, "extSaveDisabled.lspt", "initial");
@NonNull Collection wrappers = LanguageServiceAccessor.getLSWrappers(testFile,
request -> true);
assertTrue(wrappers.size() == 1);
@@ -180,11 +159,11 @@ public void testFallbackDisabledIgnoresExternalSave()
// arrange to capture didSave from the mock language server and ensure it does
// NOT complete
final var didSaveExpectation = new CompletableFuture();
- MockLanguageServerMultiRootFolders.INSTANCE.setDidSaveCallback(didSaveExpectation);
+ factory.getServer().setDidSaveCallback(didSaveExpectation);
// modify file outside of editor to simulate external save (no buffer backing
// the file now)
- Path p = Path.of(testFile.getLocationURI());
+ Path p = testFile.getLocation().toPath();
Files.writeString(p, "external-change", StandardCharsets.UTF_8);
// With fallback disabled, the mock server should NOT receive a didSave via
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/RunningLanguageServerTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/RunningLanguageServerTest.java
index 24bf3fec8..8bedde4b3 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/RunningLanguageServerTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/RunningLanguageServerTest.java
@@ -27,7 +27,8 @@
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
+import org.eclipse.lsp4e.tests.mock.MockServerState;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.texteditor.AbstractTextEditor;
@@ -40,25 +41,29 @@ public class RunningLanguageServerTest extends AbstractTestWithProject {
* closing the same file/editor multiple times
*/
@Test
- public void testOpenCloseLanguageServer() throws Exception {
+ public void testOpenCloseLanguageServer(MockLanguageServerFactory factory) throws Exception {
IFile testFile = TestUtils.createUniqueTestFile(project, "");
// open and close the editor several times
- for(int i = 1; i <= 10; i++) {
+ int iterations = 10;
+ for(int i = 0; i < iterations; i++) {
IEditorPart editor = TestUtils.openEditor(testFile);
assertFalse(LanguageServiceAccessor.getLSWrappers(testFile, capabilities -> true).isEmpty());
+
+ int serverIndex = i;
waitForAndAssertCondition("MockLanguageServer should be started for iteration #" + i, 5_000,
- () -> MockLanguageServer.INSTANCE.isRunning());
+ () -> factory.getServerCount() == serverIndex +1);
((AbstractTextEditor)editor).close(false);
waitForAndAssertCondition("MockLanguageServer should be stopped after iteration #" + i, 5_000,
- () -> !MockLanguageServer.INSTANCE.isRunning());
+ () -> factory.getServers().get(serverIndex).getState() != MockServerState.RUNNING );
}
+ assertEquals(iterations, factory.getServerCount());
}
@Test
- public void testDisabledLanguageServer() throws Exception {
+ public void testDisabledLanguageServer(MockLanguageServerFactory factory) throws Exception {
IFile testFile = TestUtils.createUniqueTestFile(project, "lspt-disabled", "");
ContentTypeToLanguageServerDefinition lsDefinition = TestUtils.getDisabledLS();
@@ -76,7 +81,7 @@ public void testDisabledLanguageServer() throws Exception {
LanguageServiceAccessor.enableLanguageServerContentType(lsDefinition, TestUtils.getEditors());
waitForAndAssertCondition("language server should be started", 5_000,
- () -> MockLanguageServer.INSTANCE.isRunning());
+ () -> factory.getServerCount() == 1);
}
@Test
@@ -94,11 +99,11 @@ public void testBug535887DisabledWithMultipleOpenFiles() throws CoreException {
}
@Test
- public void testDelayedStopDoesntCauseFreeze() throws Exception {
+ public void testDelayedStopDoesntCauseFreeze(MockLanguageServerFactory factory) throws Exception {
IFile testFile = TestUtils.createUniqueTestFile(project, "");
IEditorPart editor = TestUtils.openEditor(testFile);
IWorkbenchPage page = editor.getSite().getPage();
- MockLanguageServer.INSTANCE.setTimeToProceedQueries(10000);
+ factory.getServer().setTimeToProceedQueries(1100);
long before = System.currentTimeMillis();
page.closeEditor(editor, false);
assertTrue(System.currentTimeMillis() - before < 1000);
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/VersioningSupportTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/VersioningSupportTest.java
index 9ee64f424..6738e9a37 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/VersioningSupportTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/VersioningSupportTest.java
@@ -29,7 +29,7 @@
import org.eclipse.lsp4e.internal.DocumentUtil;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4j.DocumentFormattingParams;
import org.eclipse.lsp4j.FormattingOptions;
import org.eclipse.lsp4j.Position;
@@ -42,12 +42,14 @@
public class VersioningSupportTest extends AbstractTestWithProject {
@Test
- public void testVersionSupportSuccess() throws Exception {
+ public void testVersionSupportSuccess(MockLanguageServerFactory factory) throws Exception {
final var formattingTextEdits = new ArrayList();
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 0), new Position(0, 1)), "MyF"));
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 10), new Position(0, 11)), ""));
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 21), new Position(0, 21)), " Second"));
- MockLanguageServer.INSTANCE.setFormattingTextEdits(formattingTextEdits);
+ factory.withConfiguration((idx, server)-> {
+ server.setFormattingTextEdits(formattingTextEdits);
+ });
IFile file = TestUtils.createUniqueTestFile(project, "Formatting Other Text");
IEditorPart editor = TestUtils.openEditor(file);
@@ -79,12 +81,14 @@ public void testVersionSupportSuccess() throws Exception {
}
@Test
- public void testVersionedEditsFailsOnModification() throws Exception {
+ public void testVersionedEditsFailsOnModification(MockLanguageServerFactory factory) throws Exception {
final var formattingTextEdits = new ArrayList();
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 0), new Position(0, 1)), "MyF"));
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 10), new Position(0, 11)), ""));
formattingTextEdits.add(new TextEdit(new Range(new Position(0, 21), new Position(0, 21)), " Second"));
- MockLanguageServer.INSTANCE.setFormattingTextEdits(formattingTextEdits);
+ factory.withConfiguration((idx, server) -> {
+ server.setFormattingTextEdits(formattingTextEdits);
+ });
IFile file = TestUtils.createUniqueTestFile(project, "Formatting Other Text");
ITextViewer viewer = TestUtils.openTextViewer(file);
@@ -103,7 +107,7 @@ public void testVersionedEditsFailsOnModification() throws Exception {
VersionedEdits edits = result.join().get();
viewer.getDocument().replace(0, 0, "Hello");
- waitForAndAssertCondition(1_000, numberOfChangesIs(1));
+ waitForAndAssertCondition(1_000, numberOfChangesIs(1, factory.getServer()));
assertThrows(ConcurrentModificationException.class, () -> edits.apply());
}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/WorkspaceFoldersTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/WorkspaceFoldersTest.java
index 809e517fb..79c7c965b 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/WorkspaceFoldersTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/WorkspaceFoldersTest.java
@@ -28,33 +28,30 @@
import org.eclipse.lsp4e.test.utils.TestUtils;
import org.eclipse.lsp4e.test.utils.TestUtils.JobSynchronizer;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
+import org.eclipse.lsp4e.tests.mock.MockServerState;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.WorkspaceFoldersOptions;
import org.eclipse.lsp4j.WorkspaceServerCapabilities;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class WorkspaceFoldersTest extends AbstractTestWithProject {
- @BeforeEach
- public void setUp() {
- MockLanguageServer.INSTANCE.getWorkspaceService().getWorkspaceFoldersEvents().clear();
- }
-
@Test
- public void testRecycleLSAfterInitialProjectGotDeletedIfWorkspaceFolders() throws Exception {
+ public void testRecycleLSAfterInitialProjectGotDeletedIfWorkspaceFolders(MockLanguageServerFactory factory) throws Exception {
+ factory.withCapabilities(this::getServerCapabilities);
IFile testFile1 = TestUtils.createUniqueTestFile(project, "");
TestUtils.openEditor(testFile1);
Collection wrappers = LanguageServiceAccessor.getLSWrappers(testFile1, c -> true);
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 1);
LanguageServerWrapper wrapper1 = wrappers.iterator().next();
assertTrue(wrapper1.isActive());
UI.getActivePage().closeAllEditors(false);
- waitForAndAssertCondition(5_000, () -> !MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServer().getState() != MockServerState.RUNNING);
project.delete(true, true, new NullProgressMonitor());
@@ -63,7 +60,7 @@ public void testRecycleLSAfterInitialProjectGotDeletedIfWorkspaceFolders() throw
TestUtils.openEditor(testFile2);
wrappers = LanguageServiceAccessor.getLSWrappers(testFile2, c -> true);
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 2);
LanguageServerWrapper wrapper2 = wrappers.iterator().next();
assertTrue(wrapper2.isActive());
@@ -74,35 +71,37 @@ public void testRecycleLSAfterInitialProjectGotDeletedIfWorkspaceFolders() throw
}
@Test
- public void testPojectCreate() throws Exception {
+ public void testPojectCreate(MockLanguageServerFactory factory) throws Exception {
+ factory.withCapabilities(this::getServerCapabilities);
IFile testFile1 = TestUtils.createUniqueTestFile(project, "");
TestUtils.openEditor(testFile1);
Collection wrappers = LanguageServiceAccessor.getLSWrappers(testFile1, c -> true);
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 1);
ConnectDocumentToLanguageServerSetupParticipant.waitForAll();
LanguageServerWrapper wrapper1 = wrappers.iterator().next();
assertTrue(wrapper1.isActive());
UI.getActivePage().closeAllEditors(false);
- waitForAndAssertCondition(5_000, () -> !MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServer().getState() != MockServerState.RUNNING);
// test that the LS emitted a workspace-folder added event for our project
final var expected = Paths.get(project.getLocationURI());
- assertTrue(MockLanguageServer.INSTANCE.getWorkspaceService() //
+ assertTrue(factory.getServer().getWorkspaceService() //
.getWorkspaceFoldersEvents().stream() //
.flatMap(event -> event.getEvent().getAdded().stream()) //
.anyMatch(added -> Paths.get(URI.create(added.getUri())).equals(expected)));
}
@Test
- public void testProjectClose() throws Exception {
+ public void testProjectClose(MockLanguageServerFactory factory) throws Exception {
+ factory.withCapabilities(this::getServerCapabilities);
IFile testFile1 = TestUtils.createUniqueTestFile(project, "");
TestUtils.openEditor(testFile1);
LanguageServiceAccessor.getLSWrappers(testFile1, capabilities -> true).iterator().next();
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 1);
ConnectDocumentToLanguageServerSetupParticipant.waitForAll();
final var synchronizer = new JobSynchronizer();
project.close(synchronizer);
@@ -110,19 +109,20 @@ public void testProjectClose() throws Exception {
// test that the LS emitted a workspace-folder removal event for our project
final var expected = Paths.get(project.getLocationURI());
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.getWorkspaceService() //
+ waitForAndAssertCondition(5_000, () -> factory.getServer().getWorkspaceService() //
.getWorkspaceFoldersEvents().stream() //
.flatMap(evt -> evt.getEvent().getRemoved().stream()) //
.anyMatch(removed -> Paths.get(URI.create(removed.getUri())).equals(expected)));
}
@Test
- public void testProjectDelete() throws Exception {
+ public void testProjectDelete(MockLanguageServerFactory factory) throws Exception {
+ factory.withCapabilities(this::getServerCapabilities);
IFile testFile1 = TestUtils.createUniqueTestFile(project, "");
TestUtils.openEditor(testFile1);
Collection wrappers = LanguageServiceAccessor.getLSWrappers(testFile1, c -> true);
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 1);
ConnectDocumentToLanguageServerSetupParticipant.waitForAll();
LanguageServerWrapper wrapper1 = wrappers.iterator().next();
@@ -135,19 +135,20 @@ public void testProjectDelete() throws Exception {
synchronizer.await();
// test that the LS emitted a workspace-folder removal event for our project
- assertTrue(MockLanguageServer.INSTANCE.getWorkspaceService() //
+ assertTrue(factory.getServer().getWorkspaceService() //
.getWorkspaceFoldersEvents().stream() //
.flatMap(event -> event.getEvent().getRemoved().stream()) //
.anyMatch(removed -> Paths.get(URI.create(removed.getUri())).equals(expected)));
}
@Test
- public void testProjectReopen() throws Exception {
+ public void testProjectReopen(MockLanguageServerFactory factory) throws Exception {
+ factory.withCapabilities(this::getServerCapabilities);
IFile testFile1 = TestUtils.createUniqueTestFile(project, "");
TestUtils.openEditor(testFile1);
LanguageServiceAccessor.getLSWrappers(testFile1, capabilities -> true).iterator().next();
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.isRunning());
+ waitForAndAssertCondition(5_000, () -> factory.getServerCount() == 1);
ConnectDocumentToLanguageServerSetupParticipant.waitForAll();
final var synchronizer = new JobSynchronizer();
@@ -164,17 +165,15 @@ public void testProjectReopen() throws Exception {
// test that the LS emitted a workspace-folder added event for our project
final var expected = Paths.get(project.getLocationURI());
- waitForAndAssertCondition(5_000, () -> MockLanguageServer.INSTANCE.getWorkspaceService() //
+ waitForAndAssertCondition(5_000, () -> factory.getServer().getWorkspaceService() //
.getWorkspaceFoldersEvents().stream() //
.flatMap(evt -> evt.getEvent().getAdded().stream()) //
.anyMatch(added -> Paths.get(URI.create(added.getUri())).equals(expected)));
}
- @Override
public ServerCapabilities getServerCapabilities() {
// Enable workspace folders on the mock server (for this test only)
final ServerCapabilities base = MockLanguageServer.defaultServerCapabilities();
-
final var wsc = new WorkspaceServerCapabilities();
final var wso = new WorkspaceFoldersOptions();
wso.setSupported(true);
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyLabelProviderTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyLabelProviderTest.java
index 47c00f723..6f41407fe 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyLabelProviderTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyLabelProviderTest.java
@@ -16,13 +16,12 @@
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.lsp4e.callhierarchy.CallHierarchyLabelProvider;
import org.eclipse.lsp4e.callhierarchy.CallHierarchyViewTreeNode;
-import org.eclipse.lsp4e.test.utils.AbstractTest;
import org.eclipse.lsp4j.CallHierarchyItem;
import org.eclipse.swt.custom.StyleRange;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-public class CallHierarchyLabelProviderTest extends AbstractTest {
+public class CallHierarchyLabelProviderTest {
private static CallHierarchyLabelProvider labelProvider = null;
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyViewContentTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyViewContentTest.java
index d38d33efb..e6aaf0d3c 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyViewContentTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/callhierarchy/CallHierarchyViewContentTest.java
@@ -28,15 +28,13 @@
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4e.ui.views.HierarchyViewInput;
-import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
/**
* UI-level test that opens a file, initializes Call Hierarchy and verifies that
@@ -44,20 +42,15 @@
*/
public class CallHierarchyViewContentTest extends AbstractTestWithProject {
- @Override
- @BeforeEach
- public void setUpProject(TestInfo testInfo) throws Exception {
- super.setUpProject(testInfo);
- // Ensure the mock server advertises callHierarchyProvider
- MockLanguageServer.reset(() -> {
- ServerCapabilities caps = MockLanguageServer.defaultServerCapabilities();
+ @Test
+ public void testCallHierarchyShowsCalleeAndCaller(MockLanguageServerFactory factory) throws Exception {
+ factory.withCapabilities(() -> {
+ var caps = MockLanguageServer.defaultServerCapabilities();
+ // Ensure the mock server advertises callHierarchyProvider
caps.setCallHierarchyProvider(Boolean.TRUE);
return caps;
});
- }
-
- @Test
- public void testCallHierarchyShowsCalleeAndCaller() throws Exception {
+
IProject p = project;
IFile file = TestUtils.createUniqueTestFile(p, "// mock content for call hierarchy\nfunction f(){}\n");
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java
index ba901586f..a916e434d 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/codeactions/CodeActionTests.java
@@ -31,7 +31,7 @@
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.NoErrorLoggedRule;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.Diagnostic;
@@ -60,20 +60,24 @@ public class CodeActionTests extends AbstractTestWithProject {
public final @RegisterExtension NoErrorLoggedRule noErrorLoggedRule = new NoErrorLoggedRule();
@Test
- public void testCodeActionsClientCommandForTextEdit() throws CoreException {
+ public void testCodeActionsClientCommandForTextEdit(MockLanguageServerFactory factory) throws CoreException {
+ factory.withConfiguration((idx, server)-> {
+ server.setCodeActions(List.of(Either.forLeft(new Command(
+ "fixme",
+ "edit",
+ List.of(
+ new TextEdit(
+ new Range(new Position(0, 0), new Position(0, 5)),
+ "fixed"))
+ )
+ )
+ ));
+ server.setDiagnostics(List.of(
+ new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ });
+
IFile f = TestUtils.createUniqueTestFile(project, "error");
- MockLanguageServer.INSTANCE.setCodeActions(List.of(Either.forLeft(new Command(
- "fixme",
- "edit",
- List.of(
- new TextEdit(
- new Range(new Position(0, 0), new Position(0, 5)),
- "fixed"))
- )
- )
- ));
- MockLanguageServer.INSTANCE.setDiagnostics(List.of(
- new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+
final var editor = (AbstractTextEditor)TestUtils.openEditor(f);
try {
IMarker m = assertDiagnostics(f, "error", "fixme");
@@ -84,20 +88,23 @@ public void testCodeActionsClientCommandForTextEdit() throws CoreException {
}
@Test
- public void testCodeActionsClientCommandForWorkspaceEdit() throws CoreException {
+ public void testCodeActionsClientCommandForWorkspaceEdit(MockLanguageServerFactory factory) throws CoreException {
IFile f = TestUtils.createUniqueTestFile(project, "error");
+ factory.withConfiguration((idx, server)-> {
+ final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
+ final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
+ server.setCodeActions(List
+ .of(Either.forLeft(new Command(
+ "fixme",
+ "edit",
+ List.of(wEdit))
+ )
+ ));
+ server.setDiagnostics(List.of(
+ new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ });
+
- final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
- final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
- MockLanguageServer.INSTANCE.setCodeActions(List
- .of(Either.forLeft(new Command(
- "fixme",
- "edit",
- List.of(wEdit))
- )
- ));
- MockLanguageServer.INSTANCE.setDiagnostics(List.of(
- new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
final var editor = (AbstractTextEditor)TestUtils.openEditor(f);
IMarker m = assertDiagnostics(f, "error", "fixme");
@@ -113,19 +120,21 @@ private void checkCompletionContent(final Table completionProposalList) {
}
@Test
- public void testCodeActionsQuickAssist() throws CoreException {
- MockLanguageServer.reset();
+ public void testCodeActionsQuickAssist(MockLanguageServerFactory factory) throws CoreException {
IFile f = TestUtils.createUniqueTestFile(project, "error");
- final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
- final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
- MockLanguageServer.INSTANCE.setCodeActions(List
- .of(Either.forLeft(new Command(
- "fixme",
- "edit",
- List.of(wEdit))
- )
- ));
+ factory.withConfiguration((idx, server)-> {
+ final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
+ final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
+ server.setCodeActions(List
+ .of(Either.forLeft(new Command(
+ "fixme",
+ "edit",
+ List.of(wEdit))
+ )
+ ));
+ });
+
final var editor = (AbstractTextEditor)TestUtils.openEditor(f);
final Set beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
editor.selectAndReveal(3, 0);
@@ -138,20 +147,22 @@ public void testCodeActionsQuickAssist() throws CoreException {
}
@Test
- public void testSlowCodeActionsQuickAssist() throws CoreException {
- MockLanguageServer.reset();
+ public void testSlowCodeActionsQuickAssist(MockLanguageServerFactory factory) throws CoreException {
IFile f = TestUtils.createUniqueTestFile(project, "error");
- final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
- final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
- MockLanguageServer.INSTANCE.setCodeActions(List
- .of(Either.forLeft(new Command(
- "fixme",
- "edit",
- List.of(wEdit))
- )
- ));
- MockLanguageServer.INSTANCE.setTimeToProceedQueries(1000);
+ factory.withConfiguration((idx, server)-> {
+ final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
+ final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
+ server.setCodeActions(List
+ .of(Either.forLeft(new Command(
+ "fixme",
+ "edit",
+ List.of(wEdit))
+ )
+ ));
+ server.setTimeToProceedQueries(1000);
+ });
+
final var editor = (AbstractTextEditor)TestUtils.openEditor(f);
final Set beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
editor.selectAndReveal(3, 0);
@@ -166,27 +177,29 @@ public void testSlowCodeActionsQuickAssist() throws CoreException {
final Table completionProposalList = TestUtils.findCompletionSelectionControl(completionShell);
return completionProposalList.getItemCount() == 1 && "fixme".equals(completionProposalList.getItem(0).getText());
});
- assertEquals(1, MockLanguageServer.INSTANCE.getTextDocumentService().codeActionRequests);
+ assertEquals(1, factory.getServer().getTextDocumentService().codeActionRequests);
}
@Test
- public void testCodeActionLiteralWorkspaceEdit() throws CoreException {
+ public void testCodeActionLiteralWorkspaceEdit(MockLanguageServerFactory factory) throws CoreException {
IFile f = TestUtils.createUniqueTestFile(project, "error");
+ factory.withConfiguration((idx, server)-> {
+ final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
+ final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
+ final var codeAction = new CodeAction("fixme");
+ codeAction.setEdit(wEdit);
+ server.setCodeActions(List.of(Either.forRight(codeAction)));
+ server.setDiagnostics(List.of(
+ new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ });
- final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
- final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
- final var codeAction = new CodeAction("fixme");
- codeAction.setEdit(wEdit);
- MockLanguageServer.INSTANCE.setCodeActions(List.of(Either.forRight(codeAction)));
- MockLanguageServer.INSTANCE.setDiagnostics(List.of(
- new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
final var editor = (AbstractTextEditor)TestUtils.openEditor(f);
IMarker m = assertDiagnostics(f, "error", "fixme");
assertResolution(editor, m, "fixed");
}
@Test
- public void testNoCodeActionOnReadOnlySource() throws CoreException {
+ public void testNoCodeActionOnReadOnlySource(MockLanguageServerFactory factory) throws CoreException {
IFile f = TestUtils.createUniqueTestFile(project, "error");
f.setResourceAttributes(new ResourceAttributes() {
@Override
@@ -195,47 +208,53 @@ public boolean isReadOnly() {
}
});
- final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
- final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
- final var codeAction = new CodeAction("fixme");
- codeAction.setEdit(wEdit);
- MockLanguageServer.INSTANCE.setCodeActions(List.of(Either.forRight(codeAction)));
- MockLanguageServer.INSTANCE.setDiagnostics(List.of(
- new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ factory.withConfiguration((idx, server)-> {
+ final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
+ final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
+ final var codeAction = new CodeAction("fixme");
+ codeAction.setEdit(wEdit);
+ server.setCodeActions(List.of(Either.forRight(codeAction)));
+ server.setDiagnostics(List.of(
+ new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ });
TestUtils.openEditor(f);
assertDiagnostics(f, "error", "fixme", false);
}
@Test
- public void testCodeActionLiteralWithClientCommand() throws CoreException {
+ public void testCodeActionLiteralWithClientCommand(MockLanguageServerFactory factory) throws CoreException {
IFile f = TestUtils.createUniqueTestFile(project, "error");
- final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
- final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
- final var codeAction = new CodeAction("fixme");
- codeAction.setCommand(new Command("editCommand", "mockEditCommand", List.of(wEdit)));
- MockLanguageServer.INSTANCE.setCodeActions(List.of(Either.forRight(codeAction)));
- MockLanguageServer.INSTANCE.setDiagnostics(List.of(
- new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ factory.withConfiguration((idx, server)-> {
+ final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
+ final var wEdit = new WorkspaceEdit(Collections.singletonMap(f.getLocationURI().toString(), List.of(tEdit)));
+ final var codeAction = new CodeAction("fixme");
+ codeAction.setCommand(new Command("editCommand", "mockEditCommand", List.of(wEdit)));
+ server.setCodeActions(List.of(Either.forRight(codeAction)));
+ server.setDiagnostics(List.of(
+ new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ });
final var editor = (AbstractTextEditor)TestUtils.openEditor(f);
IMarker m = assertDiagnostics(f, "error", "fixme");
assertResolution(editor, m, "fixed");
}
@Test
- public void testCodeActionWorkspaceEditlWithDifferentURI() throws CoreException {
+ public void testCodeActionWorkspaceEditlWithDifferentURI(MockLanguageServerFactory factory) throws CoreException {
IFile sourceFile = TestUtils.createUniqueTestFile(project, "error");
IFile targetFile = TestUtils.createUniqueTestFile(project, "fixme");
- // create a diagnostic on the sourceFile with a code action
- // that changes the targetFile
- final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
- final var wEdit = new WorkspaceEdit(Collections.singletonMap(targetFile.getLocationURI().toString(), List.of(tEdit)));
- final var codeAction = new CodeAction("fixme");
- codeAction.setCommand(new Command("editCommand", "mockEditCommand", List.of(wEdit)));
- MockLanguageServer.INSTANCE.setCodeActions(List.of(Either.forRight(codeAction)));
- MockLanguageServer.INSTANCE.setDiagnostics(List.of(
- new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ factory.withConfiguration((idx, server)-> {
+ // create a diagnostic on the sourceFile with a code action
+ // that changes the targetFile
+ final var tEdit = new TextEdit(new Range(new Position(0, 0), new Position(0, 5)), "fixed");
+ final var wEdit = new WorkspaceEdit(Collections.singletonMap(targetFile.getLocationURI().toString(), List.of(tEdit)));
+ final var codeAction = new CodeAction("fixme");
+ codeAction.setCommand(new Command("editCommand", "mockEditCommand", List.of(wEdit)));
+ server.setCodeActions(List.of(Either.forRight(codeAction)));
+ server.setDiagnostics(List.of(
+ new Diagnostic(new Range(new Position(0, 0), new Position(0, 5)), "error", DiagnosticSeverity.Error, null)));
+ });
TestUtils.openEditor(sourceFile);
IMarker m = assertDiagnostics(sourceFile, "error", "fixme");
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/color/ColorTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/color/ColorTest.java
index d4136eef4..b09423179 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/color/ColorTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/color/ColorTest.java
@@ -23,6 +23,7 @@
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.lsp4j.Color;
import org.eclipse.lsp4j.ColorInformation;
@@ -35,29 +36,26 @@
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.ide.IDE;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
public class ColorTest extends AbstractTestWithProject {
- private RGB color;
-
- @BeforeEach
- public void setUp() {
- color = new RGB(56, 78, 90); // a color that's not likely used anywhere else
- MockLanguageServer.INSTANCE.getTextDocumentService().setDocumentColors(List.of(new ColorInformation(new Range(new Position(0, 0), new Position(0, 1)), new Color(color.red / 255., color.green / 255., color.blue / 255., 255))));
- }
+ // a color that's not likely used anywhere else
+ private RGB color = new RGB(56, 78, 90);
@Test
- public void testColorProvider() throws Exception {
+ public void testColorProvider(MockLanguageServerFactory factory) throws Exception {
+ factory.withConfiguration(this::configureColors);
+
ITextViewer viewer = TestUtils.openTextViewer(TestUtils.createUniqueTestFile(project, "\u2588\u2588\u2588\u2588\u2588"));
StyledText widget = viewer.getTextWidget();
waitForAndAssertCondition(3_000, widget.getDisplay(), () -> containsColor(widget, color, 10));
}
@Test
- public void testColorProviderExternalFile(@TempDir Path tempDir) throws Exception {
+ public void testColorProviderExternalFile(MockLanguageServerFactory factory, @TempDir Path tempDir) throws Exception {
+ factory.withConfiguration(this::configureColors);
Path file = Files.write(tempDir.resolve("testColorProviderExternalFile.lspt"), "\u2588\u2588\u2588\u2588\u2588".getBytes());
ITextViewer viewer = LSPEclipseUtils.getTextViewer(IDE.openEditorOnFileStore(UI.getActivePage(), EFS.getStore(file.toUri())));
StyledText widget = viewer.getTextWidget();
@@ -100,4 +98,10 @@ private static int distance(RGB from, RGB to) {
return (int) Math.sqrt((dR * dR + dG * dG + dB * dB) / 3);
}
+
+ private void configureColors(Integer idx, MockLanguageServer server) {
+ server.getTextDocumentService()
+ .setDocumentColors(List.of(new ColorInformation(new Range(new Position(0, 0), new Position(0, 1)),
+ new Color(color.red / 255., color.green / 255., color.blue / 255., 255))));
+ }
}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/commands/DynamicRegistrationTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/commands/DynamicRegistrationTest.java
index af2e90765..0dc0e5d81 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/commands/DynamicRegistrationTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/commands/DynamicRegistrationTest.java
@@ -12,7 +12,6 @@
package org.eclipse.lsp4e.test.commands;
import static org.eclipse.lsp4e.test.utils.TestUtils.waitForCondition;
-import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -30,6 +29,7 @@
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4e.tests.mock.MockWorkspaceService;
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
import org.eclipse.lsp4j.ExecuteCommandOptions;
@@ -42,7 +42,6 @@
import org.eclipse.lsp4j.WorkspaceFoldersOptions;
import org.eclipse.lsp4j.WorkspaceServerCapabilities;
import org.eclipse.lsp4j.services.LanguageClient;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class DynamicRegistrationTest extends AbstractTestWithProject {
@@ -51,43 +50,45 @@ public class DynamicRegistrationTest extends AbstractTestWithProject {
private static final String WORKSPACE_DID_CHANGE_FOLDERS = "workspace/didChangeWorkspaceFolders";
private static final String WORKSPACE_DID_CHANGE_WATCHED_FILES = "workspace/didChangeWatchedFiles";
- @BeforeEach
- public void setUp() throws Exception {
+ @Test
+ public void testCommandRegistration(MockLanguageServerFactory factory) throws Exception {
IFile testFile = TestUtils.createFile(project, "shouldUseExtension.lspt", "");
-
// Make sure mock language server is created...
IDocument document = LSPEclipseUtils.getDocument(testFile);
assertNotNull(document);
LanguageServers.forDocument(document).anyMatching();
-
- waitForCondition(5_000, () -> !MockLanguageServer.INSTANCE.getRemoteProxies().isEmpty());
- getMockClient();
- }
-
- @Test
- public void testCommandRegistration() throws Exception {
+
+ waitForCondition(5_000, () -> !factory.getServers().isEmpty());
+
assertTrue(LanguageServiceAccessor.hasActiveLanguageServers(c -> true));
assertFalse(LanguageServiceAccessor.hasActiveLanguageServers(handlesCommand("test.command")));
- UUID registration = registerCommands("test.command", "test.command.2");
+ UUID registration = registerCommands(factory.getServer(), "test.command", "test.command.2");
try {
assertTrue(LanguageServiceAccessor.hasActiveLanguageServers(handlesCommand("test.command")));
assertTrue(LanguageServiceAccessor.hasActiveLanguageServers(handlesCommand("test.command.2")));
} finally {
- unregister(registration, WORKSPACE_EXECUTE_COMMAND);
+ unregister(registration, WORKSPACE_EXECUTE_COMMAND, factory.getServer());
}
assertFalse(LanguageServiceAccessor.hasActiveLanguageServers(handlesCommand("test.command")));
assertFalse(LanguageServiceAccessor.hasActiveLanguageServers(handlesCommand("test.command.2")));
}
@Test
- public void testWatchedFilesRegistrationAndNotification() throws Exception {
+ public void testWatchedFilesRegistrationAndNotification(MockLanguageServerFactory factory) throws Exception {
+ IFile testFile = TestUtils.createFile(project, "shouldUseExtension.lspt", "");
+ // Make sure mock language server is created...
+ IDocument document = LSPEclipseUtils.getDocument(testFile);
+ assertNotNull(document);
+ LanguageServers.forDocument(document).anyMatching();
+
+ waitForCondition(5_000, () -> !factory.getServers().isEmpty());
assertTrue(LanguageServiceAccessor.hasActiveLanguageServers(c -> true));
- UUID registration = registerWatchedFiles();
+ UUID registration = registerWatchedFiles(factory.getServer());
try {
- MockWorkspaceService workspaceService = MockLanguageServer.INSTANCE.getWorkspaceService();
+ MockWorkspaceService workspaceService = factory.getServer().getWorkspaceService();
TestUtils.createFile(project, "watched.txt", "");
TestUtils.createFile(project, "unwatched.bin", "");
@@ -101,21 +102,29 @@ public void testWatchedFilesRegistrationAndNotification() throws Exception {
assertFalse(params.getChanges().stream()
.anyMatch(ev -> ev.getUri().endsWith("unwatched.bin")));
} finally {
- unregister(registration, WORKSPACE_DID_CHANGE_WATCHED_FILES);
+ unregister(registration, WORKSPACE_DID_CHANGE_WATCHED_FILES, factory.getServer());
}
}
@Test
- public void testWorkspaceFoldersRegistration() throws Exception {
+ public void testWorkspaceFoldersRegistration(MockLanguageServerFactory factory) throws Exception {
+ IFile testFile = TestUtils.createFile(project, "shouldUseExtension.lspt", "");
+ // Make sure mock language server is created...
+ IDocument document = LSPEclipseUtils.getDocument(testFile);
+ assertNotNull(document);
+ LanguageServers.forDocument(document).anyMatching();
+
+ waitForCondition(5_000, () -> !factory.getServers().isEmpty());
+
assertTrue(LanguageServiceAccessor.hasActiveLanguageServers(c -> true));
assertFalse(LanguageServiceAccessor.hasActiveLanguageServers(c -> hasWorkspaceFolderSupport(c)));
- UUID registration = registerWorkspaceFolders();
+ UUID registration = registerWorkspaceFolders(factory.getServer());
try {
assertTrue(LanguageServiceAccessor.hasActiveLanguageServers(c -> hasWorkspaceFolderSupport(c)));
} finally {
- unregister(registration, WORKSPACE_DID_CHANGE_FOLDERS);
+ unregister(registration, WORKSPACE_DID_CHANGE_FOLDERS, factory.getServer());
}
assertFalse(LanguageServiceAccessor.hasActiveLanguageServers(c -> hasWorkspaceFolderSupport(c)));
assertTrue(LanguageServiceAccessor.hasActiveLanguageServers(c -> !hasWorkspaceFolderSupport(c)));
@@ -123,16 +132,16 @@ public void testWorkspaceFoldersRegistration() throws Exception {
//////////////////////////////////////////////////////////////////////////////////
- private void unregister(UUID registration, String method) throws Exception {
- LanguageClient client = getMockClient();
+ private void unregister(UUID registration, String method, MockLanguageServer server) throws Exception {
+ LanguageClient client = server.getRemoteProxy();
final var unregistration = new Unregistration(registration.toString(), method);
client.unregisterCapability(new UnregistrationParams(List.of(unregistration)))
.get(1, TimeUnit.SECONDS);
}
- private UUID registerWatchedFiles() throws Exception {
+ private UUID registerWatchedFiles(MockLanguageServer server) throws Exception {
var id = UUID.randomUUID();
- LanguageClient client = getMockClient();
+ LanguageClient client = server.getRemoteProxy();
final var registration = new Registration();
registration.setId(id.toString());
registration.setMethod(WORKSPACE_DID_CHANGE_WATCHED_FILES);
@@ -146,9 +155,9 @@ private UUID registerWatchedFiles() throws Exception {
return id;
}
- private UUID registerWorkspaceFolders() throws Exception {
+ private UUID registerWorkspaceFolders(MockLanguageServer server) throws Exception {
UUID id = UUID.randomUUID();
- LanguageClient client = getMockClient();
+ LanguageClient client = server.getRemoteProxy();
final var registration = new Registration();
registration.setId(id.toString());
registration.setMethod(WORKSPACE_DID_CHANGE_FOLDERS);
@@ -157,9 +166,9 @@ private UUID registerWorkspaceFolders() throws Exception {
return id;
}
- private UUID registerCommands(String... command) throws Exception {
+ private UUID registerCommands(MockLanguageServer server, String... command) throws Exception {
UUID id = UUID.randomUUID();
- LanguageClient client = getMockClient();
+ LanguageClient client = server.getRemoteProxy();
final var registration = new Registration();
registration.setId(id.toString());
registration.setMethod(WORKSPACE_EXECUTE_COMMAND);
@@ -168,12 +177,6 @@ private UUID registerCommands(String... command) throws Exception {
return id;
}
- private LanguageClient getMockClient() {
- List proxies = MockLanguageServer.INSTANCE.getRemoteProxies();
- assertEquals(1, proxies.size());
- return proxies.get(0);
- }
-
private Predicate handlesCommand(String command) {
return cap -> {
ExecuteCommandOptions commandProvider = cap.getExecuteCommandProvider();
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/AbstractCompletionTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/AbstractCompletionTest.java
index 8d29b7961..54b7b08d3 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/AbstractCompletionTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/AbstractCompletionTest.java
@@ -22,7 +22,7 @@
import org.eclipse.lsp4e.operations.completion.LSContentAssistProcessor;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.CompletionList;
@@ -74,19 +74,21 @@ protected CompletionItem createCompletionItemWithInsertReplace(String label, Com
}
protected void confirmCompletionResults(String[] completions, String content, Integer cursorIndexInContent,
- String[] expectedOrder) throws CoreException {
+ String[] expectedOrder, MockLanguageServerFactory factory) throws CoreException {
final var range = new Range(new Position(0, 0), new Position(0, cursorIndexInContent));
final var items = new ArrayList();
for (String string : completions) {
items.add(createCompletionItem(string, CompletionItemKind.Class, range));
}
- confirmCompletionResults(items, content, cursorIndexInContent, expectedOrder);
+ confirmCompletionResults(items, content, cursorIndexInContent, expectedOrder, factory);
}
protected void confirmCompletionResults(List completions, String content,
- Integer cursorIndexInContent, String[] expectedOrder) throws CoreException {
-
- MockLanguageServer.INSTANCE.setCompletionList(new CompletionList(false, completions));
+ Integer cursorIndexInContent, String[] expectedOrder, MockLanguageServerFactory factory) throws CoreException {
+ factory.withConfiguration((idx, server) -> {
+ server.setCompletionList(new CompletionList(false, completions));
+ });
+
ITextViewer viewer = TestUtils.openTextViewer(TestUtils.createUniqueTestFile(project, content));
ICompletionProposal[] proposals = contentAssistProcessor.computeCompletionProposals(viewer,
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/CompleteCompletionTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/CompleteCompletionTest.java
index e9220780a..5a09f24be 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/CompleteCompletionTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/completion/CompleteCompletionTest.java
@@ -42,8 +42,8 @@
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.operations.completion.LSCompletionProposal;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockConnectionProvider;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.CompletionItem;
@@ -77,10 +77,13 @@ public class CompleteCompletionTest extends AbstractCompletionTest {
* file-specific LS already associated is something we want to support.
*/
@Test
- public void testAssistForUnknownButConnectedType() throws CoreException {
+ public void testAssistForUnknownButConnectedType(MockLanguageServerFactory factory) throws CoreException {
final var items = new ArrayList();
items.add(createCompletionItem("FirstClass", CompletionItemKind.Class));
- MockLanguageServer.INSTANCE.setCompletionList(new CompletionList(false, items));
+
+ factory.withConfiguration((idx, server) -> {
+ server.setCompletionList(new CompletionList(false, items));
+ });
IFile testFile = TestUtils.createUniqueTestFileOfUnknownType(project, "");
ITextViewer viewer = TestUtils.openTextViewer(testFile);
@@ -103,10 +106,12 @@ public void testAssistForUnknownButConnectedType() throws CoreException {
}
@Test
- public void testNoPrefix() throws CoreException {
+ public void testNoPrefix(MockLanguageServerFactory factory) throws CoreException {
final var items = new ArrayList();
items.add(createCompletionItem("FirstClass", CompletionItemKind.Class));
- MockLanguageServer.INSTANCE.setCompletionList(new CompletionList(false, items));
+ factory.withConfiguration((idx, server) -> {
+ server.setCompletionList(new CompletionList(false, items));
+ });
IFile testFile = TestUtils.createUniqueTestFile(project, "");
ITextViewer viewer = TestUtils.openTextViewer(testFile);
@@ -120,11 +125,13 @@ public void testNoPrefix() throws CoreException {
}
@Test
- public void testPrefix() throws CoreException {
+ public void testPrefix(MockLanguageServerFactory factory) throws CoreException {
final var items = new ArrayList();
items.add(createCompletionItem("FirstClass", CompletionItemKind.Class));
items.add(createCompletionItem("SecondClass", CompletionItemKind.Class));
- MockLanguageServer.INSTANCE.setCompletionList(new CompletionList(false, items));
+ factory.withConfiguration((idx, server) -> {
+ server.setCompletionList(new CompletionList(false, items));
+ });
final var content = "First";
ITextViewer viewer = TestUtils.openTextViewer(TestUtils.createUniqueTestFile(project, content));
@@ -142,13 +149,15 @@ public void testPrefix() throws CoreException {
* The test will use a Command that shall be handled by the langauge server.
*/
@Test
- public void testCommandExecution() throws CoreException, InterruptedException, ExecutionException, TimeoutException {
+ public void testCommandExecution(MockLanguageServerFactory factory) throws CoreException, InterruptedException, ExecutionException, TimeoutException {
CompletionItem completionItem = createCompletionItem("Bla", CompletionItemKind.Class);
final var expectedParameter = "command execution parameter";
List
*/
@Test
- void testInlineLinkedEditingSameFile() throws Exception {
+ void testInlineLinkedEditingSameFile(MockLanguageServerFactory factory) throws Exception {
// Ensure inline rename is enabled for this test
InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID).putBoolean("org.eclipse.lsp4e.inlineRename", //$NON-NLS-1$
true);
@@ -97,7 +98,9 @@ void testInlineLinkedEditingSameFile() throws Exception {
DocumentHighlightKind.Read),
new DocumentHighlight(new Range(new Position(0, 0), new Position(0, idLength)),
DocumentHighlightKind.Text)));
- MockLanguageServer.INSTANCE.setDocumentHighlights(highlights);
+ factory.withConfiguration((idx, server)-> {
+ server.setDocumentHighlights(highlights);
+ });
// Call the internal helper directly via reflection to avoid depending on
// UI/command wiring
@@ -128,7 +131,7 @@ void testInlineLinkedEditingSameFile() throws Exception {
*
*/
@Test
- void testInlineRenameEndToEndSameFile() throws Exception {
+ void testInlineRenameEndToEndSameFile(MockLanguageServerFactory factory) throws Exception {
// Prepare a simple document with two occurrences of the same identifier
var content = "compute();\ncompute();";
IFile file = TestUtils.createUniqueTestFile(project, content);
@@ -147,7 +150,6 @@ void testInlineRenameEndToEndSameFile() throws Exception {
Position secondPos = LSPEclipseUtils.toPosition(secondOffset, document);
var prepareRange = new Range(firstPos, new Position(firstPos.getLine(), firstPos.getCharacter() + idLength));
- MockLanguageServer.INSTANCE.getTextDocumentService().setPrepareRenameResult(Either.forLeft(prepareRange));
// WorkspaceEdit returned by textDocument/rename: both occurrences updated to
// typedName.
@@ -162,7 +164,10 @@ void testInlineRenameEndToEndSameFile() throws Exception {
new TextEdit(
new Range(secondPos, new Position(secondPos.getLine(), secondPos.getCharacter() + idLength)),
typedName)));
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(new WorkspaceEdit(edits));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setPrepareRenameResult(Either.forLeft(prepareRange));
+ server.getTextDocumentService().setRenameEdit(new WorkspaceEdit(edits));
+ });
// Open a viewer so that the document is wired to a text viewer like in real
// usage
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/rename/RenameTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/rename/RenameTest.java
index 50bbff04c..7091c2d05 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/rename/RenameTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/rename/RenameTest.java
@@ -46,7 +46,7 @@
import org.eclipse.lsp4e.operations.rename.LSPRenameProcessor;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
@@ -84,35 +84,34 @@ public void testRenameHandlerEnablement() throws Exception {
}
@Test
- public void testAsyncRenameHandlerEnablement() throws Exception {
+ public void testAsyncRenameHandlerEnablement(MockLanguageServerFactory factory) throws Exception {
final int delay = 4_000;
// this fixed value is not really an optimal solution, since it depends on the following things
// to happen within that time frame. Should maybe re-work this in the future towards a more
// precise way of steering the execution from the test here
- MockLanguageServer.INSTANCE.setTimeToProceedQueries(delay);
+ factory.withConfiguration((idx, server)-> {
+ server.setTimeToProceedQueries(delay);
+ });
- try {
- IFile file = TestUtils.createUniqueTestFile(project, "old");
- final var editor = (ITextEditor) TestUtils.openEditor(file);
+ IFile file = TestUtils.createUniqueTestFile(project, "old");
+ final var editor = (ITextEditor) TestUtils.openEditor(file);
- ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
- Command command = commandService.getCommand(IWorkbenchCommandConstants.FILE_RENAME);
- assertFalse(command.isEnabled());
+ ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
+ Command command = commandService.getCommand(IWorkbenchCommandConstants.FILE_RENAME);
+ assertFalse(command.isEnabled());
- editor.selectAndReveal(1, 0);
+ editor.selectAndReveal(1, 0);
- waitForAndAssertCondition(2 * delay, command::isEnabled);
- assertTrue(command.isHandled());
- } finally {
- // Put back so shutdown doesn't time out
- MockLanguageServer.INSTANCE.setTimeToProceedQueries(0);
- }
+ waitForAndAssertCondition(2 * delay, command::isEnabled);
+ assertTrue(command.isHandled());
}
@Test
- public void testRenameRefactoring() throws Exception {
+ public void testRenameRefactoring(MockLanguageServerFactory factory) throws Exception {
IFile file = TestUtils.createUniqueTestFile(project, "old");
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ });
IDocument document = LSPEclipseUtils.getDocument(file);
assertNotNull(document);
final var processor = new LSPRenameProcessor(document, 0);
@@ -128,9 +127,11 @@ public void testRenameRefactoring() throws Exception {
}
@Test
- public void testPrepareRenameRefactoring() throws Exception {
+ public void testPrepareRenameRefactoring(MockLanguageServerFactory factory) throws Exception {
IFile file = TestUtils.createUniqueTestFile(project, "old");
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ });
IDocument document = LSPEclipseUtils.getDocument(file);
assertNotNull(document);
final var processor = new LSPRenameProcessor(document, 0);
@@ -146,10 +147,12 @@ public void testPrepareRenameRefactoring() throws Exception {
}
@Test
- public void testPrepareRenameRefactoringError() throws Exception {
+ public void testPrepareRenameRefactoringError(MockLanguageServerFactory factory) throws Exception {
IFile file = TestUtils.createUniqueTestFile(project, "old");
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
- MockLanguageServer.INSTANCE.getTextDocumentService().setPrepareRenameResult(null);
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ server.getTextDocumentService().setPrepareRenameResult(null);
+ });
IDocument document = LSPEclipseUtils.getDocument(file);
assertNotNull(document);
final var processor = new LSPRenameProcessor(document, 0);
@@ -165,10 +168,11 @@ public void testPrepareRenameRefactoringError() throws Exception {
}
@Test
- public void testRenameRefactoringExternalFile(@TempDir Path tempDir) throws Exception {
+ public void testRenameRefactoringExternalFile(@TempDir Path tempDir, MockLanguageServerFactory factory) throws Exception {
Path file = Files.createFile(tempDir.resolve("testPerformOperationExternalFile.lspt"));
-
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(file.toUri()));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(file.toUri()));
+ });
IFileStore store = EFS.getStore(file.toUri());
ITextFileBufferManager manager = ITextFileBufferManager.DEFAULT;
try {
@@ -191,14 +195,16 @@ public void testRenameRefactoringExternalFile(@TempDir Path tempDir) throws Exce
}
@Test
- public void testRenameChangeAlsoExternalFile(@TempDir Path tempDir) throws Exception {
+ public void testRenameChangeAlsoExternalFile(@TempDir Path tempDir, MockLanguageServerFactory factory) throws Exception {
IFile workspaceFile = TestUtils.createUniqueTestFile(project, "old");
Path externalFile = Files.writeString(tempDir.resolve("testRenameChangeAlsoExternalFile.lspt"), "old");
final var edits = new HashMap>(2, 1.f);
edits.put(LSPEclipseUtils.toUri(workspaceFile).toString(), List.of(new TextEdit(new Range(new Position(0, 0), new Position(0, 3)), "new")));
edits.put(LSPEclipseUtils.toUri(externalFile.toFile()).toString(), List.of(new TextEdit(new Range(new Position(0, 0), new Position(0, 3)), "new")));
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(new WorkspaceEdit(edits));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(new WorkspaceEdit(edits));
+ });
IDocument document = LSPEclipseUtils.getDocument(workspaceFile);
assertNotNull(document);
final var processor = new LSPRenameProcessor(document, 0);
@@ -215,12 +221,14 @@ public void testRenameChangeAlsoExternalFile(@TempDir Path tempDir) throws Excep
}
@Test
- public void testRenameHandlerExecution() throws Exception {
+ public void testRenameHandlerExecution(MockLanguageServerFactory factory) throws Exception {
// This test expects the classic dialog-based rename, so disable inline mode
InstanceScope.INSTANCE.getNode(LanguageServerPlugin.PLUGIN_ID)
.putBoolean("org.eclipse.lsp4e.inlineRename", false); //$NON-NLS-1$
IFile file = TestUtils.createUniqueTestFile(project, "old");
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ });
final var editor = (ITextEditor) TestUtils.openEditor(file);
editor.selectAndReveal(1, 0);
ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
@@ -259,9 +267,11 @@ public void testRenameHandlerExecution() throws Exception {
}
@Test
- public void testPlaceholderUsingPlaceholderFromPrepareRenameResult() throws Exception {
+ public void testPlaceholderUsingPlaceholderFromPrepareRenameResult(MockLanguageServerFactory factory) throws Exception {
IFile file = TestUtils.createUniqueTestFile(project, "old");
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ });
IDocument document = LSPEclipseUtils.getDocument(file);
assertNotNull(document);
final var processor = new LSPRenameProcessor(document, 0);
@@ -275,11 +285,13 @@ public void testPlaceholderUsingPlaceholderFromPrepareRenameResult() throws Exce
}
@Test
- public void testPlaceholderUsingRangeFromPrepareRenameResult() throws Exception {
+ public void testPlaceholderUsingRangeFromPrepareRenameResult(MockLanguageServerFactory factory) throws Exception {
IFile file = TestUtils.createUniqueTestFile(project, "old");
- MockLanguageServer.INSTANCE.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
- final var range = new Range(new Position(0, 1), new Position(0, 3)); // Two last letters of "old".
- MockLanguageServer.INSTANCE.getTextDocumentService().setPrepareRenameResult(Either.forLeft(range));
+ factory.withConfiguration((idx, server)-> {
+ server.getTextDocumentService().setRenameEdit(createSimpleMockRenameEdit(LSPEclipseUtils.toUri(file)));
+ final var range = new Range(new Position(0, 1), new Position(0, 3)); // Two last letters of "old".
+ server.getTextDocumentService().setPrepareRenameResult(Either.forLeft(range));
+ });
IDocument document = LSPEclipseUtils.getDocument(file);
assertNotNull(document);
final var processor = new LSPRenameProcessor(document, 0);
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java
index a575f576a..51b656fe4 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticHighlightReconcilerStrategyTest.java
@@ -18,7 +18,7 @@
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4j.SemanticTokens;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.widgets.Display;
@@ -34,19 +34,20 @@ public class SemanticHighlightReconcilerStrategyTest extends AbstractTestWithPro
@BeforeEach
public void setUp() {
shell = new Shell();
-
- // Setup Server Capabilities
- List tokenTypes = List.of("keyword");
- List tokenModifiers = List.of("obsolete");
- SemanticTokensTestUtil.setSemanticTokensLegend(tokenTypes, tokenModifiers);
}
@Test
- public void testKeyword() throws CoreException {
+ public void testKeyword(MockLanguageServerFactory factory) throws CoreException {
+ List tokenTypes = List.of("keyword");
+ List tokenModifiers = List.of("obsolete");
+ SemanticTokensTestUtil.setSemanticTokensLegend(tokenTypes, tokenModifiers, factory);
+
final var semanticTokens = new SemanticTokens();
semanticTokens.setData(SemanticTokensTestUtil.keywordSemanticTokens());
- MockLanguageServer.INSTANCE.getTextDocumentService().setSemanticTokens(semanticTokens);
+ factory.withConfiguration((idx, server) -> {
+ server.getTextDocumentService().setSemanticTokens(semanticTokens);
+ });
IFile file = TestUtils.createUniqueTestFile(project, "lsptm", SemanticTokensTestUtil.keywordText);
ITextViewer textViewer = TestUtils.openTextViewer(file);
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensDataStreamProcessorTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensDataStreamProcessorTest.java
index 784983e13..0a9e13ca9 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensDataStreamProcessorTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensDataStreamProcessorTest.java
@@ -14,12 +14,11 @@
import org.eclipse.jface.text.Document;
import org.eclipse.lsp4e.operations.semanticTokens.SemanticTokensDataStreamProcessor;
-import org.eclipse.lsp4e.test.utils.AbstractTest;
import org.eclipse.lsp4j.SemanticTokensLegend;
import org.eclipse.swt.custom.StyleRange;
import org.junit.jupiter.api.Test;
-public class SemanticTokensDataStreamProcessorTest extends AbstractTest {
+public class SemanticTokensDataStreamProcessorTest {
@Test
public void testKeyword() {
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensLegendProviderTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensLegendProviderTest.java
index 307cc964b..ad211ebe1 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensLegendProviderTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensLegendProviderTest.java
@@ -20,16 +20,17 @@
import org.eclipse.lsp4e.operations.semanticTokens.SemanticTokensClient;
import org.eclipse.lsp4e.test.utils.AbstractTestWithProject;
import org.eclipse.lsp4e.test.utils.TestUtils;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.junit.jupiter.api.Test;
public class SemanticTokensLegendProviderTest extends AbstractTestWithProject {
@Test
- public void testSemanticTokensLegendProvider() throws CoreException {
+ public void testSemanticTokensLegendProvider(MockLanguageServerFactory factory) throws CoreException {
// Setup Server Capabilities
List tokenTypes = List.of("keyword","other");
List tokenModifiers = List.of("obsolete");
- SemanticTokensTestUtil.setSemanticTokensLegend(tokenTypes, tokenModifiers);
+ SemanticTokensTestUtil.setSemanticTokensLegend(tokenTypes, tokenModifiers, factory);
// Setup test data
IFile file = TestUtils.createUniqueTestFile(project, "lspt", "test content");
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensTestUtil.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensTestUtil.java
index db7f41907..4195efd72 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensTestUtil.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/SemanticTokensTestUtil.java
@@ -19,9 +19,11 @@
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.SemanticTokensLegend;
import org.eclipse.lsp4j.SemanticTokensWithRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.swt.graphics.Color;
public class SemanticTokensTestUtil {
@@ -112,12 +114,16 @@ public static Function keywordTokenTypeMapper(final IToken token
}
};
}
- public static void setSemanticTokensLegend(final List tokenTypes, List tokenModifiers) {
- final var legend = new SemanticTokensLegend(tokenTypes, tokenModifiers);
- final var semanticTokensWithRegistrationOptions = new SemanticTokensWithRegistrationOptions(legend);
- semanticTokensWithRegistrationOptions.setFull(true);
- semanticTokensWithRegistrationOptions.setRange(false);
-
- MockLanguageServer.INSTANCE.getInitializeResult().getCapabilities().setSemanticTokensProvider(semanticTokensWithRegistrationOptions);
+ public static void setSemanticTokensLegend(final List tokenTypes, List tokenModifiers, MockLanguageServerFactory factory) {
+ factory.withCapabilities(() -> {
+ final var legend = new SemanticTokensLegend(tokenTypes, tokenModifiers);
+ final var semanticTokensWithRegistrationOptions = new SemanticTokensWithRegistrationOptions(legend);
+ semanticTokensWithRegistrationOptions.setFull(true);
+ semanticTokensWithRegistrationOptions.setRange(false);
+
+ ServerCapabilities capabilities = MockLanguageServer.defaultServerCapabilities();
+ capabilities.setSemanticTokensProvider(semanticTokensWithRegistrationOptions);
+ return capabilities;
+ });
}
}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeHolderTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeHolderTest.java
index d0a02e11b..dd76906e4 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeHolderTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeHolderTest.java
@@ -17,12 +17,11 @@
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.lsp4e.operations.semanticTokens.StyleRangeHolder;
-import org.eclipse.lsp4e.test.utils.AbstractTest;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.junit.jupiter.api.Test;
-public class StyleRangeHolderTest extends AbstractTest {
+public class StyleRangeHolderTest {
private static final Color RED = new Color(255, 0, 0);
private List originalStyleRanges = List.of(new StyleRange(0, 4, RED, null), new StyleRange(15, 4, RED, null), new StyleRange(24, 7, RED, null));
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeMergerTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeMergerTest.java
index cfcbaf190..40b0fe0da 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeMergerTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/semanticTokens/StyleRangeMergerTest.java
@@ -20,13 +20,12 @@
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.lsp4e.operations.semanticTokens.StyleRangeHolder;
import org.eclipse.lsp4e.operations.semanticTokens.StyleRangeMerger;
-import org.eclipse.lsp4e.test.utils.AbstractTest;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.junit.jupiter.api.Test;
-public class StyleRangeMergerTest extends AbstractTest {
+public class StyleRangeMergerTest {
@Test
public void testSemanticHighlightMergesWithExistingStyleRanges() {
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/symbols/SymbolsModelTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/symbols/SymbolsModelTest.java
index dec6d64db..091e1d8d0 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/symbols/SymbolsModelTest.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/symbols/SymbolsModelTest.java
@@ -22,7 +22,6 @@
import java.util.List;
import org.eclipse.lsp4e.outline.SymbolsModel;
-import org.eclipse.lsp4e.test.utils.AbstractTest;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
@@ -32,7 +31,7 @@
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.junit.jupiter.api.Test;
-public class SymbolsModelTest extends AbstractTest {
+public class SymbolsModelTest {
private final SymbolsModel symbolsModel = new SymbolsModel();
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTest.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTest.java
deleted file mode 100644
index 7adbb8feb..000000000
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2024 Vegard IT GmbH and others.
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Sebastian Thomschke (Vegard IT GmbH) - initial implementation
- *******************************************************************************/
-package org.eclipse.lsp4e.test.utils;
-
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
-import org.eclipse.lsp4j.ServerCapabilities;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-/**
- * Test base class that configures a {@link AllCleanExtension}.
- */
-public abstract class AbstractTest {
-
- @RegisterExtension
- public final AllCleanExtension allCleanRule = new AllCleanExtension(this::getServerCapabilities);
-
- /**
- * Override if required, used by {@link #allCleanRule}
- */
- protected ServerCapabilities getServerCapabilities() {
- return MockLanguageServer.defaultServerCapabilities();
- }
-}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java
index 316e8271d..4e9567151 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AbstractTestWithProject.java
@@ -14,16 +14,13 @@
import java.lang.reflect.Method;
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo;
/**
* Test base class that provides a new unique temporary test project for each @org.junit.Test run
*/
-public abstract class AbstractTestWithProject extends AbstractTest {
+public abstract class AbstractTestWithProject {
protected IProject project;
@BeforeEach
@@ -34,40 +31,4 @@ public void setUpProject(TestInfo testInfo) throws Exception {
project = TestUtils.createProject(projectName);
}
- @AfterEach
- public void tearDownProject() throws Exception {
- if (project != null && project.exists()) {
- deleteProjectWithRetries(project, 10, 500);
- }
- }
-
- /**
- * Mitigation for potential
- * java.nio.file.FileSystemException: The process cannot access the file because it is being used by another process
- * when deleting a project.
- */
- private static void deleteProjectWithRetries(IProject project, int maxAttempts, long delayMillis)
- throws CoreException {
- for (int attempt = 1; attempt <= maxAttempts; attempt++) {
- try {
- if (!project.exists()) {
- break;
- }
- project.close(null);
- project.delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, null);
- break;
- } catch (CoreException ex) {
- if (attempt == maxAttempts) {
- throw ex;
- }
- try {
- Thread.sleep(delayMillis);
- } catch (InterruptedException ie) {
- Thread.currentThread().interrupt();
- ex.printStackTrace();
- break;
- }
- }
- }
- }
}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AllCleanExtension.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AllCleanExtension.java
deleted file mode 100644
index c9949b800..000000000
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/AllCleanExtension.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2019 Red Hat Inc. and others.
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Mickael Istria (Red Hat Inc.) - initial implementation
- *******************************************************************************/
-package org.eclipse.lsp4e.test.utils;
-
-import java.util.function.Supplier;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.lsp4e.ConnectDocumentToLanguageServerSetupParticipant;
-import org.eclipse.lsp4e.LanguageServiceAccessor;
-import org.eclipse.lsp4e.tests.mock.MockConnectionProvider;
-import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
-import org.eclipse.lsp4e.ui.UI;
-import org.eclipse.lsp4j.ServerCapabilities;
-import org.junit.jupiter.api.extension.AfterEachCallback;
-import org.junit.jupiter.api.extension.BeforeEachCallback;
-import org.junit.jupiter.api.extension.ExtensionContext;
-
-public class AllCleanExtension implements BeforeEachCallback, AfterEachCallback {
-
- private final Supplier serverConfigurer;
-
- public AllCleanExtension() {
- this.serverConfigurer = MockLanguageServer::defaultServerCapabilities;
- }
-
- public AllCleanExtension(final Supplier serverConfigurer) {
- this.serverConfigurer = serverConfigurer;
- }
-
- @Override
- public void beforeEach(ExtensionContext context) throws Exception {
- clear();
- }
-
- @Override
- public void afterEach(ExtensionContext context) throws Exception {
- clear();
- }
-
- private void clear() {
- MockLanguageServer.INSTANCE.setTimeToProceedQueries(0);
- // Give the platform three attempts to shut down windows
- for (int i = 3; i > 0 && !UI.getActivePage().closeAllEditors(false); i--) {}
- ConnectDocumentToLanguageServerSetupParticipant.waitForAll();
- for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
- try {
- project.delete(IResource.FORCE, null);
- } catch (CoreException e) {
- e.printStackTrace();
- }
- }
- MockLanguageServer.INSTANCE.waitBeforeTearDown();
- LanguageServiceAccessor.clearStartedServers();
- MockLanguageServer.reset(this.serverConfigurer);
- MockConnectionProvider.cancellations.clear();
- }
-
-}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/MockLanguageServerExtension.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/MockLanguageServerExtension.java
new file mode 100644
index 000000000..68b1b2db5
--- /dev/null
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/MockLanguageServerExtension.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * See git history
+ *******************************************************************************/
+package org.eclipse.lsp4e.test.utils;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.lsp4e.ConnectDocumentToLanguageServerSetupParticipant;
+import org.eclipse.lsp4e.LanguageServiceAccessor;
+import org.eclipse.lsp4e.tests.mock.MockConnectionProvider;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockLanguageServerFactory;
+import org.eclipse.lsp4e.ui.UI;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.ParameterResolver;
+
+/**
+ * Allows test cases to define a parameter of type
+ * {@link MockLanguageServerFactory}, which they can use to tailor the behavior
+ * of all {@link MockLanguageServer} launched during the execution of the test
+ * case.
+ *
+ * This extension also cleans up thoroughly after each test execution, e.g.,
+ * deleting all projects, clearing all Language Servers, etc.
+ */
+public class MockLanguageServerExtension implements ParameterResolver, AfterEachCallback {
+
+ private static final String KEY = "factory";
+
+ private static final Namespace NAMESPACE = Namespace.create(MockLanguageServerExtension.class);
+
+ @Override
+ public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
+ throws ParameterResolutionException {
+ return parameterContext.getParameter().getType().equals(MockLanguageServerFactory.class);
+ }
+
+ @Override
+ public @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
+ throws ParameterResolutionException {
+ // Store it, just in case.
+ MockLanguageServerFactory factory = extensionContext.getStore(NAMESPACE).computeIfAbsent(KEY, __ -> {
+ return new MockLanguageServerFactory();
+ }, MockLanguageServerFactory.class);
+ MockConnectionProvider.factory = factory;
+
+ return factory;
+ }
+
+ @Override
+ public void afterEach(ExtensionContext context) throws Exception {
+ MockLanguageServerFactory factory = MockConnectionProvider.factory;
+ for (MockLanguageServer server : factory.getServers()) {
+ // Reset delay to zero, otherwise servers will be slow to respond to shutdown
+ // request.
+ server.setTimeToProceedQueries(0);
+ // Wait for all in-flight requests to finish.
+ server.waitBeforeTearDown();
+ }
+
+ // Make sure there are no pending document setups
+ ConnectDocumentToLanguageServerSetupParticipant.waitForAll();
+
+ // Give the platform three attempts to close all editors
+ for (int i = 3; i > 0 && !UI.getActivePage().closeAllEditors(false); i--) {
+ }
+
+ // Now delete all projects
+ for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
+ deleteProjectWithRetries(project, 10, 500);
+ }
+
+ // Cleanup any started servers
+ LanguageServiceAccessor.clearStartedServers();
+
+ // Restore factory
+ MockConnectionProvider.factory = new MockLanguageServerFactory();
+ }
+
+ /**
+ * Mitigation for potential
+ * java.nio.file.FileSystemException: The process cannot access the file because it is being used by another process
+ * when deleting a project.
+ */
+ private static void deleteProjectWithRetries(IProject project, int maxAttempts, long delayMillis)
+ throws CoreException {
+ for (int attempt = 1; attempt <= maxAttempts; attempt++) {
+ try {
+ if (!project.exists()) {
+ break;
+ }
+ project.close(null);
+ project.delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, null);
+ break;
+ } catch (CoreException ex) {
+ if (attempt == maxAttempts) {
+ throw ex;
+ }
+ try {
+ Thread.sleep(delayMillis);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ ex.printStackTrace();
+ break;
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/TestUtils.java b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/TestUtils.java
index 52aad56b1..a13713a93 100644
--- a/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/TestUtils.java
+++ b/org.eclipse.lsp4e.test/src/org/eclipse/lsp4e/test/utils/TestUtils.java
@@ -12,6 +12,7 @@
*******************************************************************************/
package org.eclipse.lsp4e.test.utils;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
@@ -40,6 +41,7 @@
import org.eclipse.lsp4e.LanguageServersRegistry;
import org.eclipse.lsp4e.internal.ArrayUtil;
import org.eclipse.lsp4e.tests.mock.MockLanguageServer;
+import org.eclipse.lsp4e.tests.mock.MockServerState;
import org.eclipse.lsp4e.ui.UI;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
@@ -366,7 +368,7 @@ public void waitForLanguageServerNotRunning(MockLanguageServer server) {
assertTrue(new DisplayHelper() {
@Override
protected boolean condition() {
- return !server.isRunning();
+ return server.getState() != MockServerState.RUNNING;
}
}.waitForCondition(UI.getDisplay(), 1000));
}
@@ -397,7 +399,10 @@ public void worked(int work) {
}
}
- public static Condition numberOfChangesIs(int changes) {
- return () -> MockLanguageServer.INSTANCE.getDidChangeEvents().size() == changes;
+ public static Condition numberOfChangesIs(int changes, MockLanguageServer server) {
+ return () -> {
+ assertEquals(changes, server.getDidChangeEvents().size());
+ return true;
+ };
}
}
diff --git a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockConnectionProvider.java b/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockConnectionProvider.java
index 3af6452b4..3611e7f61 100644
--- a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockConnectionProvider.java
+++ b/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockConnectionProvider.java
@@ -15,14 +15,19 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
import java.net.URI;
import java.nio.channels.Channels;
import java.nio.channels.Pipe;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import org.eclipse.jdt.annotation.Nullable;
@@ -41,22 +46,36 @@ public class MockConnectionProvider implements StreamConnectionProvider {
private Future listener;
private Collection streams = new ArrayList<>(4);
- private static ExecutorService testRunner = Executors.newCachedThreadPool();
+ private static final Logger LOGGER = System.getLogger(MockConnectionProvider.class.getSimpleName());
+
+ /**
+ * This field is used by the JUnit Extension to inject the correct factory for
+ * each test case.
+ */
+ public static MockLanguageServerFactory factory = new MockLanguageServerFactory();
+
+ private static ExecutorService testRunner = Executors
+ .newCachedThreadPool(Thread.ofVirtual().name("MockLanguageServerListener-", 1).factory());
@Override
public void start() throws IOException {
+ factory.connectionProviderStartCounter.incrementAndGet();
+
Pipe serverOutputToClientInput = Pipe.open();
Pipe clientOutputToServerInput = Pipe.open();
errorStream = InputStream.nullInputStream();
InputStream serverInputStream = Channels.newInputStream(clientOutputToServerInput.source());
OutputStream serverOutputStream = Channels.newOutputStream(serverOutputToClientInput.sink());
- Launcher launcher = LSPLauncher.createServerLauncher(MockLanguageServer.INSTANCE, serverInputStream,
+
+ var server = factory.create(serverOutputStream);
+
+ Launcher launcher = LSPLauncher.createServerLauncher(server, serverInputStream,
serverOutputStream, testRunner, Function.identity());
clientInputStream = Channels.newInputStream(serverOutputToClientInput.source());
clientOutputStream = Channels.newOutputStream(clientOutputToServerInput.sink());
listener = launcher.startListening();
- MockLanguageServer.INSTANCE.addRemoteProxy(launcher.getRemoteProxy());
+ server.setRemoteProxy(launcher.getRemoteProxy());
// Store the output streams so we can close them to clean up. The corresponding input
// streams should automatically receive an EOF and close.
@@ -82,24 +101,29 @@ public InputStream getErrorStream() {
@Override
public void stop() {
+ factory.connectionProviderStopCounter.incrementAndGet();
+
streams.forEach(t -> {
try {
t.close();
} catch (IOException e) {
- e.printStackTrace();
+ LOGGER.log(Level.ERROR, "Failed to close an outputstream of the MockLanguageServer", e);
}
});
streams.clear();
+ try {
+ listener.get(5, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ LOGGER.log(Level.ERROR, "Failed to stop the listener of the MockLanguageServer", e);
+ }
listener.cancel(true);
listener = null;
}
- public static final Collection cancellations = new ArrayList<>();
-
@Override
public void handleMessage(Message message, LanguageServer languageServer, @Nullable URI rootURI) {
if (message.toString().contains("cancelRequest")) {
- cancellations.add(message);
+ factory.cancellations.add(message);
}
StreamConnectionProvider.super.handleMessage(message, languageServer, rootURI);
}
diff --git a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockConnectionProviderMultiRootFolders.java b/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockConnectionProviderMultiRootFolders.java
deleted file mode 100644
index de761649d..000000000
--- a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockConnectionProviderMultiRootFolders.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016, 2018 Rogue Wave Software Inc. and others.
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Michał Niewrzał (Rogue Wave Software Inc.) - initial implementation
- * Martin Lippert (Pivotal Inc.) - Bug 531030 - fixed crash when initial project gets deleted in multi-root workspaces
- *******************************************************************************/
-package org.eclipse.lsp4e.tests.mock;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.channels.Channels;
-import java.nio.channels.Pipe;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.eclipse.lsp4e.server.StreamConnectionProvider;
-import org.eclipse.lsp4j.jsonrpc.Launcher;
-import org.eclipse.lsp4j.launch.LSPLauncher;
-import org.eclipse.lsp4j.services.LanguageClient;
-
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-
-public class MockConnectionProviderMultiRootFolders implements StreamConnectionProvider {
- private static final Logger LOG = Logger.getLogger(MockConnectionProviderMultiRootFolders.class.getName());
-
- static ExecutorService sharedExecutor = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors(), 0,
- TimeUnit.SECONDS, new LinkedBlockingQueue(),
- new ThreadFactoryBuilder().setNameFormat("mock-connection-provider-%d").build());
-
- static private AtomicInteger startCount = new AtomicInteger(0);
- static private AtomicInteger stopCount = new AtomicInteger(0);
-
- static public void resetCounts() {
- startCount.set(0);
- stopCount.set(0);
- }
-
- static public int getStartCount() {
- return startCount.get();
- }
-
- static public int getStopCount() {
- return stopCount.get();
- }
-
- private InputStream clientInputStream;
- private OutputStream clientOutputStream;
- private InputStream errorStream;
- private Collection streams = new ArrayList<>(4);
- private Future launcherFuture;
-
- @Override
- public void start() throws IOException {
- try {
- Pipe serverOutputToClientInput = Pipe.open();
- Pipe clientOutputToServerInput = Pipe.open();
- errorStream = InputStream.nullInputStream();
-
- InputStream serverInputStream = Channels.newInputStream(clientOutputToServerInput.source());
- OutputStream serverOutputStream = Channels.newOutputStream(serverOutputToClientInput.sink());
-
- Launcher launcher = LSPLauncher.createServerLauncher(
- MockLanguageServerMultiRootFolders.INSTANCE, serverInputStream, serverOutputStream, sharedExecutor,
- (c) -> c);
-
- clientInputStream = Channels.newInputStream(serverOutputToClientInput.source());
- clientOutputStream = Channels.newOutputStream(clientOutputToServerInput.sink());
- launcherFuture = launcher.startListening();
- MockLanguageServer.INSTANCE.addRemoteProxy(launcher.getRemoteProxy());
- streams.add(clientInputStream);
- streams.add(clientOutputStream);
- streams.add(serverInputStream);
- streams.add(serverOutputStream);
- streams.add(errorStream);
-
- startCount.incrementAndGet();
- } catch (Exception x) {
- LOG.log(Level.SEVERE, "MockConnectionProvider#start", x);
- }
- }
-
- @Override
- public InputStream getInputStream() {
- return clientInputStream;
- }
-
- @Override
- public OutputStream getOutputStream() {
- return clientOutputStream;
- }
-
- @Override
- public InputStream getErrorStream() {
- return errorStream;
- }
-
- @Override
- public void stop() {
- stopCount.incrementAndGet();
- if (launcherFuture != null) {
- launcherFuture.cancel(true);
- }
- }
-}
diff --git a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockLanguageServer.java b/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockLanguageServer.java
index 8fbc06f2a..b4c47a724 100644
--- a/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockLanguageServer.java
+++ b/org.eclipse.lsp4e.tests.mock/src/org/eclipse/lsp4e/tests/mock/MockLanguageServer.java
@@ -16,6 +16,10 @@
*******************************************************************************/
package org.eclipse.lsp4e.tests.mock;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -29,6 +33,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import org.eclipse.lsp4j.CodeAction;
@@ -69,6 +74,8 @@
import org.eclipse.lsp4j.TextDocumentSyncOptions;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.TypeHierarchyRegistrationOptions;
+import org.eclipse.lsp4j.WorkspaceFoldersOptions;
+import org.eclipse.lsp4j.WorkspaceServerCapabilities;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.launch.LSPLauncher;
@@ -84,30 +91,37 @@ public class MockLanguageServer implements LanguageServer {
*/
public static final String SUPPORTED_COMMAND_ID = "mock.command";
- public static MockLanguageServer INSTANCE = new MockLanguageServer(MockLanguageServer::defaultServerCapabilities);
-
private volatile MockTextDocumentService textDocumentService = new MockTextDocumentService(
this::buildMaybeDelayedFuture);
private final MockWorkspaceService workspaceService = new MockWorkspaceService(this::buildMaybeDelayedFuture);
private final InitializeResult initializeResult = new InitializeResult();
private volatile long delay = 0;
private volatile Executor delayedExecutor = null;
- private volatile boolean started;
+ private AtomicReference state = new AtomicReference(MockServerState.RUNNING);
- private final List remoteProxies = new CopyOnWriteArrayList<>();
+ private static final Logger LOGGER = System.getLogger(MockLanguageServer.class.getSimpleName());
- private final List> inFlight = new CopyOnWriteArrayList<>();
+ /**
+ * The MockLanguageServer was started as a separate process.
+ */
+ private boolean launchedStandalone = false;
- public static void reset() {
- INSTANCE = new MockLanguageServer(MockLanguageServer::defaultServerCapabilities);
- }
+ /**
+ * The remote proxy. This can be used to send requests to the client.
+ */
+ private LanguageClient remoteProxy = null;
- public static void reset(final Supplier serverConfigurer) {
- INSTANCE = new MockLanguageServer(serverConfigurer);
- }
+ private final List> inFlight = new CopyOnWriteArrayList<>();
+
+ /**
+ * Stream which this LS uses to send messages to the client. Closing this stream
+ * will terminate the connection on the client side.
+ */
+ private OutputStream output;
- protected MockLanguageServer(final Supplier serverConfigurer) {
- resetInitializeResult(serverConfigurer);
+ public MockLanguageServer(Supplier supplier, OutputStream stdout) {
+ initializeResult.setCapabilities(supplier.get());
+ this.output = stdout;
}
/**
@@ -117,10 +131,11 @@ protected MockLanguageServer(final Supplier serverConfigurer
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException, ExecutionException {
- Launcher l = LSPLauncher.createServerLauncher(MockLanguageServer.INSTANCE, System.in,
+ MockLanguageServer server = new MockLanguageServer(MockLanguageServer::defaultServerCapabilities, System.out);
+ server.launchedStandalone = true;
+ Launcher l = LSPLauncher.createServerLauncher(server, System.in,
System.out);
Future> f = l.startListening();
- MockLanguageServer.INSTANCE.addRemoteProxy(l.getRemoteProxy());
f.get();
}
@@ -141,14 +156,9 @@ public void waitBeforeTearDown() {
});
}
- public void addRemoteProxy(LanguageClient remoteProxy) {
- this.textDocumentService.addRemoteProxy(remoteProxy);
- this.remoteProxies.add(remoteProxy);
- this.started = true;
- }
-
- private void resetInitializeResult(final Supplier serverConfigurer) {
- initializeResult.setCapabilities(serverConfigurer.get());
+ public void setRemoteProxy(LanguageClient remoteProxy) {
+ this.textDocumentService.setRemoteProxy(remoteProxy);
+ this.remoteProxy = remoteProxy;
}
public CompletableFuture buildMaybeDelayedFuture(U value) {
@@ -161,6 +171,10 @@ public CompletableFuture buildMaybeDelayedFuture(U value) {
return CompletableFuture.completedFuture(value);
}
+ /**
+ * Supplier to get a default set of server capabilities.
+ *
+ */
public static ServerCapabilities defaultServerCapabilities() {
final var capabilities = new ServerCapabilities();
capabilities.setTextDocumentSync(TextDocumentSyncKind.Full);
@@ -190,6 +204,22 @@ public static ServerCapabilities defaultServerCapabilities() {
return capabilities;
}
+ /**
+ * Similar to {@link #defaultServerCapabilities()}, but with workspace support
+ * (multi root) enabled.
+ *
+ */
+ public static ServerCapabilities multiRootCapabilities() {
+ var capabilities = defaultServerCapabilities();
+ final var workspace = new WorkspaceServerCapabilities();
+ final var workspaceFolders = new WorkspaceFoldersOptions();
+ workspaceFolders.setSupported(Boolean.TRUE);
+
+ workspace.setWorkspaceFolders(workspaceFolders);
+ capabilities.setWorkspace(workspace);
+ return capabilities;
+ }
+
@Override
public CompletableFuture initialize(InitializeParams params) {
@@ -290,12 +320,24 @@ public InitializeResult getInitializeResult() {
@Override
public CompletableFuture