Skip to content

Commit

Permalink
Remapper extensions (#984)
Browse files Browse the repository at this point in the history
* Remapper extension API

* Fix build

* More work

* Fixes, thanks Gradle.

* Build fix

* Cleanup
  • Loading branch information
modmuss50 authored Dec 15, 2023
1 parent 0e9663b commit 014a6fc
Show file tree
Hide file tree
Showing 17 changed files with 595 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/main/java/net/fabricmc/loom/LoomGradleExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider;
import net.fabricmc.loom.extension.LoomFiles;
import net.fabricmc.loom.extension.MixinExtension;
import net.fabricmc.loom.extension.RemapperExtensionHolder;
import net.fabricmc.loom.util.download.DownloadBuilder;

@ApiStatus.Internal
Expand Down Expand Up @@ -115,4 +116,6 @@ default List<Path> getMinecraftJars(MappingsNamespace mappingsNamespace) {
boolean multiProjectOptimisation();

ListProperty<LibraryProcessorManager.LibraryProcessorFactory> getLibraryProcessors();

ListProperty<RemapperExtensionHolder> getRemapperExtensions();
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
import net.fabricmc.loom.api.remapping.RemapperExtension;
import net.fabricmc.loom.api.remapping.RemapperParameters;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.mappings.NoOpIntermediateMappingsProvider;
Expand Down Expand Up @@ -221,4 +223,6 @@ default void splitMinecraftJar() {
Property<Boolean> getRuntimeOnlyLog4j();

Property<Boolean> getSplitModDependencies();

<T extends RemapperParameters> void addRemapperExtension(Class<RemapperExtension<T>> remapperExtensionClass, Class<T> parametersClass, Action<T> parameterAction);
}
47 changes: 47 additions & 0 deletions src/main/java/net/fabricmc/loom/api/remapping/RemapperContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package net.fabricmc.loom.api.remapping;

import org.objectweb.asm.commons.Remapper;

/**
* Context for a {@link RemapperExtension}.
*/
public interface RemapperContext {
/**
* @return The {@link Remapper} instance
*/
Remapper remapper();

/**
* @return the source namespace
*/
String sourceNamespace();

/**
* @return the target namespace
*/
String targetNamespace();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package net.fabricmc.loom.api.remapping;

import javax.inject.Inject;

import org.gradle.api.Action;
import org.objectweb.asm.ClassVisitor;

/**
* A remapper extension can be used to add extra processing to the remapping process.
*
* <p>Implementations of RemapperExtension's must have the following:
* A single constructor annotated with {@link Inject}, and taking a single argument of the parameters.
* Or a single constructor annotated with {@link Inject} taking no arguments, when the extension does not have any parameters.
*
* <p>Use {@link net.fabricmc.loom.api.LoomGradleExtensionAPI#addRemapperExtension(Class, Class, Action)} to register a remapper extension.
*
* @param <T> Parameter type for the extension. Should be {@link RemapperParameters.None} if the action does not have parameters.
*/
public interface RemapperExtension<T extends RemapperParameters> {
/**
* Return a {@link ClassVisitor} that will be used when remapping the given class.
*
* @param className The name of the class being remapped
* @param remapperContext The remapper context
* @param classVisitor The parent class visitor
* @return A {@link ClassVisitor} that will be used when remapping the given class, or the given {@code classVisitor} if no extra processing is required for this class.
*/
ClassVisitor insertVisitor(String className, RemapperContext remapperContext, ClassVisitor classVisitor);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package net.fabricmc.loom.api.remapping;

import org.jetbrains.annotations.ApiStatus;

/**
* Marker interface for parameter objects to {@link RemapperExtension}s.
*
* <p>Design based off of Gradle's {@link org.gradle.workers.WorkParameters}.
*/
public interface RemapperParameters {
final class None implements RemapperParameters {
@ApiStatus.Internal
public static None INSTANCE = new None();

private None() {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2023 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package net.fabricmc.loom.api.remapping;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import net.fabricmc.tinyremapper.TinyRemapper;

/**
* A remapper extension, that has direct access to the TinyRemapper APIs.
*
* <p>This API is not stable and may change without notice.
*/
@ApiStatus.Experimental
public interface TinyRemapperExtension {
/**
* See: {@link TinyRemapper.Builder#extraAnalyzeVisitor(TinyRemapper.AnalyzeVisitorProvider)}.
*
* @return A {@link TinyRemapper.AnalyzeVisitorProvider} or {@code null}.
*/
@Nullable
default TinyRemapper.AnalyzeVisitorProvider getAnalyzeVisitorProvider() {
return null;
}

/**
* See: {@link TinyRemapper.Builder#extraPreApplyVisitor(TinyRemapper.ApplyVisitorProvider)}.
*
* @return A {@link TinyRemapper.ApplyVisitorProvider} or {@code null}.
*/
@Nullable
default TinyRemapper.ApplyVisitorProvider getPreApplyVisitor() {
return null;
}

/**
* See: {@link TinyRemapper.Builder#extraPostApplyVisitor(TinyRemapper.ApplyVisitorProvider)}.
*
* @return A {@link TinyRemapper.ApplyVisitorProvider} or {@code null}.
*/
@Nullable
default TinyRemapper.ApplyVisitorProvider getPostApplyVisitor() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.mods.dependency.ModDependency;
import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration;
import net.fabricmc.loom.extension.RemapperExtensionHolder;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.Pair;
import net.fabricmc.loom.util.TinyRemapperHelper;
Expand Down Expand Up @@ -157,6 +158,10 @@ private void remapJars(List<ModDependency> remapList) throws IOException {
builder.extension(new MixinExtension(remapMixins::contains));
}

for (RemapperExtensionHolder holder : extension.getRemapperExtensions().get()) {
holder.apply(builder, fromM, toM, project.getObjects());
}

final TinyRemapper remapper = builder.build();

for (Path minecraftJar : extension.getMinecraftJars(MappingsNamespace.INTERMEDIARY)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.SetProperty;
Expand All @@ -50,6 +51,8 @@
import net.fabricmc.loom.api.mappings.intermediate.IntermediateMappingsProvider;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.api.processor.MinecraftJarProcessor;
import net.fabricmc.loom.api.remapping.RemapperExtension;
import net.fabricmc.loom.api.remapping.RemapperParameters;
import net.fabricmc.loom.configuration.RemapConfigurations;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.processors.JarProcessor;
Expand Down Expand Up @@ -91,6 +94,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
private final NamedDomainObjectContainer<ModSettings> mods;
private final NamedDomainObjectList<RemapConfigurationSettings> remapConfigurations;
private final ListProperty<MinecraftJarProcessor<?>> minecraftJarProcessors;
protected final ListProperty<RemapperExtensionHolder> remapperExtensions;

// A common mistake with layered mappings is to call the wrong `officialMojangMappings` method, use this to keep track of when we are building a layered mapping spec.
protected final ThreadLocal<Boolean> layeredSpecBuilderScope = ThreadLocal.withInitial(() -> false);
Expand Down Expand Up @@ -150,6 +154,9 @@ protected LoomGradleExtensionApiImpl(Project project, LoomFiles directories) {
this.splitEnvironmentalSourceSet = project.getObjects().property(Boolean.class).convention(false);
this.splitEnvironmentalSourceSet.finalizeValueOnRead();

remapperExtensions = project.getObjects().listProperty(RemapperExtensionHolder.class);
remapperExtensions.finalizeValueOnRead();

// Enable dep iface injection by default
interfaceInjection(interfaceInjection -> {
interfaceInjection.getEnableDependencyInterfaceInjection().convention(true).finalizeValueOnRead();
Expand Down Expand Up @@ -382,6 +389,23 @@ public void createRemapConfigurations(SourceSet sourceSet) {
RemapConfigurations.setupForSourceSet(getProject(), sourceSet);
}

@Override
public <T extends RemapperParameters> void addRemapperExtension(Class<RemapperExtension<T>> remapperExtensionClass, Class<T> parametersClass, Action<T> parameterAction) {
final ObjectFactory objectFactory = getProject().getObjects();
final RemapperExtensionHolder holder;

if (parametersClass != RemapperParameters.None.class) {
T parameters = objectFactory.newInstance(parametersClass);
parameterAction.execute(parameters);
holder = objectFactory.newInstance(RemapperExtensionHolder.class, parameters);
} else {
holder = objectFactory.newInstance(RemapperExtensionHolder.class, RemapperParameters.None.INSTANCE);
}

holder.getRemapperExtensionClassName().set(remapperExtensionClass.getName());
remapperExtensions.add(holder);
}

// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods
private final class EnsureCompile extends LoomGradleExtensionApiImpl {
private EnsureCompile() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ public ListProperty<LibraryProcessorManager.LibraryProcessorFactory> getLibraryP
return libraryProcessorFactories;
}

@Override
public ListProperty<RemapperExtensionHolder> getRemapperExtensions() {
return remapperExtensions;
}

@Override
protected <T extends IntermediateMappingsProvider> void configureIntermediateMappingsProviderInternal(T provider) {
provider.getMinecraftVersion().set(getProject().provider(() -> getMinecraftProvider().minecraftVersion()));
Expand Down
Loading

0 comments on commit 014a6fc

Please sign in to comment.