Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
f1e1748
Boilerplate for LSP router.
toinehartman Apr 22, 2026
d838723
Symmetric pairing of services.
toinehartman Apr 22, 2026
50c8fc0
Routing language server as special case of parametric.
toinehartman Apr 22, 2026
f320f88
Extract routing services.
toinehartman Apr 22, 2026
fe01d94
Basic delegate server.
toinehartman Apr 23, 2026
2b6d9a4
Factor out initialization.
toinehartman Apr 23, 2026
3134be6
Route all client calls back to the original client.
toinehartman Apr 23, 2026
4ed8701
Simplify routing with utility interfaces.
toinehartman Apr 23, 2026
0e86a65
Move classes to appropriate package.
toinehartman Apr 23, 2026
1fe0e43
Allow routing by extensions.
toinehartman Apr 23, 2026
d784529
Forward `textDocument/*` LSP calls to delegates.
toinehartman Apr 23, 2026
3a4b347
Start multiple delegate servers on predefined ports.
toinehartman Apr 23, 2026
381b847
Add deployed launch config.
toinehartman Apr 24, 2026
8b3fbc1
Fix deployed running and cleanup.
toinehartman Apr 24, 2026
8d5bae3
Fix lint errors and nulls.
toinehartman Apr 24, 2026
0f43434
Only interrupt on interruption exception.
toinehartman Apr 24, 2026
40e0dc9
Shut down child processes on exit.
toinehartman Apr 24, 2026
bd14c05
Implement command execution.
toinehartman Apr 28, 2026
d5d3e1b
Print port number in log message.
toinehartman Apr 28, 2026
60a3509
Prepare for class path based on POM.
toinehartman Apr 28, 2026
410c2cb
Log language registration calls.
toinehartman Apr 28, 2026
310ec57
Merge remote-tracking branch 'origin/main' into feature/1010-pom-lead…
toinehartman Apr 28, 2026
096ad1a
Do not resolve project location.
toinehartman Apr 28, 2026
aa08777
Fix nullability.
toinehartman Apr 28, 2026
12742a4
Rename caller interface name & methods.
toinehartman Apr 28, 2026
c9991f3
Rename router interface.
toinehartman Apr 28, 2026
34f3daa
Fix dedicated language arg.
toinehartman Apr 29, 2026
7ebc693
Fix & suppress warnings.
toinehartman Apr 29, 2026
dbaa57b
Implement basic argument parsing.
toinehartman Apr 29, 2026
a76ec75
Document new classes and interfaces.
toinehartman Apr 29, 2026
53cc8b3
Remove redundant pairing.
toinehartman Apr 29, 2026
701b483
Refactor starting/connecting language servers.
toinehartman Apr 29, 2026
800e992
Improve readability & comment.
toinehartman Apr 29, 2026
ee69b05
Start server with dedicated language.
toinehartman Apr 29, 2026
295f674
Exit dedicated remote server when it has no more contributions.
toinehartman Apr 29, 2026
01a643e
Fix indentation.
toinehartman Apr 30, 2026
c66a12b
Fix warnings.
toinehartman Apr 30, 2026
0790e7a
Run dedicated servers with POM-based class path.
toinehartman Apr 30, 2026
81be307
Handle registration from different locations.
toinehartman May 1, 2026
00504be
Clean up terminated servers.
toinehartman May 1, 2026
933e697
Ignore unregistration of unknown languages.
toinehartman May 1, 2026
1f33795
Push down error handling to server connect methods.
toinehartman May 4, 2026
6821900
Rename thread pool.
toinehartman May 4, 2026
80f54bf
Clean up on language unregistration.
toinehartman May 4, 2026
f1dfff7
Do not use dedicated language mode.
toinehartman May 4, 2026
110ccbb
Await language registration before returning.
toinehartman May 4, 2026
7637abe
Forward close/save notifications.
toinehartman May 4, 2026
8713e45
Distribute some notifications over all remote servers.
toinehartman May 4, 2026
3a0c311
Merge branch 'feature/1010-pom-leading-for-dsls/final' into feature/1…
toinehartman May 4, 2026
b5b4a8e
Attempt to make CF happy.
toinehartman May 4, 2026
ce9fd15
Fix SQ warnings.
toinehartman May 4, 2026
5bc39e0
Upload logs as artifact.
toinehartman May 5, 2026
67950a3
Properly compose and await language registration.
toinehartman May 5, 2026
3feac15
Re-do cleanup of child processes without hooks or bookkeeping.
toinehartman May 5, 2026
9054f9b
Make class path separator OS-dependent.
toinehartman May 5, 2026
6ee7eca
Fix CF by casting function.
toinehartman May 5, 2026
1fd3c42
Encode as base64 when decoding is needed.
toinehartman May 8, 2026
03e6011
Add TODO for later.
toinehartman May 8, 2026
b51e497
Route commands via workspace service like other servers.
toinehartman May 8, 2026
3acc0ce
Move routing server to dedicated package.
toinehartman May 11, 2026
e648018
Proxy IValues by wrapping the wrap JSON.
toinehartman May 11, 2026
f026e3c
Skip some tests that we implement later.
toinehartman May 11, 2026
37a0ebe
Rename `LanguageServerRouter` => `ActualRoutingLanguageServer`
toinehartman May 11, 2026
97905d9
Various small fixes and reverts.
toinehartman May 11, 2026
e70e5e0
Merge branch 'feature/1010-pom-leading-for-dsls/final' into feature/1…
toinehartman May 11, 2026
6f475fe
Used proxied language client in routing server.
toinehartman May 11, 2026
842de26
Improved JSON number parser fallbacks.
toinehartman May 11, 2026
ea42bd3
Remove/change some TODOs.
toinehartman May 12, 2026
2b01979
Inline future caller utils.
toinehartman May 12, 2026
3c19a6d
Remove unused executor.
toinehartman May 13, 2026
8ec2677
Do not suppress warning on function that we need later.
toinehartman May 13, 2026
485921c
Route doc->doc, workspace->workspace.
toinehartman May 13, 2026
ff93256
More precise command ignore message.
toinehartman May 13, 2026
949aab0
Deserialize routed IValue as wrapped JSON element.
toinehartman May 13, 2026
ac870fc
Construct class path based on path config.
toinehartman May 13, 2026
1e642c2
Swap launch config order.
toinehartman May 14, 2026
754297e
Extract client proxy to separate class.
toinehartman May 14, 2026
367a864
Implement leaner doc service interface after refactoring routing.
toinehartman May 14, 2026
9bef253
Restore static registration of dynamic capabilities.
toinehartman May 14, 2026
99cc70a
Wrap missing language exceptions in futures.
toinehartman May 14, 2026
d704127
Clean up child processes on exit.
toinehartman May 14, 2026
9433208
Notes & docs.
toinehartman May 14, 2026
9ce67cd
Re-use language server start logic.
toinehartman May 15, 2026
6968b4a
Forwards logs properly.
toinehartman May 15, 2026
df575bb
Child process cleanup.
toinehartman May 15, 2026
4af6cb8
Remove commented code; do not use dedicated mode.
toinehartman May 18, 2026
e39f31b
Fix indentation.
toinehartman May 19, 2026
e5ca190
Maven-based class path.
toinehartman May 19, 2026
cfee654
Suppress and fix warnings.
toinehartman May 19, 2026
453739c
Reduce visibility of function.
toinehartman May 19, 2026
c378259
Wait longer for diagnostics to clear.
toinehartman May 20, 2026
6e8a341
Ignore failures while setting debug level.
toinehartman May 20, 2026
2902727
Await file notifications.
toinehartman May 20, 2026
33bbd3b
Fix warnings.
toinehartman May 20, 2026
4cb1941
Revert "Ignore failures while setting debug level."
toinehartman May 20, 2026
59b6ac7
Revert "Child process cleanup."
toinehartman May 20, 2026
7643643
Simplify & fix log forwarding.
toinehartman May 21, 2026
bebb23e
Clean up logging.
toinehartman May 21, 2026
756576e
Merge branch 'feature/1010-pom-leading-for-dsls/final' into feature/1…
toinehartman May 21, 2026
91f14d7
Log to stderr directly instead of stdout.
toinehartman May 21, 2026
fea7a10
Start servers with the same log level.
toinehartman May 21, 2026
a28792e
Rewrite filtering of dependencies.
toinehartman May 21, 2026
391e67b
Cleanup of resources.
toinehartman May 21, 2026
8438484
Re-use safe language implementation.
toinehartman May 21, 2026
766bbe5
Make single-use interface more specific.
toinehartman May 21, 2026
33e042e
Use port pool for dev servers.
toinehartman May 21, 2026
191610e
Remove redundant checks.
toinehartman May 21, 2026
01eb385
Revert "Await file notifications."
toinehartman May 21, 2026
a298003
Null check.
toinehartman May 26, 2026
4e5038e
Always set thread name.
toinehartman May 26, 2026
6f75dbb
Merge branch 'feature/1010-pom-leading-for-dsls/final' into feature/1…
toinehartman May 27, 2026
091223b
Document server exit hooks.
toinehartman May 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions rascal-lsp/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,47 @@
"-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar",
"-Drascal.fallbackResolver=org.rascalmpl.vscode.lsp.uri.FallbackResolver"
]
},
{
"type": "java",
"name": "Parametric Routing Server",
"request": "launch",
"mainClass": "org.rascalmpl.vscode.lsp.parametric.routing.RoutingLanguageServer",
"projectName": "rascal-lsp",
"console": "internalConsole",
"vmArgs": [
"-Dlog4j2.level=TRACE",
"-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar",
"-Drascal.fallbackResolver=org.rascalmpl.vscode.lsp.uri.FallbackResolver"
]
},
{
"type": "java",
"name": "Delegate Parametric Server [1]",
"request": "launch",
"mainClass": "org.rascalmpl.vscode.lsp.parametric.ParametricLanguageServer",
"args": ["--port", "9990"],
"projectName": "rascal-lsp",
"console": "internalConsole",
"vmArgs": [
"-Dlog4j2.level=TRACE",
"-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar",
"-Drascal.fallbackResolver=org.rascalmpl.vscode.lsp.uri.FallbackResolver"
]
},
{
"type": "java",
"name": "Delegate Parametric Server [2]",
"request": "launch",
"mainClass": "org.rascalmpl.vscode.lsp.parametric.ParametricLanguageServer",
"args": ["--port", "9991"],
"projectName": "rascal-lsp",
"console": "internalConsole",
"vmArgs": [
"-Dlog4j2.level=TRACE",
"-Drascal.compilerClasspath=${workspaceFolder}/target/lib/rascal.jar",
"-Drascal.fallbackResolver=org.rascalmpl.vscode.lsp.uri.FallbackResolver"
]
}
]
}
20 changes: 20 additions & 0 deletions rascal-lsp/src/main/checkerframework/jdk.astub
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,23 @@ public interface Map<K, V> {
K key,
BiFunction<? super K, ? super @Nullable V, ? extends @Nullable V> remappingFunction) {}
}

