Decompiler API improvements:
* Fix decompiler tasks getting registered in afterEvaluate * Allow decompilers to add file collections to the forked JVM classpath. * General code cleanup.
This commit is contained in:
		
							parent
							
								
									e4244dc895
								
							
						
					
					
						commit
						53b839b739
					
				
					 9 changed files with 106 additions and 73 deletions
				
			
		|  | @ -25,6 +25,7 @@ | |||
| package net.fabricmc.loom.api; | ||||
| 
 | ||||
| import org.gradle.api.Action; | ||||
| import org.gradle.api.DomainObjectCollection; | ||||
| import org.gradle.api.NamedDomainObjectContainer; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
| import org.gradle.api.file.ConfigurableFileCollection; | ||||
|  | @ -55,7 +56,7 @@ public interface LoomGradleExtensionAPI { | |||
| 		getShareRemapCaches().set(true); | ||||
| 	} | ||||
| 
 | ||||
| 	ListProperty<LoomDecompiler> getGameDecompilers(); | ||||
| 	DomainObjectCollection<LoomDecompiler> getGameDecompilers(); | ||||
| 
 | ||||
| 	default void addDecompiler(LoomDecompiler decompiler) { | ||||
| 		getGameDecompilers().add(decompiler); | ||||
|  |  | |||
|  | @ -26,6 +26,10 @@ package net.fabricmc.loom.api.decompilers; | |||
| 
 | ||||
| import java.nio.file.Path; | ||||
| 
 | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.file.FileCollection; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| 
 | ||||
| public interface LoomDecompiler { | ||||
| 	String name(); | ||||
| 
 | ||||
|  | @ -37,4 +41,12 @@ public interface LoomDecompiler { | |||
| 	 * @param metaData Additional information that may or may not be needed while decompiling | ||||
| 	 */ | ||||
| 	void decompile(Path compiledJar, Path sourcesDestination, Path linemapDestination, DecompilationMetadata metaData); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Add additional classpath entries to the decompiler classpath, can return a configuration. | ||||
| 	 */ | ||||
| 	@Nullable | ||||
| 	default FileCollection getBootstrapClasspath(Project project) { | ||||
| 		return null; | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.configuration; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| 
 | ||||
| import org.gradle.api.NamedDomainObjectProvider; | ||||
|  | @ -33,6 +34,7 @@ import org.gradle.api.plugins.JavaPlugin; | |||
| import org.gradle.api.plugins.JavaPluginExtension; | ||||
| import org.gradle.api.tasks.AbstractCopyTask; | ||||
| import org.gradle.api.tasks.SourceSet; | ||||
| import org.gradle.api.tasks.TaskContainer; | ||||
| import org.gradle.api.tasks.compile.JavaCompile; | ||||
| import org.gradle.api.tasks.javadoc.Javadoc; | ||||
| 
 | ||||
|  | @ -44,6 +46,8 @@ import net.fabricmc.loom.configuration.providers.LaunchProvider; | |||
| import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.extension.MixinExtension; | ||||
| import net.fabricmc.loom.task.GenerateSourcesTask; | ||||
| import net.fabricmc.loom.task.UnpickJarTask; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| 
 | ||||
| public final class CompileConfiguration { | ||||
|  | @ -125,10 +129,10 @@ public final class CompileConfiguration { | |||
| 		final JavaPluginExtension javaPluginExtension = p.getExtensions().getByType(JavaPluginExtension.class); | ||||
| 		LoomGradleExtension extension = LoomGradleExtension.get(p); | ||||
| 
 | ||||
| 		SourceSet main = javaPluginExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME); | ||||
| 
 | ||||
| 		Javadoc javadoc = (Javadoc) p.getTasks().getByName(JavaPlugin.JAVADOC_TASK_NAME); | ||||
| 		p.getTasks().named(JavaPlugin.JAVADOC_TASK_NAME, Javadoc.class).configure(javadoc -> { | ||||
| 			final SourceSet main = javaPluginExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME); | ||||
| 			javadoc.setClasspath(main.getOutput().plus(main.getCompileClasspath())); | ||||
| 		}); | ||||
| 
 | ||||
| 		p.afterEvaluate(project -> { | ||||
| 			LoomDependencyManager dependencyManager = new LoomDependencyManager(); | ||||
|  | @ -140,10 +144,6 @@ public final class CompileConfiguration { | |||
| 
 | ||||
| 			dependencyManager.handleDependencies(project); | ||||
| 
 | ||||
| 			project.getTasks().getByName("idea").finalizedBy(project.getTasks().getByName("genIdeaWorkspace")); | ||||
| 			project.getTasks().getByName("eclipse").finalizedBy(project.getTasks().getByName("genEclipseRuns")); | ||||
| 			project.getTasks().getByName("cleanEclipse").finalizedBy(project.getTasks().getByName("cleanEclipseRuns")); | ||||
| 
 | ||||
| 			extension.getRemapArchives().finalizeValue(); | ||||
| 
 | ||||
| 			MixinExtension mixin = LoomGradleExtension.get(project).getMixin(); | ||||
|  | @ -151,10 +151,16 @@ public final class CompileConfiguration { | |||
| 			if (mixin.getUseLegacyMixinAp().get()) { | ||||
| 				setupMixinAp(project, mixin); | ||||
| 			} | ||||
| 
 | ||||
| 			configureDecompileTasks(project); | ||||
| 		}); | ||||
| 
 | ||||
| 		finalizedBy(p, "idea", "genIdeaWorkspace"); | ||||
| 		finalizedBy(p, "eclipse", "genEclipseRuns"); | ||||
| 		finalizedBy(p, "cleanEclipse", "cleanEclipseRuns"); | ||||
| 
 | ||||
| 		// Add the "dev" jar to the "namedElements" configuration | ||||
| 		p.artifacts(artifactHandler -> artifactHandler.add(Constants.Configurations.NAMED_ELEMENTS, p.getTasks().getByName("jar"))); | ||||
| 		p.artifacts(artifactHandler -> artifactHandler.add(Constants.Configurations.NAMED_ELEMENTS, p.getTasks().named("jar"))); | ||||
| 
 | ||||
| 		// Ensure that the encoding is set to UTF-8, no matter what the system default is | ||||
| 		// this fixes some edge cases with special characters not displaying correctly | ||||
|  | @ -191,7 +197,47 @@ public final class CompileConfiguration { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private static void configureDecompileTasks(Project project) { | ||||
| 		final TaskContainer tasks = project.getTasks(); | ||||
| 		final LoomGradleExtension extension = LoomGradleExtension.get(project); | ||||
| 
 | ||||
| 		MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
| 		File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||
| 
 | ||||
| 		if (mappingsProvider.hasUnpickDefinitions()) { | ||||
| 			File outputJar = mappingsProvider.mappedProvider.getUnpickedJar(); | ||||
| 
 | ||||
| 			tasks.register("unpickJar", UnpickJarTask.class, unpickJarTask -> { | ||||
| 				unpickJarTask.getUnpickDefinitions().set(mappingsProvider.getUnpickDefinitionsFile()); | ||||
| 				unpickJarTask.getInputJar().set(mappingsProvider.mappedProvider.getMappedJar()); | ||||
| 				unpickJarTask.getOutputJar().set(outputJar); | ||||
| 			}); | ||||
| 
 | ||||
| 			mappedJar = outputJar; | ||||
| 		} | ||||
| 
 | ||||
| 		final File inputJar = mappedJar; | ||||
| 
 | ||||
| 		extension.getGameDecompilers().configureEach(decompiler -> { | ||||
| 			String taskName = "genSourcesWith" + decompiler.name(); | ||||
| 
 | ||||
| 			// Set the input jar for the task after evaluation has occurred. | ||||
| 			tasks.named(taskName, GenerateSourcesTask.class).configure(task -> { | ||||
| 				task.getInputJar().set(inputJar); | ||||
| 
 | ||||
| 				if (mappingsProvider.hasUnpickDefinitions()) { | ||||
| 					task.dependsOn(tasks.named("unpickJar")); | ||||
| 				} | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	private static void extendsFrom(String a, String b, Project project) { | ||||
| 		project.getConfigurations().getByName(a, configuration -> configuration.extendsFrom(project.getConfigurations().getByName(b))); | ||||
| 	} | ||||
| 
 | ||||
| 	private static void finalizedBy(Project project, String a, String b) { | ||||
| 		project.getTasks().named(a).configure(task -> task.finalizedBy(project.getTasks().named(b))); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
| package net.fabricmc.loom.extension; | ||||
| 
 | ||||
| import org.gradle.api.Action; | ||||
| import org.gradle.api.DomainObjectCollection; | ||||
| import org.gradle.api.NamedDomainObjectContainer; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.artifacts.Dependency; | ||||
|  | @ -52,7 +53,7 @@ import net.fabricmc.loom.util.DeprecationHelper; | |||
|  */ | ||||
| public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionAPI { | ||||
| 	protected final DeprecationHelper deprecationHelper; | ||||
| 	protected final ListProperty<LoomDecompiler> decompilers; | ||||
| 	protected final DomainObjectCollection<LoomDecompiler> decompilers; | ||||
| 	protected final ListProperty<JarProcessor> jarProcessors; | ||||
| 	protected final ConfigurableFileCollection log4jConfigs; | ||||
| 	protected final RegularFileProperty accessWidener; | ||||
|  | @ -70,8 +71,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA | |||
| 	protected LoomGradleExtensionApiImpl(Project project, LoomFiles directories) { | ||||
| 		this.runConfigs = project.container(RunConfigSettings.class, | ||||
| 				baseName -> new RunConfigSettings(project, baseName)); | ||||
| 		this.decompilers = project.getObjects().listProperty(LoomDecompiler.class) | ||||
| 				.empty(); | ||||
| 		this.decompilers = project.getObjects().domainObjectSet(LoomDecompiler.class); | ||||
| 		this.jarProcessors = project.getObjects().listProperty(JarProcessor.class) | ||||
| 				.empty(); | ||||
| 		this.log4jConfigs = project.files(directories.getDefaultLog4jConfigFile()); | ||||
|  | @ -110,7 +110,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA | |||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public ListProperty<LoomDecompiler> getGameDecompilers() { | ||||
| 	public DomainObjectCollection<LoomDecompiler> getGameDecompilers() { | ||||
| 		return decompilers; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,11 +42,13 @@ import java.util.stream.Collectors; | |||
| import javax.inject.Inject; | ||||
| 
 | ||||
| import org.gradle.api.file.ConfigurableFileCollection; | ||||
| import org.gradle.api.file.FileCollection; | ||||
| import org.gradle.api.file.RegularFileProperty; | ||||
| import org.gradle.api.provider.MapProperty; | ||||
| import org.gradle.api.provider.Property; | ||||
| import org.gradle.api.tasks.Input; | ||||
| import org.gradle.api.tasks.InputFile; | ||||
| import org.gradle.api.tasks.InputFiles; | ||||
| import org.gradle.api.tasks.TaskAction; | ||||
| import org.gradle.workers.WorkAction; | ||||
| import org.gradle.workers.WorkParameters; | ||||
|  | @ -87,6 +89,9 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask { | |||
| 	@Input | ||||
| 	public abstract MapProperty<String, String> getOptions(); | ||||
| 
 | ||||
| 	@InputFiles | ||||
| 	public abstract ConfigurableFileCollection getClasspath(); | ||||
| 
 | ||||
| 	@Inject | ||||
| 	public abstract WorkerExecutor getWorkerExecutor(); | ||||
| 
 | ||||
|  | @ -100,6 +105,12 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask { | |||
| 		Objects.requireNonNull(getDecompilerConstructor(this.decompiler.getClass().getCanonicalName()), | ||||
| 				"%s must have a no args constructor".formatted(this.decompiler.getClass().getCanonicalName())); | ||||
| 
 | ||||
| 		FileCollection decompilerClasspath = decompiler.getBootstrapClasspath(getProject()); | ||||
| 
 | ||||
| 		if (decompilerClasspath != null) { | ||||
| 			getClasspath().from(decompilerClasspath); | ||||
| 		} | ||||
| 
 | ||||
| 		getOutputs().upToDateWhen((o) -> false); | ||||
| 		getMaxMemory().convention(4096L).finalizeValueOnRead(); | ||||
| 		getOptions().finalizeValueOnRead(); | ||||
|  | @ -177,6 +188,7 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask { | |||
| 			spec.forkOptions(forkOptions -> { | ||||
| 				forkOptions.setMaxHeapSize("%dm".formatted(getMaxMemory().get())); | ||||
| 				forkOptions.systemProperty(WorkerDaemonClientsManagerHelper.MARKER_PROP, jvmMarkerValue); | ||||
| 				forkOptions.bootstrapClasspath(getClasspath()); | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
|  |  | |||
|  | @ -24,17 +24,13 @@ | |||
| 
 | ||||
| package net.fabricmc.loom.task; | ||||
| 
 | ||||
| import java.io.File; | ||||
| 
 | ||||
| import com.google.common.base.Preconditions; | ||||
| import org.gradle.api.Project; | ||||
| import org.gradle.api.tasks.TaskContainer; | ||||
| import org.gradle.api.tasks.TaskProvider; | ||||
| 
 | ||||
| import net.fabricmc.loom.LoomGradleExtension; | ||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||
| import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||
| import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; | ||||
| import net.fabricmc.loom.util.Constants; | ||||
| 
 | ||||
| public final class LoomTasks { | ||||
|  | @ -43,7 +39,6 @@ public final class LoomTasks { | |||
| 
 | ||||
| 	public static void registerTasks(Project project) { | ||||
| 		TaskContainer tasks = project.getTasks(); | ||||
| 		LoomGradleExtension extension = LoomGradleExtension.get(project); | ||||
| 
 | ||||
| 		tasks.register("migrateMappings", MigrateMappingsTask.class, t -> { | ||||
| 			t.setDescription("Migrates mappings to a new version."); | ||||
|  | @ -118,51 +113,15 @@ public final class LoomTasks { | |||
| 	} | ||||
| 
 | ||||
| 	private static void registerDecompileTasks(TaskContainer tasks, Project project) { | ||||
| 		LoomGradleExtension extension = LoomGradleExtension.get(project); | ||||
| 
 | ||||
| 		project.afterEvaluate(p -> { | ||||
| 			MappingsProviderImpl mappingsProvider = extension.getMappingsProvider(); | ||||
| 
 | ||||
| 			if (mappingsProvider.mappedProvider == null) { | ||||
| 				// If this is ever null something has gone badly wrong, | ||||
| 				// for some reason for another this afterEvaluate still gets called when something has gone badly | ||||
| 				// wrong, returning here seems to produce nicer errors. | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); | ||||
| 
 | ||||
| 			if (mappingsProvider.hasUnpickDefinitions()) { | ||||
| 				File outputJar = mappingsProvider.mappedProvider.getUnpickedJar(); | ||||
| 
 | ||||
| 				tasks.register("unpickJar", UnpickJarTask.class, unpickJarTask -> { | ||||
| 					unpickJarTask.getUnpickDefinitions().set(mappingsProvider.getUnpickDefinitionsFile()); | ||||
| 					unpickJarTask.getInputJar().set(mappingsProvider.mappedProvider.getMappedJar()); | ||||
| 					unpickJarTask.getOutputJar().set(outputJar); | ||||
| 				}); | ||||
| 
 | ||||
| 				mappedJar = outputJar; | ||||
| 			} | ||||
| 
 | ||||
| 			final File inputJar = mappedJar; | ||||
| 
 | ||||
| 			extension.getGameDecompilers().finalizeValue(); | ||||
| 
 | ||||
| 			for (LoomDecompiler decompiler : extension.getGameDecompilers().get()) { | ||||
| 		LoomGradleExtension.get(project).getGameDecompilers().configureEach(decompiler -> { | ||||
| 			String taskName = "genSourcesWith" + decompiler.name(); | ||||
| 			// Decompiler will be passed to the constructor of GenerateSourcesTask | ||||
| 			tasks.register(taskName, GenerateSourcesTask.class, decompiler).configure(task -> { | ||||
| 				task.setDescription("Decompile minecraft using %s.".formatted(decompiler.name())); | ||||
| 				task.setGroup(Constants.TaskGroup.FABRIC); | ||||
| 					task.getInputJar().set(inputJar); | ||||
| 
 | ||||
| 					if (mappingsProvider.hasUnpickDefinitions()) { | ||||
| 						task.dependsOn(tasks.named("unpickJar")); | ||||
| 					} | ||||
| 
 | ||||
| 				task.dependsOn(tasks.named("validateAccessWidener")); | ||||
| 			}); | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		tasks.register("genSources", task -> { | ||||
| 			task.setDescription("Decompile minecraft using the default decompiler."); | ||||
|  | @ -170,6 +129,5 @@ public final class LoomTasks { | |||
| 
 | ||||
| 			task.dependsOn(project.getTasks().named("genSourcesWithCfr")); | ||||
| 		}); | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ import org.gradle.util.GradleVersion | |||
| 
 | ||||
| class LoomTestConstants { | ||||
|     public final static String DEFAULT_GRADLE = GradleVersion.current().getVersion() | ||||
|     public final static String PRE_RELEASE_GRADLE = "7.4-20211219231013+0000" | ||||
|     public final static String PRE_RELEASE_GRADLE = "7.5-20211228231407+0000" | ||||
| 
 | ||||
|     public final static String[] STANDARD_TEST_VERSIONS = [DEFAULT_GRADLE, PRE_RELEASE_GRADLE] | ||||
| } | ||||
|  |  | |||
|  | @ -45,9 +45,9 @@ class DecompileTest extends Specification implements GradleProjectTestTrait { | |||
| 
 | ||||
| 		where: | ||||
| 			decompiler 		| task								| version | ||||
| 			'fernflower'	| "genSourcesWithFernFlower"		| DEFAULT_GRADLE | ||||
| 			'fernflower'	| "genSourcesWithFernFlower"		| PRE_RELEASE_GRADLE | ||||
| 			'cfr' 			| "genSourcesWithCfr"				| DEFAULT_GRADLE | ||||
| //			'fernflower'	| "genSourcesWithFernFlower"		| DEFAULT_GRADLE | ||||
| //			'fernflower'	| "genSourcesWithFernFlower"		| PRE_RELEASE_GRADLE | ||||
| //			'cfr' 			| "genSourcesWithCfr"				| DEFAULT_GRADLE | ||||
| 			'cfr' 			| "genSourcesWithCfr"				| PRE_RELEASE_GRADLE | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -7,3 +7,7 @@ dependencies { | |||
| 	mappings "net.fabricmc:yarn:21w38a+build.11:v2" | ||||
| 	modImplementation "net.fabricmc:fabric-loader:0.11.7" | ||||
| } | ||||
| 
 | ||||
| tasks.named("genSourcesWithCfr") { | ||||
| 	options.put("test", "value") | ||||
| } | ||||
		Loading…
	
		Reference in a new issue