diff --git a/README.md b/README.md index 9c0c66207..9362c9cdb 100644 --- a/README.md +++ b/README.md @@ -237,33 +237,46 @@ Per SourceSet the following configurations are added, where XXX is the SourceSet > For this to work, your SourceSets need to be defined before your dependency block. Per Run the following configurations are added: -- XXXRunRuntime +- XXXRun +- XXXMod > [!NOTE] > For this to work, your Runs need to be defined before your dependency block. Globally the following configurations are added: -- runRuntime +- runs +- mods #### LocalRuntime (Per SourceSet) This configuration is used to add dependencies to your local projects runtime only, without exposing them to the runtime of other projects. #### LocalRunRuntime (Per SourceSet) This configuration is used to add dependencies to the local runtime of the runs you add the SourceSets too, without exposing them to the runtime of other runs. -This requires automatic dependency injection from sourcesets per run to be enabled (see below). -#### RunRuntime (Per Run) +#### Run (Per Run) This configuration is used to add dependencies to the runtime of a specific run only, without exposing them to the runtime of other runs. -#### runRuntime (Global) +#### Mod (Per Run) +This configuration is used to add dependencies (and their dependencies), straight into the mods folder, without exposing them to the runtime of the run itself, or other runs. + +#### run (Global) This configuration is used to add dependencies to the runtime of all runs. +#### mods (Global) +This configuration is used to add dependencies (and their dependencies), straight into the mods folder of all runs, without exposing them to the runtime of the runs. + ### Sourceset Management +To disable the sourceset management, you can set the following property in your gradle.properties: +```properties +neogradle.subsystems.conventions.sourceset.enabled=false +``` + #### Automatic inclusion of the current project in its runs By default, the current project is automatically included in its runs. If you want to disable this, you can set the following property in your gradle.properties: ```properties neogradle.subsystems.conventions.sourceset.automatic-inclusion=false ``` + This is equivalent to setting the following in your build.gradle: ```groovy runs { @@ -327,3 +340,16 @@ idea { } } ``` + +### Runs +To disable the runs conventions, you can set the following property in your gradle.properties: +```properties +neogradle.subsystems.conventions.runs.enabled=false +``` + +#### Automatic default run per type +By default, a run is created for each type of run. +If you want to disable this, you can set the following property in your gradle.properties: +```properties +neogradle.subsystems.conventions.runs.create-default-run-per-type=false +``` \ No newline at end of file diff --git a/common/src/main/java/net/neoforged/gradle/common/CommonProjectPlugin.java b/common/src/main/java/net/neoforged/gradle/common/CommonProjectPlugin.java index e9216d00b..8b7f75ef8 100644 --- a/common/src/main/java/net/neoforged/gradle/common/CommonProjectPlugin.java +++ b/common/src/main/java/net/neoforged/gradle/common/CommonProjectPlugin.java @@ -22,6 +22,8 @@ import net.neoforged.gradle.common.runtime.extensions.RuntimesExtension; import net.neoforged.gradle.common.runtime.naming.OfficialNamingChannelConfigurator; import net.neoforged.gradle.common.tasks.DisplayMappingsLicenseTask; +import net.neoforged.gradle.common.util.DelegatingDomainObjectContainer; +import net.neoforged.gradle.common.util.ProjectUtils; import net.neoforged.gradle.common.util.TaskDependencyUtils; import net.neoforged.gradle.common.util.constants.RunsConstants; import net.neoforged.gradle.common.util.exceptions.MultipleDefinitionsFoundException; @@ -36,26 +38,30 @@ import net.neoforged.gradle.dsl.common.extensions.RunnableSourceSet; import net.neoforged.gradle.dsl.common.extensions.dependency.replacement.DependencyReplacement; import net.neoforged.gradle.dsl.common.extensions.repository.Repository; +import net.neoforged.gradle.dsl.common.extensions.subsystems.Conventions; import net.neoforged.gradle.dsl.common.extensions.subsystems.Subsystems; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.Configurations; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.IDE; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.Runs; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.SourceSets; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.ide.IDEA; import net.neoforged.gradle.dsl.common.runs.run.Run; import net.neoforged.gradle.dsl.common.runs.type.RunType; +import net.neoforged.gradle.dsl.common.util.ConfigurationUtils; import net.neoforged.gradle.dsl.common.util.NamingConstants; import net.neoforged.gradle.util.UrlConstants; -import org.gradle.api.Action; -import org.gradle.api.NamedDomainObjectContainer; -import org.gradle.api.Plugin; -import org.gradle.api.Project; +import org.gradle.api.*; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; import org.gradle.api.attributes.AttributeContainer; import org.gradle.api.attributes.Category; import org.gradle.api.component.AdhocComponentWithVariants; import org.gradle.api.plugins.JavaPlugin; -import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Delete; import org.gradle.api.tasks.SourceSetContainer; import org.gradle.plugins.ide.eclipse.EclipsePlugin; import org.gradle.plugins.ide.idea.IdeaPlugin; +import org.jetbrains.annotations.Nullable; import org.jetbrains.gradle.ext.IdeaExtPlugin; import java.util.HashSet; @@ -63,14 +69,14 @@ import java.util.Set; public class CommonProjectPlugin implements Plugin { - + public static final String ASSETS_SERVICE = "ng_assets"; public static final String LIBRARIES_SERVICE = "ng_libraries"; public static final String ACCESS_TRANSFORMER_ELEMENTS_CONFIGURATION = "accessTransformerElements"; public static final String ACCESS_TRANSFORMER_API_CONFIGURATION = "accessTransformerApi"; public static final String ACCESS_TRANSFORMER_CONFIGURATION = "accessTransformer"; static final String ACCESS_TRANSFORMER_CATEGORY = "accesstransformer"; - + @Override public void apply(Project project) { //Apply the evaluation extension to monitor immediate execution of indirect tasks when evaluation already happened. @@ -87,7 +93,7 @@ public void apply(Project project) { project.getRootProject().getPluginManager().apply(IdeaExtPlugin.class); project.getPluginManager().apply(IdeaExtPlugin.class); project.getPluginManager().apply(EclipsePlugin.class); - + project.getExtensions().create("allRuntimes", RuntimesExtension.class); project.getExtensions().create(IdeManagementExtension.class, "ideManager", IdeManagementExtension.class, project); project.getExtensions().create(ArtifactDownloader.class, "artifactDownloader", ArtifactDownloaderExtension.class, project); @@ -97,7 +103,7 @@ public void apply(Project project) { AccessTransformers accessTransformers = project.getExtensions().create(AccessTransformers.class, "accessTransformers", AccessTransformersExtension.class, project); project.getExtensions().create("extensionManager", ExtensionManager.class, project); project.getExtensions().create("clientExtraJarDependencyManager", ExtraJarDependencyManager.class, project); - final ConfigurationData configurationData = project.getExtensions().create( ConfigurationData.class, "configurationData", ConfigurationDataExtension.class, project); + final ConfigurationData configurationData = project.getExtensions().create(ConfigurationData.class, "configurationData", ConfigurationDataExtension.class, project); final ExtensionManager extensionManager = project.getExtensions().getByType(ExtensionManager.class); @@ -112,7 +118,7 @@ public void apply(Project project) { final Mappings mappings = project.getExtensions().getByType(Mappings.class); if (mappings.getChannel().get().getHasAcceptedLicense().get()) return null; - + return mappings.getChannel().get().getLicenseText().get(); })); }); @@ -122,31 +128,151 @@ public void apply(Project project) { e.metadataSources(MavenArtifactRepository.MetadataSources::artifact); }); - project.afterEvaluate(this::applyAfterEvaluate); - project.getExtensions().getByType(SourceSetContainer.class).configureEach(sourceSet -> { sourceSet.getExtensions().create(ProjectHolder.class, ProjectHolderExtension.NAME, ProjectHolderExtension.class, project); sourceSet.getExtensions().create(RunnableSourceSet.NAME, RunnableSourceSet.class, project); sourceSet.getExtensions().add("runtimeDefinition", project.getObjects().property(CommonRuntimeDefinition.class)); + + sourceSet.getExtensions().add("configurations", project.getObjects().domainObjectContainer(Configuration.class)); + final NamedDomainObjectCollection sourceSetConfigurations = new DelegatingDomainObjectContainer((NamedDomainObjectContainer) sourceSet.getExtensions().getByName("configurations")) { + @Override + public boolean add(@Nullable Configuration e) { + if (e == null) + return false; + + return super.add(e); + } + }; + + //Add the gradle default configurations + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getApiConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getApiElementsConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getImplementationConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getCompileOnlyConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getCompileOnlyApiConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getCompileClasspathConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getAnnotationProcessorConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getRuntimeOnlyConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getRuntimeClasspathConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getRuntimeElementsConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getJavadocElementsConfigurationName())); + sourceSetConfigurations.add(project.getConfigurations().findByName(sourceSet.getSourcesElementsConfigurationName())); }); project.getExtensions().add( RunsConstants.Extensions.RUN_TYPES, project.getObjects().domainObjectContainer(RunType.class, name -> project.getObjects().newInstance(RunType.class, name)) ); - + project.getExtensions().add( RunsConstants.Extensions.RUNS, project.getObjects().domainObjectContainer(Run.class, name -> RunsUtil.create(project, name)) ); setupAccessTransformerConfigurations(project, accessTransformers); - + IdeRunIntegrationManager.getInstance().setup(project); project.getTasks().named("clean", Delete.class, delete -> { delete.delete(configurationData.getLocation()); }); + + //Needs to be before after evaluate + configureConventions(project); + + project.afterEvaluate(this::applyAfterEvaluate); + } + + private void configureConventions(Project project) { + final Conventions conventions = project.getExtensions().getByType(Subsystems.class).getConventions(); + if (!conventions.getIsEnabled().get()) + return; + + configureRunConventions(project, conventions); + configureSourceSetConventions(project, conventions); + configureIDEConventions(project, conventions); + } + + private void configureSourceSetConventions(Project project, Conventions conventions) { + final SourceSets sourceSets = conventions.getSourceSets(); + final Configurations configurations = conventions.getConfigurations(); + + if (!sourceSets.getIsEnabled().get()) + return; + + if (configurations.getIsEnabled().get()) { + project.getExtensions().getByType(SourceSetContainer.class).configureEach(sourceSet -> { + final NamedDomainObjectCollection sourceSetConfigurations = (NamedDomainObjectCollection) sourceSet.getExtensions().getByName("configurations"); + + sourceSetConfigurations.add(project.getConfigurations().create(ConfigurationUtils.getSourceSetName(sourceSet, configurations.getLocalRuntimeConfigurationPostFix().get()))); + sourceSetConfigurations.add(project.getConfigurations().create(ConfigurationUtils.getSourceSetName(sourceSet, configurations.getRunRuntimeConfigurationPostFix().get()))); + }); + } + + ProjectUtils.afterEvaluate(project, () -> { + project.getExtensions().configure(RunsConstants.Extensions.RUNS, (Action>) runs -> runs.configureEach(run -> { + if (sourceSets.getShouldMainSourceSetBeAutomaticallyAddedToRuns().get()) + run.getModSources().add(project.getExtensions().getByType(SourceSetContainer.class).getByName("main")); + + if (sourceSets.getShouldSourceSetsLocalRunRuntimesBeAutomaticallyAddedToRuns().get() && configurations.getIsEnabled().get()) + run.getModSources().get().forEach(sourceSet -> { + final NamedDomainObjectCollection sourceSetConfigurations = (NamedDomainObjectCollection) sourceSet.getExtensions().getByName("configurations"); + run.getDependencies().get().getRuntime().add(sourceSetConfigurations.getByName(ConfigurationUtils.getSourceSetName(sourceSet, configurations.getRunRuntimeConfigurationPostFix().get()))); + }); + })); + }); + + } + + private void configureRunConventions(Project project, Conventions conventions) { + final Configurations configurations = conventions.getConfigurations(); + final Runs runs = conventions.getRuns(); + + if (!configurations.getIsEnabled().get()) + return; + + final Configuration runRuntimeConfiguration = project.getConfigurations().create(configurations.getRunRuntimeConfigurationName().get()); + final Configuration runModsConfiguration = project.getConfigurations().create(configurations.getRunModsConfigurationName().get()); + + if (runs.getShouldDefaultRunsBeCreated().get()) { + project.getExtensions().configure(RunsConstants.Extensions.RUN_TYPES, (Action>) runTypesContainer -> runTypesContainer.configureEach(runType -> { + project.getExtensions().configure(RunsConstants.Extensions.RUNS, (Action>) runContainer -> { + if (runContainer.getAsMap().containsKey(runType.getName())) + return; + + runContainer.create(runType.getName(), run -> { + run.configure(runType); + }); + }); + })); + } + + project.getExtensions().configure(RunsConstants.Extensions.RUNS, (Action>) runContainer -> runContainer.configureEach(run -> { + final Configuration runSpecificRuntimeConfiguration = project.getConfigurations().create(ConfigurationUtils.getRunName(run, configurations.getPerRunRuntimeConfigurationPostFix().get())); + final Configuration runSpecificModsConfiguration = project.getConfigurations().create(ConfigurationUtils.getRunName(run, configurations.getPerRunModsConfigurationPostFix().get())); + + run.getDependencies().get().getRuntime().add(runRuntimeConfiguration); + run.getDependencies().get().getMod().add(runModsConfiguration); + + run.getDependencies().get().getRuntime().add(runSpecificRuntimeConfiguration); + run.getDependencies().get().getMod().add(runSpecificModsConfiguration); + })); + } + + private void configureIDEConventions(Project project, Conventions conventions) { + final IDE ideConventions = conventions.getIde(); + if (!ideConventions.getIsEnabled().get()) + return; + + configureIDEAIDEConventions(project, ideConventions); + } + + private void configureIDEAIDEConventions(Project project, IDE ideConventions) { + final IDEA ideaConventions = ideConventions.getIdea(); + if (!ideaConventions.getIsEnabled().get()) + return; + + IdeRunIntegrationManager.getInstance().configureIdeaConventions(project, ideaConventions); } @SuppressWarnings("UnstableApiUsage") @@ -177,7 +303,8 @@ private void setupAccessTransformerConfigurations(Project project, AccessTransfo // Now we set up the component, conditionally AdhocComponentWithVariants java = (AdhocComponentWithVariants) project.getComponents().getByName("java"); - Runnable enable = () -> java.addVariantsFromConfiguration(accessTransformerElements, variant -> {}); + Runnable enable = () -> java.addVariantsFromConfiguration(accessTransformerElements, variant -> { + }); accessTransformerElements.getAllDependencies().configureEach(dep -> enable.run()); accessTransformerElements.getArtifacts().configureEach(artifact -> enable.run()); @@ -209,9 +336,9 @@ private void applyAfterEvaluate(final Project project) { if (run.getConfigureFromDependencies().get()) { final RunImpl runImpl = (RunImpl) run; - + final Set> definitionSet = new HashSet<>(); - + runImpl.getModSources().get().forEach(sourceSet -> { try { final Optional> definition = TaskDependencyUtils.findRuntimeDefinition(project, sourceSet); @@ -220,14 +347,14 @@ private void applyAfterEvaluate(final Project project) { throw new RuntimeException("Failed to configure run: " + run.getName() + " there are multiple runtime definitions found for the source set: " + sourceSet.getName(), e); } }); - + definitionSet.forEach(definition -> { - definition.configureRun(runImpl); + definition.configureRun(runImpl); }); } } })); - + IdeRunIntegrationManager.getInstance().apply(project); } } diff --git a/common/src/main/java/net/neoforged/gradle/common/extensions/base/WithEnabledProperty.java b/common/src/main/java/net/neoforged/gradle/common/extensions/base/WithEnabledProperty.java new file mode 100644 index 000000000..8b770cf54 --- /dev/null +++ b/common/src/main/java/net/neoforged/gradle/common/extensions/base/WithEnabledProperty.java @@ -0,0 +1,47 @@ +package net.neoforged.gradle.common.extensions.base; + +import org.gradle.api.Project; +import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; + +import java.util.List; + +public abstract class WithEnabledProperty extends WithPropertyLookup { + + private final String prefix; + + public WithEnabledProperty(Project project, String prefix) { + super(project); + this.prefix = prefix; + + getIsEnabled().convention( + getBooleanProperty("enabled").orElse(true) + ); + }; + + public WithEnabledProperty(WithEnabledProperty parent, String prefix) { + super(parent.project); + + this.prefix = String.format("%s.%s", parent.prefix, prefix); + getIsEnabled().convention( + parent.getIsEnabled().zip(getBooleanProperty("enabled"), (parentEnabled, enabled) -> parentEnabled && enabled).orElse(true) + ); + } + + public abstract Property getIsEnabled(); + + @Override + protected Provider getStringProperty(String propertyName) { + return super.getStringProperty(String.format("%s.%s", prefix, propertyName)); + } + + @Override + protected Provider getBooleanProperty(String propertyName) { + return super.getBooleanProperty(String.format("%s.%s", prefix, propertyName)); + } + + @Override + protected Provider> getSpaceSeparatedListProperty(String propertyName) { + return super.getSpaceSeparatedListProperty(String.format("%s.%s", prefix, propertyName)); + } +} diff --git a/common/src/main/java/net/neoforged/gradle/common/extensions/base/WithPropertyLookup.java b/common/src/main/java/net/neoforged/gradle/common/extensions/base/WithPropertyLookup.java new file mode 100644 index 000000000..2fa5b43a1 --- /dev/null +++ b/common/src/main/java/net/neoforged/gradle/common/extensions/base/WithPropertyLookup.java @@ -0,0 +1,43 @@ +package net.neoforged.gradle.common.extensions.base; + +import org.gradle.api.GradleException; +import org.gradle.api.Project; +import org.gradle.api.provider.Provider; + +import java.util.Arrays; +import java.util.List; + +import static net.neoforged.gradle.dsl.common.util.Constants.SUBSYSTEM_PROPERTY_PREFIX; + +public abstract class WithPropertyLookup { + protected final Project project; + + public WithPropertyLookup(Project project) { + this.project = project; + } + + protected Provider getStringProperty(String propertyName) { + return this.project.getProviders().gradleProperty(SUBSYSTEM_PROPERTY_PREFIX + propertyName); + } + + protected Provider getBooleanProperty(String propertyName) { + String fullPropertyName = SUBSYSTEM_PROPERTY_PREFIX + propertyName; + return this.project.getProviders().gradleProperty(fullPropertyName) + .map(value -> { + try { + return Boolean.valueOf(value); + } catch (Exception e) { + throw new GradleException("Gradle Property " + fullPropertyName + " is not set to a boolean value: '" + value + "'"); + } + }); + } + + protected Provider> getSpaceSeparatedListProperty(String propertyName) { + return this.project.getProviders().gradleProperty(SUBSYSTEM_PROPERTY_PREFIX + propertyName) + .map(s -> Arrays.asList(s.split("\\s+"))); + } + + public Project getProject() { + return project; + } +} diff --git a/common/src/main/java/net/neoforged/gradle/common/extensions/subsystems/ConventionsExtension.java b/common/src/main/java/net/neoforged/gradle/common/extensions/subsystems/ConventionsExtension.java new file mode 100644 index 000000000..8d68cc23f --- /dev/null +++ b/common/src/main/java/net/neoforged/gradle/common/extensions/subsystems/ConventionsExtension.java @@ -0,0 +1,116 @@ +package net.neoforged.gradle.common.extensions.subsystems; + +import net.minecraftforge.gdi.BaseDSLElement; +import net.neoforged.gradle.common.extensions.base.WithEnabledProperty; +import net.neoforged.gradle.dsl.common.extensions.subsystems.Conventions; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.Configurations; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.IDE; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.Runs; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.SourceSets; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.ide.IDEA; +import org.gradle.api.Project; +import org.gradle.api.provider.Property; + +import javax.inject.Inject; + +public abstract class ConventionsExtension extends WithEnabledProperty implements BaseDSLElement, Conventions { + + private final Configurations configurations; + private final SourceSets sourceSets; + private final IDE ide; + private final Runs runs; + + @Inject + public ConventionsExtension(Project project) { + super(project, "conventions"); + + this.configurations = project.getObjects().newInstance(ConfigurationsExtension.class, this); + this.sourceSets = project.getObjects().newInstance(SourceSetsExtension.class, this); + this.ide = project.getObjects().newInstance(IDEExtension.class, this); + this.runs = project.getObjects().newInstance(RunsExtension.class, this); + } + + @Override + public Configurations getConfigurations() { + return configurations; + } + + @Override + public SourceSets getSourceSets() { + return sourceSets; + } + + @Override + public IDE getIde() { + return ide; + } + + @Override + public Runs getRuns() { + return runs; + } + + public static abstract class ConfigurationsExtension extends WithEnabledProperty implements BaseDSLElement, Configurations { + + @Inject + public ConfigurationsExtension(WithEnabledProperty parent) { + super(parent, "configurations"); + + getLocalRuntimeConfigurationPostFix().convention(getStringProperty("localRuntimeConfigurationPostFix").orElse("LocalRuntime")); + getRunRuntimeConfigurationPostFix().convention(getStringProperty("perSourceSetRunRuntimeConfigurationPostFix").orElse("LocalRunRuntime")); + getPerRunRuntimeConfigurationPostFix().convention(getStringProperty("perRunRuntimeConfigurationPostFix").orElse("Run")); + getPerRunModsConfigurationPostFix().convention(getStringProperty("perRunModsConfigurationPostFix").orElse("Mod")); + getRunRuntimeConfigurationName().convention(getStringProperty("runRuntimeConfigurationName").orElse("runs")); + getRunModsConfigurationName().convention(getStringProperty("runModsConfigurationName").orElse("mods")); + } + } + + public static abstract class SourceSetsExtension extends WithEnabledProperty implements BaseDSLElement, SourceSets { + + @Inject + public SourceSetsExtension(WithEnabledProperty parent) { + super(parent, "sourceSets"); + + getShouldMainSourceSetBeAutomaticallyAddedToRuns().convention(getBooleanProperty("automatic-inclusion").orElse(true)); + getShouldSourceSetsLocalRunRuntimesBeAutomaticallyAddedToRuns().convention(getBooleanProperty("automatic-inclusion-local-run-runtime").orElse(true)); + } + } + + public static abstract class IDEExtension extends WithEnabledProperty implements BaseDSLElement, IDE { + + private final IDEA idea; + + @Inject + public IDEExtension(WithEnabledProperty parent) { + super(parent, "ide"); + + this.idea = getProject().getObjects().newInstance(IDEAExtension.class, this); + } + + @Override + public IDEA getIdea() { + return idea; + } + } + + public static abstract class RunsExtension extends WithEnabledProperty implements BaseDSLElement, Runs { + + @Inject + public RunsExtension(WithEnabledProperty parent) { + super(parent, "runs"); + + getShouldDefaultRunsBeCreated().convention(getBooleanProperty("create-default-run-per-type").orElse(true)); + } + } + + public static abstract class IDEAExtension extends WithEnabledProperty implements BaseDSLElement, IDEA { + + @Inject + public IDEAExtension(WithEnabledProperty parent) { + super(parent, "idea"); + + getShouldUseCompilerDetection().convention(getBooleanProperty("compiler-detection").orElse(true)); + getCompilerOutputDir().convention(getProject().getLayout().getProjectDirectory().dir(getStringProperty("compiler-output-dir").orElse("out"))); + } + } +} diff --git a/common/src/main/java/net/neoforged/gradle/common/extensions/subsystems/SubsystemsExtension.java b/common/src/main/java/net/neoforged/gradle/common/extensions/subsystems/SubsystemsExtension.java index 7d907b276..6a9c62c2c 100644 --- a/common/src/main/java/net/neoforged/gradle/common/extensions/subsystems/SubsystemsExtension.java +++ b/common/src/main/java/net/neoforged/gradle/common/extensions/subsystems/SubsystemsExtension.java @@ -1,21 +1,16 @@ package net.neoforged.gradle.common.extensions.subsystems; import net.minecraftforge.gdi.ConfigurableDSLElement; -import net.neoforged.gradle.dsl.common.extensions.subsystems.Decompiler; -import net.neoforged.gradle.dsl.common.extensions.subsystems.DecompilerLogLevel; -import net.neoforged.gradle.dsl.common.extensions.subsystems.Parchment; -import net.neoforged.gradle.dsl.common.extensions.subsystems.Recompiler; -import net.neoforged.gradle.dsl.common.extensions.subsystems.Subsystems; +import net.neoforged.gradle.common.extensions.base.WithPropertyLookup; +import net.neoforged.gradle.dsl.common.extensions.subsystems.*; import org.gradle.api.GradleException; import org.gradle.api.Project; import org.gradle.api.artifacts.repositories.MavenArtifactRepository; -import org.gradle.api.provider.Provider; import javax.inject.Inject; import java.net.URI; import java.util.Arrays; import java.util.Collections; -import java.util.List; import java.util.Locale; import static net.neoforged.gradle.dsl.common.util.Constants.DEFAULT_PARCHMENT_ARTIFACT_PREFIX; @@ -23,15 +18,16 @@ import static net.neoforged.gradle.dsl.common.util.Constants.DEFAULT_PARCHMENT_MAVEN_URL; import static net.neoforged.gradle.dsl.common.util.Constants.DEFAULT_PARCHMENT_TOOL_ARTIFACT; import static net.neoforged.gradle.dsl.common.util.Constants.DEFAULT_RECOMPILER_MAX_MEMORY; -import static net.neoforged.gradle.dsl.common.util.Constants.SUBSYSTEM_PROPERTY_PREFIX; -public abstract class SubsystemsExtension implements ConfigurableDSLElement, Subsystems { +public abstract class SubsystemsExtension extends WithPropertyLookup implements ConfigurableDSLElement, Subsystems { - private final Project project; + private final Conventions conventions; @Inject public SubsystemsExtension(Project project) { - this.project = project; + super(project); + + this.conventions = project.getObjects().newInstance(ConventionsExtension.class, project); configureDecompilerDefaults(); configureRecompilerDefaults(); @@ -106,29 +102,8 @@ private void configureParchmentDefaults() { }); } - private Provider getStringProperty(String propertyName) { - return this.project.getProviders().gradleProperty(SUBSYSTEM_PROPERTY_PREFIX + propertyName); - } - - private Provider getBooleanProperty(String propertyName) { - String fullPropertyName = SUBSYSTEM_PROPERTY_PREFIX + propertyName; - return this.project.getProviders().gradleProperty(fullPropertyName) - .map(value -> { - try { - return Boolean.valueOf(value); - } catch (Exception e) { - throw new GradleException("Gradle Property " + fullPropertyName + " is not set to a boolean value: '" + value + "'"); - } - }); - } - - private Provider> getSpaceSeparatedListProperty(String propertyName) { - return this.project.getProviders().gradleProperty(SUBSYSTEM_PROPERTY_PREFIX + propertyName) - .map(s -> Arrays.asList(s.split("\\s+"))); - } - @Override - public Project getProject() { - return project; + public Conventions getConventions() { + return conventions; } } 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 cdfd7fd99..2a0cb7a28 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 @@ -11,10 +11,12 @@ import net.neoforged.gradle.common.util.SourceSetUtils; import net.neoforged.gradle.common.util.constants.RunsConstants; import net.neoforged.gradle.common.util.run.RunsUtil; +import net.neoforged.gradle.dsl.common.extensions.subsystems.conventions.ide.IDEA; import net.neoforged.gradle.dsl.common.runs.ide.extensions.IdeaRunExtension; import net.neoforged.gradle.dsl.common.runs.idea.extensions.IdeaRunsExtension; import net.neoforged.gradle.dsl.common.runs.run.Run; import net.neoforged.gradle.dsl.common.util.CommonRuntimeUtils; +import net.neoforged.gradle.util.FileUtils; import org.apache.commons.lang3.StringUtils; import org.gradle.api.Action; import org.gradle.api.NamedDomainObjectContainer; @@ -91,7 +93,32 @@ public void apply(final Project project) { ideManager.apply(new RunsImportAction()); }); } - + + public void configureIdeaConventions(Project project, IDEA ideaConventions) { + final Project rootProject = project.getRootProject(); + final IdeaModel ideaModel = rootProject.getExtensions().getByType(IdeaModel.class); + final IdeaProject ideaProject = ideaModel.getProject(); + final ExtensionAware extensionAware = (ExtensionAware) ideaProject; + final IdeaRunsExtension runsExtension = extensionAware.getExtensions().getByType(IdeaRunsExtension.class); + + runsExtension.getRunWithIdea().convention( + ideaConventions.getShouldUseCompilerDetection() + .map(useCompilerDetection -> { + if (!useCompilerDetection) { + return false; + } + + final File DotIdeaDirectory = new File(project.getProjectDir(), ".idea"); + final File GradleXml = new File(DotIdeaDirectory, "gradle.xml"); + return FileUtils.contains(GradleXml, "