package java.util.concurrent;

import org.checkerframework.checker.nullness.qual.*;

public interface ConcurrentHashMap<K, V> {
// Since ConcurrentHashMap does not permit null values, compute functions can only return `null` if the compute function returns null

public @PolyNull V compute(
K key,
BiFunction<? super K, ? super @Nullable V, ? extends @PolyNull V> remappingFunction) {}

public @PolyNull V computeIfAbsent(
K key,
Function<? super K, ? extends @PolyNull V> computeFunction) {}

public @PolyNull V computeIfPresent(
K key,
BiFunction<? super K, ? super V, ? extends @PolyNull V> remappingFunction) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
public abstract class BaseLanguageServer {
private static final PrintStream capturedOut;
private static final InputStream capturedIn;
private static final boolean DEPLOY_MODE;
public static final boolean DEPLOY_MODE;
private static final String LOG_CONFIGURATION_KEY = "log4j2.configurationFactory";

static {
Expand All @@ -108,13 +108,13 @@ protected BaseLanguageServer() {}

private static final Logger logger = LogManager.getLogger(BaseLanguageServer.class);

private static Launcher<IBaseLanguageClient> constructLSPClient(Socket client, ActualLanguageServer server, ExecutorService threadPool)
protected static Launcher<IBaseLanguageClient> constructLSPClient(Socket client, ActualLanguageServer server, ExecutorService threadPool)
throws IOException {
client.setTcpNoDelay(true);
return constructLSPClient(client.getInputStream(), client.getOutputStream(), server, threadPool);
}

private static Launcher<IBaseLanguageClient> constructLSPClient(InputStream in, OutputStream out, ActualLanguageServer server, ExecutorService threadPool) {
protected static Launcher<IBaseLanguageClient> constructLSPClient(InputStream in, OutputStream out, ActualLanguageServer server, ExecutorService threadPool) {
Launcher<IBaseLanguageClient> clientLauncher = new Launcher.Builder<IBaseLanguageClient>()
.setLocalService(server)
.setRemoteInterface(IBaseLanguageClient.class)
Expand All @@ -129,12 +129,21 @@ private static Launcher<IBaseLanguageClient> constructLSPClient(InputStream in,
return clientLauncher;
}

private static void printClassPath() {
protected static void printClassPath() {
logger.trace("Started with classpath: {}", () -> System.getProperty("java.class.path"));
}

@FunctionalInterface
protected interface ServerBuilder {
ActualLanguageServer apply(Runnable a, ExecutorService b, IBaseTextDocumentService c, BaseWorkspaceService d);
}

protected static void startLanguageServer(String requestPoolName, String workerPoolName, Function<ExecutorService, IBaseTextDocumentService> docServiceProvider, Function<ExecutorService, BaseWorkspaceService> workspaceServiceProvider, int portNumber) {
startLanguageServer(ActualLanguageServer::new, requestPoolName, workerPoolName, docServiceProvider, workspaceServiceProvider, portNumber);
}

@SuppressWarnings({"java:S2189", "java:S106"})
public static void startLanguageServer(String requestPoolName, String workerPoolName, Function<ExecutorService, IBaseTextDocumentService> docServiceProvider, Function<ExecutorService, BaseWorkspaceService> workspaceServiceProvider, int portNumber) {
protected static void startLanguageServer(ServerBuilder serverBuilder, String requestPoolName, String workerPoolName, Function<ExecutorService, IBaseTextDocumentService> docServiceProvider, Function<ExecutorService, BaseWorkspaceService> workspaceServiceProvider, int portNumber) {
logger.info("Starting Rascal Language Server: {}", getVersion());
printClassPath();

Expand All @@ -145,9 +154,7 @@ public static void startLanguageServer(String requestPoolName, String workerPool
try {
var docService = docServiceProvider.apply(workerPool);
var wsService = workspaceServiceProvider.apply(workerPool);
docService.pair(wsService);
wsService.pair(docService);
startLSP(constructLSPClient(capturedIn, capturedOut, new ActualLanguageServer(() -> System.exit(0), workerPool, docService, wsService), requestPool));
startLSP(constructLSPClient(capturedIn, capturedOut, serverBuilder.apply(() -> System.exit(0), workerPool, docService, wsService), requestPool));
} finally {
requestPool.shutdown();
workerPool.shutdown();
Expand All @@ -164,9 +171,7 @@ public static void startLanguageServer(String requestPoolName, String workerPool
logger.info("New client connected to Rascal LSP server (listening on port number: {})", portNumber);
var docService = docServiceProvider.apply(workerPool);
var wsService = workspaceServiceProvider.apply(workerPool);
docService.pair(wsService);
wsService.pair(docService);
startLSP(constructLSPClient(clientSocket, new ActualLanguageServer(() -> {}, workerPool, docService, wsService), requestPool));
startLSP(constructLSPClient(clientSocket, serverBuilder.apply(() -> {}, workerPool, docService, wsService), requestPool));
}
finally {
requestPool.shutdown();
Expand All @@ -181,7 +186,7 @@ public static void startLanguageServer(String requestPoolName, String workerPool

private static final String DEFAULT_VERSION = "unknown";

private static String getVersion() {
protected static String getVersion() {
try (InputStream prop = ActualLanguageServer.class.getClassLoader().getResourceAsStream("project.properties")) {
if (prop == null) {
logger.error("Could not find project.properties file");
Expand All @@ -198,7 +203,7 @@ private static String getVersion() {
}
}

private static void startLSP(Launcher<IBaseLanguageClient> server) {
protected static void startLSP(Launcher<IBaseLanguageClient> server) {
try {
server.startListening().get();
} catch (InterruptedException e) {
Expand All @@ -216,19 +221,23 @@ private static void startLSP(Launcher<IBaseLanguageClient> server) {
}
}
}
private static class ActualLanguageServer implements IBaseLanguageServerExtensions, LanguageClientAware {
public static class ActualLanguageServer implements IBaseLanguageServerExtensions, LanguageClientAware {
static final Logger logger = LogManager.getLogger(ActualLanguageServer.class);
private final IBaseTextDocumentService lspDocumentService;
private final BaseWorkspaceService lspWorkspaceService;
private final Runnable onExit;
private final ExecutorService executor;

private @MonotonicNonNull IDEServicesConfiguration remoteIDEServicesConfiguration;
private @MonotonicNonNull IBaseLanguageClient client;

private ActualLanguageServer(Runnable onExit, ExecutorService executor, IBaseTextDocumentService lspDocumentService, BaseWorkspaceService lspWorkspaceService) {
protected ActualLanguageServer(Runnable onExit, ExecutorService executor, IBaseTextDocumentService lspDocumentService, BaseWorkspaceService lspWorkspaceService) {
this.onExit = onExit;
this.executor = executor;
this.lspDocumentService = lspDocumentService;
this.lspWorkspaceService = lspWorkspaceService;
lspDocumentService.pair(lspWorkspaceService);
lspWorkspaceService.pair(lspDocumentService);
}

@Override
Expand Down Expand Up @@ -266,15 +275,20 @@ public CompletableFuture<Two<String, URI[]>[]> supplyPathConfig(PathConfigParame

@Override
public CompletableFuture<Void> sendRegisterLanguage(LanguageParameter lang) {
logger.debug("rascal/sendRegisterLanguage({}, {})", lang.getName(), lang.getMainFunction());
return CompletableFuture.runAsync(() -> lspDocumentService.registerLanguage(lang), executor);
}
@Override
public CompletableFuture<Void> sendUnregisterLanguage(LanguageParameter lang) {
logger.debug("rascal/sendUnregisterLanguage({})", lang.getName());
return CompletableFuture.runAsync(() -> lspDocumentService.unregisterLanguage(lang), executor);
}

@Override
public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
// Exit when our parent process exits
executor.submit(() -> ProcessHandle.of(params.getProcessId()).ifPresent(p -> p.onExit().thenAccept(ignored -> this.exit())));

return CompletableFuture.supplyAsync(() -> {
logger.info("LSP connection started (connected to {} version {})", params.getClientInfo().getName(), params.getClientInfo().getVersion());
logger.debug("LSP client capabilities: {}", params.getCapabilities());
Expand Down Expand Up @@ -324,13 +338,20 @@ public void setTrace(SetTraceParams params) {

@Override
public void connect(LanguageClient client) {
var proxy = addShutdownDetectionTo(client);
lspDocumentService.connect(proxy);
lspWorkspaceService.connect(proxy);
remoteIDEServicesConfiguration = RemoteIDEServicesThread.startRemoteIDEServicesServer(proxy, lspDocumentService, executor);
this.client = addShutdownDetectionTo(client);
lspDocumentService.connect(this.client);
lspWorkspaceService.connect(this.client);
remoteIDEServicesConfiguration = RemoteIDEServicesThread.startRemoteIDEServicesServer(this.client, lspDocumentService, executor);
logger.debug("Remote IDE Services Port {}", remoteIDEServicesConfiguration);
}

protected IBaseLanguageClient availableClient() {
if (client == null) {
throw new IllegalStateException("Language Client has not been connected yet");
}
return client;
}

/**
* Creates a proxy instance that forwards method calls to the provided
* language client only when (the thread pool of) this language server
Expand Down Expand Up @@ -371,5 +392,10 @@ public void setMinimumLogLevel(String level) {
final var l = Level.toLevel(level, Level.DEBUG); // fall back to debug when the string cannot be mapped
Configurator.setRootLevel(l);
}

protected ExecutorService getExecutor() {
return executor;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

import java.net.URI;
import java.util.concurrent.CompletableFuture;

import org.eclipse.lsp4j.jsonrpc.messages.Tuple.Two;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
Expand Down Expand Up @@ -63,4 +62,5 @@ default CompletableFuture<Two<String, URI[]>[]> supplyPathConfig(PathConfigParam

@JsonNotification("rascal/logLevel")
void setMinimumLogLevel(String level);

}
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,16 @@ public Configuration getConfiguration(LoggerContext loggerContext, Configuration
return buildConfiguration();
}

private Configuration buildConfiguration() {
Level targetLevel = Level.getLevel(System.getProperty("log4j2.level", "INFO"));
public static Level getLogLevel() {
var targetLevel = Level.getLevel(System.getProperty("log4j2.level", "INFO"));
if (targetLevel == null) {
targetLevel = Level.INFO;
return Level.INFO;
}
return targetLevel;
}

private Configuration buildConfiguration() {
Level targetLevel = getLogLevel();

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setConfigurationName("JsonLogger");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,7 @@ public Configuration getConfiguration(LoggerContext loggerContext, Configuration
}

private static Configuration buildRedirectConfig() {
Level targetLevel = Level.getLevel(System.getProperty("log4j2.level", "INFO"));
if (targetLevel == null) {
targetLevel = Level.INFO;
}
Level targetLevel = LogJsonConfiguration.getLogLevel();

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setConfigurationName("DefaultLogger");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,75 @@
package org.rascalmpl.vscode.lsp.parametric;


import com.google.gson.GsonBuilder;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.rascalmpl.vscode.lsp.BaseLanguageServer;
import org.rascalmpl.vscode.lsp.parametric.LanguageRegistry.LanguageParameter;

import com.google.gson.GsonBuilder;

public class ParametricLanguageServer extends BaseLanguageServer {
public static void main(String[] args) {
LanguageParameter dedicatedLanguage;
if (args.length > 0) {
dedicatedLanguage = new GsonBuilder().create().fromJson(args[0], LanguageParameter.class);
}
else {
dedicatedLanguage = null;
}

protected static void startParametric(ServerArgs args) {
startLanguageServer("parametric-lsp"
, "parametric"
, threadPool -> new ParametricTextDocumentService(threadPool, dedicatedLanguage)
, threadPool -> new ParametricTextDocumentService(threadPool, args.getDedicatedLanguage(), args.isExitWhenEmpty())
, ParametricWorkspaceService::new
, 9999
, args.getPort()
);
}

public static void main(String[] args) {
startParametric(parseArgs(args));
}

public static class ServerArgs {
private int port = 9999;
private @Nullable LanguageParameter dedicatedLanguage = null;
private boolean exitWhenEmpty = false;

public int getPort() {
return port;
}

public void setPort(int port) {
this.port = port;
}

public @Nullable LanguageParameter getDedicatedLanguage() {
return dedicatedLanguage;
}

public void setDedicatedLanguage(LanguageParameter dedicatedLanguage) {
this.dedicatedLanguage = dedicatedLanguage;
}

public boolean isExitWhenEmpty() {
return exitWhenEmpty;
}

public void setExitWhenEmpty(boolean exitWhenEmpty) {
this.exitWhenEmpty = exitWhenEmpty;
}

}

@SuppressWarnings("java:S127") // skipping next argument from loop
protected static ServerArgs parseArgs(String[] args) {
var serverArgs = new ServerArgs();
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "--port":
serverArgs.setPort(Integer.parseInt(args[++i]));
break;
case "--exitWhenEmpty":
serverArgs.setExitWhenEmpty(true);
break;
default:
if (serverArgs.getDedicatedLanguage() == null) {
serverArgs.setDedicatedLanguage(new GsonBuilder().create().fromJson(args[i], LanguageParameter.class));
}
break;
}
}
return serverArgs;
}
}
Loading
Loading