Skip to content

Commit 7e6a4af

Browse files
gselzerclaude
andcommitted
Make test sessions with a fake LanguageServerService
ScriptSession is made with a service only: FakeServers gives each test session a fake server of its own, which sees scripts as they are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 0530536 commit 7e6a4af

3 files changed

Lines changed: 158 additions & 17 deletions

File tree

‎src/test/java/org/scijava/ui/swing/script/autocompletion/CodeIntelligenceUITest.java‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@
5252
import org.fife.ui.rsyntaxtextarea.parser.ParserNotice;
5353
import org.junit.Test;
5454
import org.scijava.code.lsp.Environment;
55-
import org.scijava.code.lsp.ScriptDocument;
5655
import org.scijava.code.lsp.jvm.AbstractLanguageServer;
57-
import org.scijava.code.lsp.ScriptSession;
5856

5957
/**
6058
* Tests {@link HoverToolTipSupplier}, {@link DiagnosticsParser} and
@@ -82,7 +80,7 @@ protected Hover hover(final Document doc, final int at) {
8280
}
8381
};
8482
final HoverToolTipSupplier supplier = new HoverToolTipSupplier(
85-
new ScriptSession(e -> server, ScriptDocument::of), null);
83+
FakeServers.session(server), null);
8684
final String text = "x.dumps(1)";
8785
assertEquals("<html><pre>Serialize.</pre></html>", supplier.toolTip(text,
8886
3));
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* #%L
3+
* Script Editor and Interpreter for SciJava script languages.
4+
* %%
5+
* Copyright (C) 2009 - 2026 SciJava developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
30+
package org.scijava.ui.swing.script.autocompletion;
31+
32+
import java.util.Collections;
33+
import java.util.Map;
34+
35+
import javax.script.ScriptEngine;
36+
37+
import org.eclipse.lsp4j.services.LanguageServer;
38+
import org.scijava.Context;
39+
import org.scijava.code.lsp.Environment;
40+
import org.scijava.code.lsp.LanguageServerService;
41+
import org.scijava.code.lsp.ScriptDialect;
42+
import org.scijava.code.lsp.ScriptDocument;
43+
import org.scijava.code.lsp.ScriptSession;
44+
import org.scijava.script.AbstractScriptLanguage;
45+
import org.scijava.script.ScriptLanguage;
46+
import org.scijava.service.AbstractService;
47+
48+
/**
49+
* A {@link LanguageServerService} serving every script with one fake server,
50+
* which sees scripts as they are: for tests of what editors do with sessions.
51+
*
52+
* @author Gabriel Selzer
53+
*/
54+
final class FakeServers extends AbstractService implements
55+
LanguageServerService
56+
{
57+
58+
/** A script language: any will do, as all are served alike here. */
59+
private static final ScriptLanguage LANGUAGE =
60+
new AbstractScriptLanguage()
61+
{
62+
63+
@Override
64+
public ScriptEngine getScriptEngine() {
65+
return null;
66+
}
67+
};
68+
69+
/** Shows scripts as they are. */
70+
private static final ScriptDialect AS_IS = new ScriptDialect() {
71+
72+
@Override
73+
public boolean supports(final ScriptLanguage language) {
74+
return true;
75+
}
76+
77+
@Override
78+
public String languageId() {
79+
return "plaintext";
80+
}
81+
82+
@Override
83+
public Header header(final Map<String, Class<?>> parameters) {
84+
return new Header("", Collections.emptySet());
85+
}
86+
};
87+
88+
/** Where sessions look for a log service: there is none. */
89+
private static final Context EMPTY = new Context(true);
90+
91+
private final LanguageServer server;
92+
93+
private FakeServers(final LanguageServer server) {
94+
this.server = server;
95+
}
96+
97+
@Override
98+
public Context context() {
99+
return EMPTY;
100+
}
101+
102+
@Override
103+
public Context getContext() {
104+
return EMPTY;
105+
}
106+
107+
/** A session whose server is the given one. */
108+
static ScriptSession session(final LanguageServer server) {
109+
return new ScriptSession(new FakeServers(server), LANGUAGE);
110+
}
111+
112+
@Override
113+
public ScriptDialect dialect(final ScriptLanguage language) {
114+
return AS_IS;
115+
}
116+
117+
@Override
118+
public ScriptDocument document(final String script,
119+
final ScriptDialect dialect)
120+
{
121+
return ScriptDocument.of(script);
122+
}
123+
124+
@Override
125+
public boolean supports(final ScriptLanguage language) {
126+
return true;
127+
}
128+
129+
@Override
130+
public boolean supports(final String languageId) {
131+
return true;
132+
}
133+
134+
@Override
135+
public LanguageServer launch(final String languageId,
136+
final Environment environment)
137+
{
138+
return server;
139+
}
140+
141+
@Override
142+
public Map<String, Class<?>> scriptParameters(final String text) {
143+
return Collections.emptyMap();
144+
}
145+
}

‎src/test/java/org/scijava/ui/swing/script/autocompletion/SciJavaCompletionProviderTest.java‎

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,10 @@
6060
import org.fife.ui.autocomplete.ParameterizedCompletion;
6161
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
6262
import org.junit.Test;
63-
import org.scijava.code.lsp.ScriptDocument;
6463
import org.scijava.code.lsp.jvm.Callable;
6564
import org.scijava.code.lsp.Environment;
6665
import org.scijava.code.lsp.Positions;
6766
import org.scijava.code.lsp.jvm.AbstractLanguageServer;
68-
import org.scijava.code.lsp.ScriptSession;
6967

