From 61ac660435da0fa12d9fa7c6f66fc654e2b9dc9d Mon Sep 17 00:00:00 2001 From: shedaniel Date: Wed, 20 Jan 2021 22:50:36 +0800 Subject: [PATCH] Auto generate vscode run configurations, inject our own pre launch tasks to tasks.json --- README.md | 1 + .../configuration/CompileConfiguration.java | 2 + .../loom/task/GenVsCodeProjectTask.java | 115 +++++++++++++++++- 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index df34c1aa..42b40d85 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ A [Gradle](https://gradle.org/) plugin to setup a deobfuscated development envir * Utilises the Fernflower and CFR decompilers to generate source code with comments. * Designed to support modern versions of Minecraft (Tested with 1.14.4 and upwards) * ~~Built in support for IntelliJ IDEA, Eclipse and Visual Studio Code to generate run configurations for Minecraft.~~ + - Currently, only IntelliJ IDEA and Visual Studio Code works with Forge Loom. * Loom targets a wide range of Gradle versions. _Tested with 4.9 up to 6.7_ * Supports the latest version of Java all the way down to Java 8 diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index 1824e4f8..e15c0f1b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -59,6 +59,7 @@ import net.fabricmc.loom.configuration.providers.forge.PatchProvider; import net.fabricmc.loom.configuration.providers.forge.SrgProvider; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; import net.fabricmc.loom.task.AbstractLoomTask; +import net.fabricmc.loom.task.GenVsCodeProjectTask; import net.fabricmc.loom.task.RemapAllSourcesTask; import net.fabricmc.loom.task.RemapJarTask; import net.fabricmc.loom.task.RemapSourcesJarTask; @@ -247,6 +248,7 @@ public final class CompileConfiguration { if (extension.autoGenIDERuns) { SetupIntelijRunConfigs.setup(project1); + GenVsCodeProjectTask.generate(project1); } // Enables the default mod remapper diff --git a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java index c2e9ab31..795adb44 100644 --- a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java @@ -28,11 +28,16 @@ import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.apache.commons.io.FileUtils; +import org.apache.tools.ant.taskdefs.condition.Os; import org.gradle.api.Project; import org.gradle.api.tasks.TaskAction; @@ -46,9 +51,12 @@ import net.fabricmc.loom.configuration.ide.RunConfig; public class GenVsCodeProjectTask extends AbstractLoomTask { @TaskAction public void genRuns() { - Project project = getProject(); - LoomGradleExtension extension = getExtension(); - File projectDir = project.file(".vscode"); + clean(getProject()); + generate(getProject()); + } + + public static void clean(Project project) { + File projectDir = project.getRootProject().file(".vscode"); if (!projectDir.exists()) { projectDir.mkdir(); @@ -59,12 +67,36 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { if (launchJson.exists()) { launchJson.delete(); } + } + + public static void generate(Project project) { + LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + File projectDir = project.getRootProject().file(".vscode"); + + if (!projectDir.exists()) { + projectDir.mkdir(); + } + + File launchJson = new File(projectDir, "launch.json"); + File tasksJson = new File(projectDir, "tasks.json"); + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + VsCodeLaunch launch; + + if (launchJson.exists()) { + try { + launch = gson.fromJson(FileUtils.readFileToString(launchJson, StandardCharsets.UTF_8), VsCodeLaunch.class); + } catch (IOException e) { + throw new RuntimeException("Failed to read launch.json", e); + } + } else { + launch = new VsCodeLaunch(); + } - VsCodeLaunch launch = new VsCodeLaunch(); launch.add(RunConfig.clientRunConfig(project)); launch.add(RunConfig.serverRunConfig(project)); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); String json = gson.toJson(launch); try { @@ -78,6 +110,39 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { if (!runDir.exists()) { runDir.mkdirs(); } + + VsCodeTasks tasks; + + if (tasksJson.exists()) { + try { + tasks = gson.fromJson(FileUtils.readFileToString(tasksJson, StandardCharsets.UTF_8), VsCodeTasks.class); + } catch (IOException e) { + throw new RuntimeException("Failed to read launch.json", e); + } + } else { + tasks = new VsCodeTasks(); + } + + for (VsCodeConfiguration configuration : launch.configurations) { + if (configuration.preLaunchTask != null && configuration.tasksBeforeRun != null) { + String prefix = Os.isFamily(Os.FAMILY_WINDOWS) ? "gradlew.bat" : "./gradlew"; + tasks.add(new VsCodeTask(configuration.preLaunchTask, prefix + " " + configuration.tasksBeforeRun.stream() + .map(s -> { + int i = s.indexOf('/'); + return i == -1 ? s : s.substring(i + 1); + }).collect(Collectors.joining(" ")), "shell", new String[0])); + } + } + + if (!tasks.tasks.isEmpty()) { + String jsonTasks = gson.toJson(tasks); + + try { + FileUtils.writeStringToFile(tasksJson, jsonTasks, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException("Failed to write tasks.json", e); + } + } } private static class VsCodeLaunch { @@ -85,7 +150,25 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { public List configurations = new ArrayList<>(); public void add(RunConfig runConfig) { - configurations.add(new VsCodeConfiguration(runConfig)); + if (configurations.stream().noneMatch(config -> Objects.equals(config.name, runConfig.configName))) { + VsCodeConfiguration configuration = new VsCodeConfiguration(runConfig); + configurations.add(configuration); + + if (!configuration.tasksBeforeRun.isEmpty()) { + configuration.preLaunchTask = "generated_" + runConfig.configName; + } + } + } + } + + private static class VsCodeTasks { + public String version = "2.0.0"; + public List tasks = new ArrayList<>(); + + public void add(VsCodeTask vsCodeTask) { + if (tasks.stream().noneMatch(task -> Objects.equals(task.label, vsCodeTask.label))) { + tasks.add(vsCodeTask); + } } } @@ -100,12 +183,32 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { public String mainClass; public String vmArgs; public String args; + public Map env = new LinkedHashMap<>(); + public transient List tasksBeforeRun = new ArrayList<>(); + public String preLaunchTask = null; VsCodeConfiguration(RunConfig runConfig) { this.name = runConfig.configName; this.mainClass = runConfig.mainClass; this.vmArgs = runConfig.vmArgs; this.args = runConfig.programArgs; + this.env.putAll(runConfig.envVariables); + this.tasksBeforeRun.addAll(runConfig.tasksBeforeRun); + } + } + + private static class VsCodeTask { + public String label; + public String command; + public String type; + public String[] args; + public String group = "build"; + + VsCodeTask(String label, String command, String type, String[] args) { + this.label = label; + this.command = command; + this.type = type; + this.args = args; } } }