diff --git a/common/build.gradle b/common/build.gradle index ce57913cf..495be60d8 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -21,6 +21,7 @@ dependencies { api "io.codechicken:DiffPatch:${project.diffpatch_version}" api "commons-codec:commons-codec:${project.commons_codec_version}" api "net.neoforged:EclipseLaunchConfigs:${project.eclipse_launch_configs_version}" + api "net.neoforged:VscLaunchConfigs:${project.vscode_launch_configs_version}" api "net.neoforged:JarJarMetadata:${project.jarjar_version}" api "net.neoforged:JarJarSelector:${project.jarjar_version}" diff --git a/common/src/main/java/net/neoforged/gradle/common/extensions/IdeManagementExtension.java b/common/src/main/java/net/neoforged/gradle/common/extensions/IdeManagementExtension.java index 6c7160bcc..5a059be83 100644 --- a/common/src/main/java/net/neoforged/gradle/common/extensions/IdeManagementExtension.java +++ b/common/src/main/java/net/neoforged/gradle/common/extensions/IdeManagementExtension.java @@ -17,6 +17,7 @@ import org.jetbrains.gradle.ext.ProjectSettings; import org.jetbrains.gradle.ext.TaskTriggersConfig; +import java.util.function.BiConsumer; import javax.inject.Inject; /** @@ -74,13 +75,37 @@ public boolean isEclipseImport() { return System.getProperty("eclipse.application") != null; } + /** + * Checks whether Gradle is being invoked: + * - from Eclipse plugin and the plugin is sourced from RedHat VSCode extension + * - from VSCode Microsoft Gradle plugin + * + * @return true if should rather perform VsCode setup instead of Eclipse setup. + */ + public boolean isVscodeImport() + { + final boolean isNativeEclipse = isEclipseImport() && System.getProperty("eclipse.home.location", "").contains("redhat.java"); + return isNativeEclipse || isVscodePluginImport(project); + } + + /** + * Checks whether Gradle is being invoked from VSCode Microsoft Gradle plugin + * + * @return true if must perform VsCode setup instead of Eclipse setup. + * @implNote reinvestigate after https://github.com/microsoft/vscode-java-debug/issues/1106 + */ + public static boolean isVscodePluginImport(final Project project) + { + return project.getPlugins().stream().anyMatch(p -> p.getClass().getName().equals("com.microsoft.gradle.GradlePlugin")); + } + /** * Indicates if an IDE import in any of the supported IDEs is ongoing. * * @return {@code true} if an IDE import is ongoing, {@code false} otherwise */ public boolean isIdeImportInProgress() { - return isIdeaImport() || isEclipseImport(); + return isIdeaImport() || isEclipseImport() || isVscodeImport(); } /** @@ -124,6 +149,12 @@ public void eclipse(Project project, EclipseModel eclipse) { //Register the task to run after the Eclipse import is complete, via its build-in support. eclipse.synchronizationTasks(idePostSyncTask); } + + @Override + public void vscode(Project project, EclipseModel eclipse) { + // vscode ~= eclipse + eclipse(project, eclipse); + } }); } else { @@ -143,7 +174,9 @@ public void eclipse(Project project, EclipseModel eclipse) { */ public void apply(final IdeImportAction toPerform) { onIdea(toPerform); - onEclipse(toPerform); + // since vscode and eclipse shares EclipseModel import only one of them + if (isVscodeImport()) onVscode(toPerform); + else onEclipse(toPerform); onGradle(toPerform); } @@ -182,7 +215,15 @@ public void onIdea(final IdeaIdeImportAction toPerform) { toPerform.idea(project, model, ideaExt); }); } - + + public void onEclipse(final EclipseIdeImportAction toPerform) { + onCommonEclipse(toPerform::eclipse); + } + + public void onVscode(final VscodeIdeImportAction toPerform) { + onCommonEclipse(toPerform::vscode); + } + /** * Applies the specified configuration action to configure eclipse IDE projects only. * @@ -191,7 +232,7 @@ public void onIdea(final IdeaIdeImportAction toPerform) { * * @param toPerform the actions to perform */ - public void onEclipse(final EclipseIdeImportAction toPerform) { + private void onCommonEclipse(final BiConsumer toPerform) { //When the Eclipse plugin is available, configure it project.getPlugins().withType(EclipsePlugin.class, plugin -> { //Do not configure the eclipse plugin if we are not importing. @@ -204,11 +245,13 @@ public void onEclipse(final EclipseIdeImportAction toPerform) { EclipseModel model = project.getExtensions().findByType(EclipseModel.class); if (model == null) { model = rootProject.getExtensions().findByType(EclipseModel.class); - return; + if (model == null) { + return; + } } //Configure the project, passing the model and the relevant project. Which does not need to be the root, but can be. - toPerform.eclipse(project, model); + toPerform.accept(project, model); }); } @@ -218,7 +261,7 @@ public void onEclipse(final EclipseIdeImportAction toPerform) { * @param toPerform the actions to perform */ public void onGradle(final GradleIdeImportAction toPerform) { - if (!isEclipseImport() && !isIdeaImport()) { + if (!isEclipseImport() && !isIdeaImport() && !isVscodeImport()) { toPerform.gradle(project); } } @@ -262,8 +305,22 @@ public interface EclipseIdeImportAction { void eclipse(Project project, EclipseModel eclipse); } + /** + * A configuration action for vscode IDE projects. + */ + public interface VscodeIdeImportAction { + + /** + * Configure an vscode project. + * + * @param project the project being imported + * @param eclipse the eclipse project model to modify + */ + void vscode(Project project, EclipseModel eclipse); + } + /** * A configuration action for IDE projects. */ - public interface IdeImportAction extends IdeaIdeImportAction, EclipseIdeImportAction, GradleIdeImportAction { } + public interface IdeImportAction extends IdeaIdeImportAction, EclipseIdeImportAction, VscodeIdeImportAction, GradleIdeImportAction { } } diff --git a/common/src/main/java/net/neoforged/gradle/common/runs/ide/IdeRunIntegrationManager.java b/common/src/main/java/net/neoforged/gradle/common/runs/ide/IdeRunIntegrationManager.java index 2a2f99744..110662acb 100644 --- a/common/src/main/java/net/neoforged/gradle/common/runs/ide/IdeRunIntegrationManager.java +++ b/common/src/main/java/net/neoforged/gradle/common/runs/ide/IdeRunIntegrationManager.java @@ -18,6 +18,11 @@ import net.neoforged.gradle.dsl.common.runs.run.Run; import net.neoforged.gradle.dsl.common.util.CommonRuntimeUtils; import net.neoforged.gradle.util.FileUtils; +import net.neoforged.vsclc.BatchedLaunchWriter; +import net.neoforged.vsclc.LaunchConfiguration; +import net.neoforged.vsclc.attribute.PathLike; +import net.neoforged.vsclc.attribute.ShortCmdBehaviour; +import net.neoforged.vsclc.writer.WritingMode; import org.apache.commons.lang3.StringUtils; import org.gradle.api.Action; import org.gradle.api.NamedDomainObjectContainer; @@ -218,6 +223,47 @@ public void eclipse(Project project, EclipseModel eclipse) { }); } + @Override + public void vscode(Project project, EclipseModel eclipse) + { + ProjectUtils.afterEvaluate(project, () -> { + final BatchedLaunchWriter launchWriter = new BatchedLaunchWriter(WritingMode.MODIFY_CURRENT); + project.getExtensions().configure(RunsConstants.Extensions.RUNS, (Action>) runs -> runs.getAsMap().forEach((name, run) -> { + final String runName = StringUtils.capitalize(project.getName() + " - " + StringUtils.capitalize(name.replace(" ", "-"))); + final RunImpl runImpl = (RunImpl) run; + final TaskProvider ideBeforeRunTask = createIdeBeforeRunTask(project, name, run, runImpl); + + final List> copyProcessResourcesTasks = createEclipseCopyResourcesTasks(eclipse, run); + ideBeforeRunTask.configure(task -> copyProcessResourcesTasks.forEach(t -> task.dependsOn(t))); + + final LaunchConfiguration cfg = launchWriter.createGroup("NG - " + project.getName(), WritingMode.REMOVE_EXISTING) + .createLaunchConfiguration() + .withAdditionalJvmArgs(runImpl.realiseJvmArguments()) + .withArguments(runImpl.getProgramArguments().get()) + .withCurrentWorkingDirectory(PathLike.ofNio(runImpl.getWorkingDirectory().get().getAsFile().toPath())) + .withEnvironmentVariables(adaptEnvironment(runImpl, RunsUtil::buildRunWithEclipseModClasses)) + .withShortenCommandLine(ShortCmdBehaviour.ARGUMENT_FILE) + .withMainClass(runImpl.getMainClass().get()) + .withProjectName(project.getName()) + .withName(runName); + + if (IdeManagementExtension.isVscodePluginImport(project)) + { + cfg.withPreTaskName("gradle: " + ideBeforeRunTask.getName()); + } + else + { + eclipse.autoBuildTasks(ideBeforeRunTask); + } + })); + try { + launchWriter.writeToLatestJson(project.getRootDir().toPath()); + } catch (final IOException e) { + throw new RuntimeException("Failed to write launch files", e); + } + }); + } + private static String quoteAndJoin(List args) { return quoteStream(args).collect(Collectors.joining(" ")); } diff --git a/gradle.properties b/gradle.properties index e912f02bd..2d2df3349 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,6 +28,7 @@ jetbrains_annotations_version=23.0.0 gradle_idea_extension_version=1.1.6 groovy_dsl_improver_version=1.0.15 eclipse_launch_configs_version=0.1.3 +vscode_launch_configs_version=1.0.8 #Test dependencies junit_version=5.9.2