package de.peeeq.wurstio.languageserver; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import de.peeeq.wurstio.languageserver.requests.*; import de.peeeq.wurstscript.WLogger; import org.eclipse.lsp4j.ExecuteCommandParams; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; /** * */ public class WurstCommands { public static final String WURST_RESTART = "wurst.restart"; public static final String WURST_CLEAN = "wurst.clean"; public static final String WURST_STARTMAP = "wurst.startmap"; public static final String WURST_HOTSTARTMAP = "wurst.hotstartmap"; public static final String WURST_HOTRELOAD = "wurst.hotreload"; public static final String WURST_BUILDMAP = "wurst.buildmap"; public static final String WURST_STARTLAST = "wurst.startlast"; public static final String WURST_TESTS = "wurst.tests"; public static final String WURST_TESTS_FILE = "wurst.tests_file"; public static final String WURST_TESTS_FUNC = "wurst.tests_func"; public static final String WURST_PERFORM_CODE_ACTION = "wurst.perform_code_action"; static List providedCommands() { return List.of( WURST_CLEAN ); } public static CompletableFuture execute(WurstLanguageServer server, ExecuteCommandParams params) { switch (params.getCommand()) { case WURST_CLEAN: return server.worker().handle(new CleanProject()).thenApply(x -> x); case WURST_STARTMAP: return startMap(server, params); case WURST_HOTSTARTMAP: return startMap(server, params, "-hotstart"); case WURST_HOTRELOAD: return startMap(server, params, "-hotreload"); case WURST_TESTS: return testMap(server, params); case WURST_PERFORM_CODE_ACTION: return server.worker().handle(new PerformCodeActionRequest(server, params)); case WURST_BUILDMAP: return buildMap(server, params); } WLogger.info("unhandled command: " + params.getCommand()); throw new RuntimeException("unhandled command: " + params.getCommand()); } private static CompletableFuture testMap(WurstLanguageServer server, ExecuteCommandParams params) { JsonObject options = (JsonObject) params.getArguments().get(0); Optional filename = getString(options, "filename"); int line = options.has("line") ? options.get("line").getAsInt() : -1; int column = options.has("column") ? options.get("column").getAsInt() : -1; int testTimeout = options.has("testTimeout") ? options.get("testTimeout").getAsInt() : 20; Optional testName = getString(options, "testName"); return server.worker().handle(new RunTests(filename, line, column, testName, testTimeout)); } private static CompletableFuture buildMap(WurstLanguageServer server, ExecuteCommandParams params) { WFile workspaceRoot = server.getRootUri(); if (params.getArguments().isEmpty()) { throw new RuntimeException("Missing arguments"); } JsonObject options = (JsonObject) params.getArguments().get(0); Optional mapPath = getString(options, "mappath"); Optional wc3Path = getString(options, "wc3path"); if (!mapPath.isPresent()) { throw new RuntimeException("No mappath given"); } Optional map = mapPath.map(File::new); List compileArgs = getCompileArgs(workspaceRoot); return server.worker().handle(new BuildMap(server, workspaceRoot, wc3Path, map, compileArgs)).thenApply(x -> x); } private static CompletableFuture startMap(WurstLanguageServer server, ExecuteCommandParams params, String... additionalArgs) { WFile workspaceRoot = server.getRootUri(); if (params.getArguments().isEmpty()) { throw new RuntimeException("Missing arguments"); } JsonObject options = (JsonObject) params.getArguments().get(0); Optional mapPath = getString(options, "mappath"); Optional wc3Path = getString(options, "wc3path"); Optional map = mapPath.map(File::new); List compileArgs = getCompileArgs(workspaceRoot, additionalArgs); return server.worker().handle(new RunMap(server, workspaceRoot, wc3Path, map, compileArgs)).thenApply(x -> x); } private static Optional getString(JsonObject options, String key) { try { return Optional.ofNullable(options.get(key)).map(JsonElement::getAsString); } catch (ClassCastException | IllegalStateException e) { WLogger.warning("Invalid configuration", e); return Optional.empty(); } } private static final List defaultArgs = ImmutableList.of("-runcompiletimefunctions", "-injectobjects", "-stacktraces"); public static List getCompileArgs(WFile rootPath, String... additionalArgs) { try { Path configFile = Paths.get(rootPath.toString(), "wurst_run.args"); if (Files.exists(configFile)) { try (Stream lines = Files.lines(configFile)) { return Stream.concat( lines.filter(s -> s.startsWith("-")), Stream.of(additionalArgs) ).collect(Collectors.toList()); } } else { String cfg = String.join("\n", defaultArgs) + "\n"; Files.write(configFile, cfg.getBytes(Charsets.UTF_8)); return defaultArgs; } } catch (IOException e) { throw new RuntimeException("Could not access wurst_run.args config file", e); } } }