Add support to test harness for checking highlights.
This commit is contained in:
@@ -127,7 +127,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
|
||||
projectFinder = serverParams.projectFinder;
|
||||
projectObserver = serverParams.projectObserver;
|
||||
|
||||
liveHoverWatchdog = new SpringLiveHoverWatchdog(this, hoverInfoProvider, serverParams.runningAppProvider, projectFinder, projectObserver);
|
||||
liveHoverWatchdog = new SpringLiveHoverWatchdog(this, hoverInfoProvider, serverParams.runningAppProvider, projectFinder, projectObserver, serverParams.watchDogInterval);
|
||||
documents.onDidChangeContent(params -> {
|
||||
TextDocument doc = params.getDocument();
|
||||
if (testHightlighter != null) {
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider;
|
||||
import org.springframework.ide.vscode.boot.java.utils.BootProjectUtil;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringLiveHoverWatchdog;
|
||||
import org.springframework.ide.vscode.boot.metadata.DefaultSpringPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
|
||||
import org.springframework.ide.vscode.commons.gradle.GradleCore;
|
||||
@@ -36,17 +38,21 @@ public class BootJavaLanguageServerParams {
|
||||
public final ProjectObserver projectObserver;
|
||||
public final SpringPropertyIndexProvider indexProvider;
|
||||
public final RunningAppProvider runningAppProvider;
|
||||
public final Duration watchDogInterval;
|
||||
|
||||
public BootJavaLanguageServerParams(
|
||||
JavaProjectFinder projectFinder,
|
||||
ProjectObserver projectObserver,
|
||||
SpringPropertyIndexProvider indexProvider,
|
||||
RunningAppProvider runningAppProvider) {
|
||||
RunningAppProvider runningAppProvider,
|
||||
Duration watchDogInterval
|
||||
) {
|
||||
super();
|
||||
this.projectFinder = projectFinder;
|
||||
this.projectObserver = projectObserver;
|
||||
this.indexProvider = indexProvider;
|
||||
this.runningAppProvider = runningAppProvider;
|
||||
this.watchDogInterval = watchDogInterval;
|
||||
}
|
||||
|
||||
public static LSFactory<BootJavaLanguageServerParams> createDefault() {
|
||||
@@ -66,7 +72,8 @@ public class BootJavaLanguageServerParams {
|
||||
javaProjectFinder.filter(BootProjectUtil::isBootProject),
|
||||
projectObserver,
|
||||
new DefaultSpringPropertyIndexProvider(javaProjectFinder, projectObserver),
|
||||
RunningAppProvider.DEFAULT
|
||||
RunningAppProvider.DEFAULT,
|
||||
SpringLiveHoverWatchdog.DEFAULT_INTERVAL
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
@@ -35,8 +36,10 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
*/
|
||||
public class SpringLiveHoverWatchdog {
|
||||
|
||||
private static final int POLLING_INTERVAL_MILLISECONDS = 5000;
|
||||
|
||||
public static final Duration DEFAULT_INTERVAL = Duration.ofMillis(5000);
|
||||
|
||||
private final long POLLING_INTERVAL_MILLISECONDS;
|
||||
private final Set<String> watchedDocs;
|
||||
private final SimpleLanguageServer server;
|
||||
private final BootJavaHoverProvider hoverProvider;
|
||||
@@ -61,7 +64,15 @@ public class SpringLiveHoverWatchdog {
|
||||
return uris.anyMatch(uri -> projectFinder.find(new TextDocumentIdentifier(uri)).isPresent());
|
||||
}
|
||||
|
||||
public SpringLiveHoverWatchdog(SimpleLanguageServer server, BootJavaHoverProvider hoverProvider, RunningAppProvider runningAppProvider, JavaProjectFinder projectFinder, ProjectObserver projectChanges) {
|
||||
public SpringLiveHoverWatchdog(
|
||||
SimpleLanguageServer server,
|
||||
BootJavaHoverProvider hoverProvider,
|
||||
RunningAppProvider runningAppProvider,
|
||||
JavaProjectFinder projectFinder,
|
||||
ProjectObserver projectChanges,
|
||||
Duration pollingInterval
|
||||
) {
|
||||
this.POLLING_INTERVAL_MILLISECONDS = pollingInterval == null ? DEFAULT_INTERVAL.toMillis() : pollingInterval.toMillis();
|
||||
this.server = server;
|
||||
this.hoverProvider = hoverProvider;
|
||||
this.runningAppProvider = runningAppProvider;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.profile;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
@@ -31,6 +33,7 @@ public class ActiveProfilesHoverTest {
|
||||
harness = BootLanguageServerHarness.builder()
|
||||
.mockDefaults()
|
||||
.runningAppProvider(mockAppProvider.provider)
|
||||
.watchDogInterval(Duration.ofMillis(100))
|
||||
.build();
|
||||
harness.useProject(projects.mavenProject("empty-boot-15-web-app"));
|
||||
harness.intialize(null);
|
||||
@@ -60,6 +63,10 @@ public class ActiveProfilesHoverTest {
|
||||
editor.assertHoverContains("@Profile", "local-profile");
|
||||
editor.assertHoverContains("@Profile", "foo.bar.RunningApp");
|
||||
editor.assertHoverContains("@Profile", "22022");
|
||||
|
||||
editor.assertHighlights(
|
||||
"@Profile(\"local\")"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.project.harness;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
|
||||
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerParams;
|
||||
@@ -46,6 +48,7 @@ public class BootLanguageServerHarness extends LanguageServerHarness<BootJavaLan
|
||||
private SpringPropertyIndexProvider indexProvider = null;
|
||||
private RunningAppProvider runningAppProvider = null;
|
||||
private PropertyIndexHarness indexHarness = null;
|
||||
private Duration watchDogInterval = null;
|
||||
|
||||
public BootLanguageServerHarness build() throws Exception {
|
||||
BootLanguageServerHarness harness = new BootLanguageServerHarness(this);
|
||||
@@ -75,6 +78,11 @@ public class BootLanguageServerHarness extends LanguageServerHarness<BootJavaLan
|
||||
this.indexProvider = propertyIndexProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder watchDogInterval(Duration watchDogInterval) {
|
||||
this.watchDogInterval = watchDogInterval;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +96,8 @@ public class BootLanguageServerHarness extends LanguageServerHarness<BootJavaLan
|
||||
builder.projectFinder==null?defaults.projectFinder:builder.projectFinder,
|
||||
builder.projectObserver==null?defaults.projectObserver:builder.projectObserver,
|
||||
builder.indexProvider==null?defaults.indexProvider:builder.indexProvider,
|
||||
builder.runningAppProvider==null?defaults.runningAppProvider:builder.runningAppProvider
|
||||
builder.runningAppProvider==null?defaults.runningAppProvider:builder.runningAppProvider,
|
||||
builder.watchDogInterval==null?defaults.watchDogInterval:builder.watchDogInterval
|
||||
);
|
||||
};
|
||||
return new BootJavaLanguageServer(params);
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
|
||||
package org.springframework.ide.vscode.languageserver.testharness;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.assertContains;
|
||||
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.assertDoesNotContain;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -26,6 +28,10 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -46,11 +52,13 @@ import org.eclipse.lsp4j.TextDocumentPositionParams;
|
||||
import org.eclipse.lsp4j.TextEdit;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.junit.Assert;
|
||||
import org.springframework.ide.vscode.commons.languageserver.HighlightParams;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.Unicodes;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@@ -109,8 +117,21 @@ public class Editor {
|
||||
return p1.getCharacter() - p2.getCharacter();
|
||||
}
|
||||
};
|
||||
private static final Comparator<Range> RANGE_COMPARATOR = new Comparator<Range>() {
|
||||
@Override
|
||||
public int compare(Range o1, Range o2) {
|
||||
int diff = compare(o1.getStart(), o2.getStart());
|
||||
if (diff!=0) return diff;
|
||||
return compare(o1.getEnd(), o2.getEnd());
|
||||
}
|
||||
private int compare(Position p1, Position p2) {
|
||||
int d = p1.getLine() - p2.getLine();
|
||||
if (d!=0) return d;
|
||||
return p1.getCharacter() - p2.getCharacter();
|
||||
}
|
||||
};
|
||||
|
||||
private LanguageServerHarness harness;
|
||||
private LanguageServerHarness<?> harness;
|
||||
private TextDocumentInfo doc;
|
||||
|
||||
private int selectionEnd;
|
||||
@@ -190,6 +211,19 @@ public class Editor {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
public List<Range> assertHighlights(String... expectedHighlights) throws Exception {
|
||||
HighlightParams highlights = harness.getHighlights(doc);
|
||||
List<Range> ranges = new ArrayList<>(highlights.getRanges());
|
||||
Collections.sort(ranges, RANGE_COMPARATOR);
|
||||
List<String> actualHighlights = ranges.stream()
|
||||
.map(this::getText)
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(ImmutableList.copyOf(expectedHighlights), actualHighlights);
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the editor text, with cursor markers inserted (for easy textual comparison
|
||||
* after applying a proposal)
|
||||
@@ -806,5 +840,4 @@ public class Editor {
|
||||
public void setCursor(Position position) {
|
||||
this.selectionStart = this.selectionEnd = doc.toOffset(position);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -34,7 +36,10 @@ import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.assertj.core.api.Condition;
|
||||
@@ -99,6 +104,8 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@@ -116,6 +123,7 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
|
||||
private InitializeResult initResult;
|
||||
|
||||
private Map<String,TextDocumentInfo> documents = new HashMap<>();
|
||||
private Multimap<String, CompletableFuture<HighlightParams>> highlights = MultimapBuilder.hashKeys().linkedListValues().build();
|
||||
private Map<String, PublishDiagnosticsParams> diagnostics = new HashMap<>();
|
||||
private List<Editor> activeEditors = new ArrayList<>();
|
||||
|
||||
@@ -125,6 +133,8 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
|
||||
this.defaultLanguageId = defaultLanguageId;
|
||||
}
|
||||
|
||||
public static final Duration HIGHLIGHTS_TIMEOUT = Duration.ofMinutes(1000);
|
||||
|
||||
public LanguageServerHarness(Callable<S> factory) throws Exception {
|
||||
this(factory, LanguageId.PLAINTEXT);
|
||||
}
|
||||
@@ -176,6 +186,21 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
|
||||
this.diagnostics.put(diags.getUri(), diags);
|
||||
}
|
||||
|
||||
private void receiveHighlights(HighlightParams highlights) {
|
||||
Collection<CompletableFuture<HighlightParams>>requestors = ImmutableList.of();
|
||||
synchronized (this) {
|
||||
String uri = highlights.getDoc().getUri();
|
||||
if (uri!=null) {
|
||||
requestors = ImmutableList.copyOf(this.highlights.get(uri));
|
||||
//Carefull!! Must make a copy above. Because the returned collection is cleared when we call removeAll below.
|
||||
this.highlights.removeAll(uri); //futures can only be completed once, so no point holding any longer
|
||||
}
|
||||
}
|
||||
for (CompletableFuture<HighlightParams> future : requestors) {
|
||||
future.complete(highlights);
|
||||
}
|
||||
}
|
||||
|
||||
public InitializeResult intialize(File workspaceRoot) throws Exception {
|
||||
server = factory.call();
|
||||
int parentPid = random.nextInt(40000)+1000;
|
||||
@@ -220,6 +245,11 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
|
||||
receiveDiagnostics(diagnostics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void highlight(HighlightParams highlights) {
|
||||
receiveHighlights(highlights);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logMessage(MessageParams message) {
|
||||
// TODO Auto-generated method stub
|
||||
@@ -254,11 +284,6 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
|
||||
}
|
||||
return CompletableFuture.completedFuture(new ApplyWorkspaceEditResponse(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void highlight(HighlightParams highlights) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -372,6 +397,16 @@ public class LanguageServerHarness<S extends SimpleLanguageServer> {
|
||||
return diagnostics.get(doc.getUri());
|
||||
}
|
||||
|
||||
public synchronized Future<HighlightParams> getHighlightsFuture(TextDocumentInfo doc) {
|
||||
CompletableFuture<HighlightParams> future = new CompletableFuture<HighlightParams>();
|
||||
highlights.put(doc.getUri(), future);
|
||||
return future;
|
||||
}
|
||||
|
||||
public HighlightParams getHighlights(TextDocumentInfo doc) throws Exception {
|
||||
return getHighlightsFuture(doc).get(HIGHLIGHTS_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static Condition<Diagnostic> isDiagnosticWithSeverity(DiagnosticSeverity severity) {
|
||||
return new Condition<>(
|
||||
(d) -> d.getSeverity()==severity,
|
||||
|
||||
Reference in New Issue
Block a user