Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
/// needing to duplicate code across projects.
///
/// @param <T> The type of target
public non-sealed abstract class EnhancedPlugin<T> implements Plugin<T>, EnhancedPluginAdditions {
public abstract non-sealed class EnhancedPlugin<T> implements Plugin<T>, EnhancedPluginAdditions {
private final String name;
private final String displayName;
private final @Nullable String toolsExtName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

/// This interface defines the additional methods added by [EnhancedPlugin]. They are additionally accessible in tasks
/// that implement [EnhancedTask].
public sealed interface EnhancedPluginAdditions permits EnhancedPlugin, EnhancedTask {
public sealed interface EnhancedPluginAdditions permits EnhancedPlugin, EnhancedTask, EnhancedTaskAdditions {
/// Gets a provider to the file for a [Tool] to be used. The tool's state is managed by Gradle through the
/// [org.gradle.api.provider.ValueSource] API and will not cause caching issues.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
/// The enhanced task contains a handful of helper methods to make working with the enhanced plugin and caches easier.
///
/// @param <P> The type of enhanced problems
public non-sealed interface EnhancedTask<P extends EnhancedProblems> extends Task, EnhancedPluginAdditions {
public non-sealed interface EnhancedTask<P extends EnhancedProblems> extends Task, EnhancedPluginAdditions, EnhancedTaskAdditions {
/// The enhanced plugin type for this task.
///
/// @return The plugin type
Expand All @@ -27,70 +27,14 @@ public non-sealed interface EnhancedTask<P extends EnhancedProblems> extends Tas
/// @return The problems type
Class<P> problemsType();

private EnhancedPlugin<? super Project> getPlugin() {
return this.getProject().getPlugins().getPlugin(this.pluginType());
}

@Override
default Tool.Resolved getTool(Tool tool) {
return this.getPlugin().getTool(tool);
}

@Override
default DirectoryProperty globalCaches() {
return this.getPlugin().globalCaches();
}

@Override
default DirectoryProperty localCaches() {
return this.getPlugin().localCaches();
}

@Override
default DirectoryProperty rootProjectDirectory() {
return this.getPlugin().rootProjectDirectory();
default EnhancedPlugin<? super Project> plugin() {
return this.getProject().getPlugins().getPlugin(this.pluginType());
}

@Override
default DirectoryProperty workingProjectDirectory() {
return this.getPlugin().workingProjectDirectory();
}

/// The default output directory to use for this task if it outputs a directory.
///
/// @return A provider for the directory
default @Internal Provider<Directory> getDefaultOutputDirectory() {
return this.localCaches().dir(this.getName()).map(this.getPlugin().getProblemsInternal().ensureFileLocation());
}

/// The default output file to use for this task if it outputs a file. Uses the `.jar` extension.
///
/// @return A provider for the file
default @Internal Provider<RegularFile> getDefaultOutputFile() {
return this.getDefaultOutputFile("jar");
}

/// The default output file to use for this task if it outputs a file.
///
/// @param ext The extension to use for the file
/// @return A provider for the file
default @Internal Provider<RegularFile> getDefaultOutputFile(String ext) {
return this.getOutputFile("output." + ext);
}

/// The default output log file to use for this task.
///
/// @return A provider for the file
default @Internal Provider<RegularFile> getDefaultLogFile() {
return this.getOutputFile("log.txt");
}

/// A file with the specified name in the default output directory.
///
/// @param fileName The name of the output file
/// @return A provider for the file
default @Internal Provider<RegularFile> getOutputFile(String fileName) {
return this.localCaches().file(String.format("%s/%s", this.getName(), fileName)).map(this.getPlugin().getProblemsInternal().ensureFileLocation());
default String baseName() {
return this.getName();
}

default void afterEvaluate(Action<? super Project> action) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package net.minecraftforge.gradleutils.shared;

import org.gradle.api.file.Directory;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFile;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Internal;

sealed interface EnhancedTaskAdditions extends EnhancedPluginAdditions permits EnhancedTask, ToolExecSpec {
EnhancedPlugin<?> plugin();

String baseName();

default Tool.Resolved getTool(Tool tool) {
return this.plugin().getTool(tool);
}

default DirectoryProperty globalCaches() {
return this.plugin().globalCaches();
}

default DirectoryProperty localCaches() {
return this.plugin().localCaches();
}

default DirectoryProperty rootProjectDirectory() {
return this.plugin().rootProjectDirectory();
}

default DirectoryProperty workingProjectDirectory() {
return this.plugin().workingProjectDirectory();
}

/// The default output directory to use for this task if it outputs a directory.
///
/// @return A provider for the directory
default @Internal Provider<Directory> getDefaultOutputDirectory() {
return this.localCaches().dir(this.baseName()).map(this.plugin().getProblemsInternal().ensureFileLocation());
}

/// The default output file to use for this task if it outputs a file. Uses the `.jar` extension.
///
/// @return A provider for the file
default @Internal Provider<RegularFile> getDefaultOutputFile() {
return this.getDefaultOutputFile("jar");
}

/// The default output file to use for this task if it outputs a file.
///
/// @param ext The extension to use for the file
/// @return A provider for the file
default @Internal Provider<RegularFile> getDefaultOutputFile(String ext) {
return this.getOutputFile("output." + ext);
}

/// The default output log file to use for this task.
///
/// @return A provider for the file
default @Internal Provider<RegularFile> getDefaultLogFile() {
return this.getOutputFile("log.txt");
}

/// A file with the specified name in the default output directory.
///
/// @param fileName The name of the output file
/// @return A provider for the file
default @Internal Provider<RegularFile> getOutputFile(String fileName) {
return this.localCaches().file(String.format("%s/%s", this.baseName(), fileName)).map(this.plugin().getProblemsInternal().ensureFileLocation());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package net.minecraftforge.gradleutils.shared;

import org.gradle.api.file.FileSystemLocation;
import org.gradle.api.file.FileSystemLocationProperty;
import org.gradle.api.provider.Provider;
import org.jetbrains.annotations.UnknownNullability;

import java.io.File;
import java.util.Map;

public interface ToolExecArgumentsCollector {
void args(Object... args);

void args(Iterable<?> args);

void args(String arg, Iterable<? extends File> files);

void args(String arg, FileSystemLocationProperty<? extends FileSystemLocation> fileProvider);

void args(String arg, @UnknownNullability Provider<?> provider);

void args(Map<?, ?> args);

void jvmArgs(Object... args);

void jvmArgs(Iterable<?> args);

void environment(String key, String value);

void systemProperty(String key, String value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package net.minecraftforge.gradleutils.shared;

import org.gradle.api.file.FileSystemLocation;
import org.gradle.api.file.FileSystemLocationProperty;
import org.gradle.api.provider.Provider;
import org.gradle.api.provider.ProviderConvertible;
import org.gradle.api.provider.ProviderFactory;
import org.jetbrains.annotations.UnknownNullability;

import javax.inject.Inject;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

abstract class ToolExecArgumentsCollectorImpl implements ToolExecArgumentsCollector {
final List<Provider<String>> args = new ArrayList<>();
final List<Provider<String>> jvmArgs = new ArrayList<>();
final Map<String, String> environment = new HashMap<>();
final Map<String, String> systemProperties = new HashMap<>();

protected abstract @Inject ProviderFactory getProviders();

@Inject
public ToolExecArgumentsCollectorImpl() { }

@Override
public void args(Object... args) {
this.args(Arrays.asList(args));
}

@Override
public void args(Iterable<?> args) {
try {
for (var arg : args) {
if (arg instanceof ProviderConvertible<?> providerConvertible)
this.args.add(providerConvertible.asProvider().map(Object::toString));
if (arg instanceof Provider<?> provider)
this.args.add(provider.map(Object::toString));
else
this.args.add(this.getProviders().provider(arg::toString));
}
} catch (NullPointerException e) {
throw new IllegalStateException("ToolExecBase#jvmArgs can only be called inside of #addArguments()", e);
}
}

/// Adds each file to the arguments preceded by the given argument. Designed to work well with
/// <a href="https://jopt-simple.github.io/jopt-simple/">JOpt Simple</a>.
///
/// @param arg The flag to use for each file
/// @param files The files to add
@Override
public void args(String arg, Iterable<? extends File> files) {
for (File file : files)
this.args(arg, file);
}

/// Adds the given argument followed by the given file location to the arguments.
///
/// @param arg The flag to use
/// @param fileProvider The file to add
@Override
public void args(String arg, FileSystemLocationProperty<? extends FileSystemLocation> fileProvider) {
this.args(arg, fileProvider.getLocationOnly());
}

/// Adds the given argument followed by the given object (may be a file location) to the arguments.
///
/// @param arg The flag to use
/// @param provider The object (or file) to add
@Override
public void args(String arg, @UnknownNullability Provider<?> provider) {
if (provider == null || !provider.isPresent()) return;

// NOTE: We don't use File#getAbsoluteFile because path sensitivity should be handled by tasks.
var value = provider.map(it -> it instanceof FileSystemLocation ? ((FileSystemLocation) it).getAsFile() : it).getOrNull();
if (value == null) return;

if (value instanceof Boolean booleanValue) {
if (booleanValue)
this.args(arg);
} else {
this.args(arg, String.valueOf(value));
}
}

/// Adds the given map of arguments.
///
/// [#args(String, Provider)] will be invoked for each entry in the map. If the key and/or value are not of the
/// required types, they will be automatically converted using [Object#toString()] and
/// [org.gradle.api.provider.ProviderFactory#provider(Callable)].
///
/// @param args The args to add
/// @deprecated Too ambiguous with [#args(String, Provider)]. Prefer that method instead.
@Override
@Deprecated(forRemoval = true)
public void args(Map<?, ?> args) {
for (Map.Entry<?, ?> entry : args.entrySet()) {
var key = entry.getKey();
var value = entry.getValue();
this.args(
key instanceof Provider<?> provider ? provider.map(Object::toString).get() : this.getProviders().provider(key::toString).get(),
value instanceof Provider<?> provider ? (provider instanceof FileSystemLocationProperty<?> file ? file.getLocationOnly() : provider) : this.getProviders().provider(() -> value)
);
}
}

@Override
public void jvmArgs(Object... args) {
try {
for (var arg : args) {
this.jvmArgs.add(this.getProviders().provider(arg::toString));
}
} catch (NullPointerException e) {
throw new IllegalStateException("ToolExecBase#jvmArgs can only be called inside of #addArguments()", e);
}
}

@Override
public void jvmArgs(Iterable<?> args) {
try {
for (var arg : args) {
this.jvmArgs.add(this.getProviders().provider(arg::toString));
}
} catch (NullPointerException e) {
throw new IllegalStateException("ToolExecBase#jvmArgs can only be called inside of #addArguments()", e);
}
}

@Override
public void environment(String key, String value) {
try {
this.environment.put(key, value);
} catch (NullPointerException e) {
throw new IllegalStateException("ToolExecBase#environment can only be called inside of #addArguments()", e);
}
}

@Override
public void systemProperty(String key, String value) {
try {
this.systemProperties.put(key, value);
} catch (NullPointerException e) {
throw new IllegalStateException("ToolExecBase#systemProperty can only be called inside of #addArguments()", e);
}
}
}
Loading