Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remapper extensions #984

Merged
merged 7 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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
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