7068
/**
7169
* Tests that {@link SciJavaCompletionProvider} faithfully bridges a language
@@ -92,7 +90,7 @@ public void testBridgesCompletions() {
9290
return FakeServer.items(doc, 4, caret, bar, new CompletionItem("baz"));
9391
};
9492
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
95-
new ScriptSession(e -> server, ScriptDocument::of));
93+
FakeServers.session(server));
9694

9795
// The provider must report the already-entered text as the replaced span.
9896
assertEquals("ba", provider.getAlreadyEnteredText(area));
@@ -119,7 +117,7 @@ public void testAdditionalEditsSurfaceAsSciJavaCompletion() {
119117
return FakeServer.items(doc, 0, caret, roi);
120118
};
121119
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
122-
new ScriptSession(e -> server, ScriptDocument::of));
120+
FakeServers.session(server));
123121

124122
final List<Completion> completions = provider.getCompletionsImpl(area);
125123
assertEquals(1, completions.size());
@@ -155,7 +153,7 @@ public void testCallablesBecomeFunctionCompletionsWithChoices() {
155153
return FakeServer.items(doc, caret, caret, myRoi, addRoi.toItem());
156154
};
157155
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
158-
new ScriptSession(e -> server, ScriptDocument::of));
156+
FakeServers.session(server));
159157

160158
// Callables surface as FunctionCompletions so parameter assistance works.
161159
final List<Completion> completions = provider.getCompletionsImpl(area);
@@ -182,7 +180,7 @@ public void testCallablesRenderWithSignatures() {
182180
server.complete = (doc, caret) -> FakeServer.items(doc, 0, caret, method(
183181
completionText, "long[]").toItem());
184182
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
185-
new ScriptSession(e -> server, ScriptDocument::of));
183+
FakeServers.session(server));
186184

187185
// The popup list must show a callable's parameters, not just its name.
188186
final Completion c = provider.getCompletionsImpl(area).get(0);
@@ -206,7 +204,7 @@ public void testParameterTooltipListsOtherOverloads() {
206204
method("img.getAt", "int[]").toItem(), // e.g. a bridge method
207205
method("img.getAtX", "long[]").toItem());
208206
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
209-
new ScriptSession(e -> server, ScriptDocument::of));
207+
FakeServers.session(server));
210208
final List<Completion> completions = provider.getCompletionsImpl(area);
211209

212210
// Each overload's tooltip lists the others, once each, even before RSTA
@@ -252,7 +250,7 @@ public void testParameterTooltipShowsSignatureHelp() {
252250
.toSignature(), longs.toSignature(), strings.toSignature()), 0, 1);
253251
};
254252
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
255-
new ScriptSession(e -> server, ScriptDocument::of));
253+
FakeServers.session(server));
256254
final List<Completion> completions = provider.getCompletionsImpl(area);
257255
final ParameterizedCompletion intOverload =
258256
(ParameterizedCompletion) completions.get(0);
@@ -284,7 +282,7 @@ public void testParameterTooltipIgnoresOtherCalls() {
284282
server.help = (doc, caret) -> new SignatureHelp(Collections.singletonList(
285283
method("b", "double").toSignature()), 0, 0);
286284
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
287-
new ScriptSession(e -> server, ScriptDocument::of));
285+
FakeServers.session(server));
288286
final ParameterizedCompletion intOverload =
289287
(ParameterizedCompletion) provider.getCompletionsImpl(area).get(0);
290288
area.setText("a(b(|), p1)");
@@ -313,7 +311,7 @@ public void testLazyDescriptions() {
313311
return "The zeta function.";
314312
}));
315313
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
316-
new ScriptSession(e -> server, ScriptDocument::of));
314+
FakeServers.session(server));
317315
final List<Completion> completions = provider.getCompletionsImpl(area);
318316
// Nothing is described until RSTA shows a completion's description...
319317
assertEquals(0, asked.get());
@@ -331,7 +329,7 @@ public void testResultUpdates() throws Exception {
331329
area.setCaretPosition(4);
332330
final CompletableFuture<CompletionList> later = new CompletableFuture<>();
333331
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
334-
new ScriptSession(e -> new LateServer(later), ScriptDocument::of));
332+
FakeServers.session(new LateServer(later)));
335333
final Boolean[] notified = { null };
336334
provider.setUpdateListener(wasEmpty -> notified[0] = wasEmpty);
337335

@@ -347,7 +345,7 @@ public void testResultUpdates() throws Exception {
347345
// A result for a request the user has typed past is ignored.
348346
final CompletableFuture<CompletionList> stale = new CompletableFuture<>();
349347
final SciJavaCompletionProvider provider2 = new SciJavaCompletionProvider(
350-
new ScriptSession(e -> new LateServer(stale), ScriptDocument::of));
348+
FakeServers.session(new LateServer(stale)));
351349
notified[0] = null;
352350
provider2.setUpdateListener(wasEmpty -> notified[0] = wasEmpty);
353351
area.setText("np.z");
@@ -367,7 +365,7 @@ public void testOpenOnInstall() {
367365
final File file = new File("scripts", "blur.py");
368366
final FakeServer server = new FakeServer();
369367
final LanguageServerLanguageSupport support =
370-
new LanguageServerLanguageSupport(() -> new ScriptSession(e -> server, ScriptDocument::of),
368+
new LanguageServerLanguageSupport(() -> FakeServers.session(server),
371369
null, () -> file);
372370
support.install(area);
373371
// NB: Sessions tell their servers off the caller's thread.
@@ -398,7 +396,7 @@ public void testRequestCarriesScriptPath() {
398396
return new CompletionList();
399397
};
400398
final SciJavaCompletionProvider provider = new SciJavaCompletionProvider(
401-
new ScriptSession(e -> server, ScriptDocument::of));
399+
FakeServers.session(server));
402400

403401
// Without a file supplier (e.g. in an interpreter): no path.
404402
provider.getCompletionsImpl(area);

0 commit comments

Comments
 (0)