Migrate to access-widener library (#294)
parent
62e89395f9
commit
d1281be741
|
@ -50,6 +50,8 @@ dependencies {
|
|||
implementation ('net.fabricmc:tiny-remapper:0.3.0.70')
|
||||
implementation ('net.fabricmc:tiny-mappings-parser:0.2.2.14')
|
||||
|
||||
implementation 'net.fabricmc:access-widener:1.0.0'
|
||||
|
||||
implementation ('net.fabricmc:lorenz-tiny:2.0.0+build.2') {
|
||||
transitive = false
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ package net.fabricmc.loom.util;
|
|||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
public class Constants {
|
||||
public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/";
|
||||
|
@ -35,6 +36,8 @@ public class Constants {
|
|||
|
||||
public static final String SYSTEM_ARCH = System.getProperty("os.arch").equals("64") ? "64" : "32";
|
||||
|
||||
public static final int ASM_VERSION = Opcodes.ASM9;
|
||||
|
||||
public static final List<RemappedConfigurationEntry> MOD_COMPILE_ENTRIES = ImmutableList.of(
|
||||
new RemappedConfigurationEntry("modCompile", "compile", true, "compile"),
|
||||
new RemappedConfigurationEntry("modApi", "api", true, "compile"),
|
||||
|
|
|
@ -45,7 +45,6 @@ import org.objectweb.asm.ClassVisitor;
|
|||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import net.fabricmc.loom.util.progress.ProgressLogger;
|
||||
|
||||
|
@ -124,7 +123,7 @@ public class LineNumberRemapper {
|
|||
ClassReader reader = new ClassReader(is);
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
|
||||
reader.accept(new LineNumberVisitor(Opcodes.ASM7, writer, lineMap.get(idx)), 0);
|
||||
reader.accept(new LineNumberVisitor(Constants.ASM_VERSION, writer, lineMap.get(idx)), 0);
|
||||
Files.write(dst, writer.toByteArray());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,11 +51,13 @@ import org.zeroturnaround.zip.ZipUtil;
|
|||
import org.zeroturnaround.zip.transform.StringZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerWriter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.providers.MappingsProvider;
|
||||
import net.fabricmc.loom.providers.MinecraftMappedProvider;
|
||||
import net.fabricmc.loom.util.accesswidener.AccessWidener;
|
||||
import net.fabricmc.loom.util.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.loom.processors.dependency.ModDependencyInfo;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
import net.fabricmc.tinyremapper.InputTag;
|
||||
|
@ -109,13 +111,15 @@ public class ModProcessor {
|
|||
private static byte[] remapAccessWidener(byte[] input, Remapper remapper) {
|
||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(input), StandardCharsets.UTF_8))) {
|
||||
AccessWidener accessWidener = new AccessWidener();
|
||||
accessWidener.read(bufferedReader);
|
||||
AccessWidenerReader accessWidenerReader = new AccessWidenerReader(accessWidener);
|
||||
accessWidenerReader.read(bufferedReader);
|
||||
|
||||
AccessWidenerRemapper accessWidenerRemapper = new AccessWidenerRemapper(accessWidener, remapper, "named");
|
||||
AccessWidener remapped = accessWidenerRemapper.remap();
|
||||
AccessWidenerWriter accessWidenerWriter = new AccessWidenerWriter(remapped);
|
||||
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
remapped.write(writer);
|
||||
accessWidenerWriter.write(writer);
|
||||
return writer.toString().getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -1,477 +0,0 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 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.util.accesswidener;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import net.fabricmc.mappings.EntryTriple;
|
||||
|
||||
public class AccessWidener {
|
||||
public String namespace;
|
||||
public Map<String, Access> classAccess = new HashMap<>();
|
||||
public Map<EntryTriple, Access> methodAccess = new HashMap<>();
|
||||
public Map<EntryTriple, Access> fieldAccess = new HashMap<>();
|
||||
private final Set<String> classes = new LinkedHashSet<>();
|
||||
|
||||
public void read(BufferedReader reader) throws IOException {
|
||||
String headerStr = reader.readLine();
|
||||
|
||||
if (headerStr == null) {
|
||||
throw new RuntimeException("Cannot read empty or invalid access widener");
|
||||
}
|
||||
|
||||
String[] header = headerStr.split("\\s+");
|
||||
|
||||
if (header.length != 3 || !header[0].equals("accessWidener")) {
|
||||
throw new UnsupportedOperationException("Invalid access access widener header");
|
||||
}
|
||||
|
||||
if (!header[1].equals("v1")) {
|
||||
throw new RuntimeException(String.format("Unsupported access widener format (%s)", header[1]));
|
||||
}
|
||||
|
||||
if (namespace != null) {
|
||||
if (!namespace.equals(header[2])) {
|
||||
throw new RuntimeException(String.format("Namespace mismatch, expected %s got %s", namespace, header[2]));
|
||||
}
|
||||
}
|
||||
|
||||
namespace = header[2];
|
||||
|
||||
String line;
|
||||
|
||||
Set<String> targets = new LinkedHashSet<>();
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
// Comment handling
|
||||
int commentPos = line.indexOf('#');
|
||||
|
||||
if (commentPos >= 0) {
|
||||
line = line.substring(0, commentPos).trim();
|
||||
}
|
||||
|
||||
if (line.isEmpty()) continue;
|
||||
|
||||
String[] split = line.split("\\s+");
|
||||
|
||||
if (split.length != 3 && split.length != 5) {
|
||||
throw new RuntimeException(String.format("Invalid line (%s)", line));
|
||||
}
|
||||
|
||||
String access = split[0];
|
||||
|
||||
targets.add(split[2].replaceAll("/", "."));
|
||||
|
||||
switch (split[1]) {
|
||||
case "class":
|
||||
if (split.length != 3) {
|
||||
throw new RuntimeException(String.format("Expected (<access>\tclass\t<className>) got (%s)", line));
|
||||
}
|
||||
|
||||
classAccess.put(split[2], applyAccess(access, classAccess.getOrDefault(split[2], ClassAccess.DEFAULT), null));
|
||||
break;
|
||||
case "field":
|
||||
if (split.length != 5) {
|
||||
throw new RuntimeException(String.format("Expected (<access>\tfield\t<className>\t<fieldName>\t<fieldDesc>) got (%s)", line));
|
||||
}
|
||||
|
||||
addOrMerge(fieldAccess, new EntryTriple(split[2], split[3], split[4]), access, FieldAccess.DEFAULT);
|
||||
break;
|
||||
case "method":
|
||||
if (split.length != 5) {
|
||||
throw new RuntimeException(String.format("Expected (<access>\tmethod\t<className>\t<methodName>\t<methodDesc>) got (%s)", line));
|
||||
}
|
||||
|
||||
addOrMerge(methodAccess, new EntryTriple(split[2], split[3], split[4]), access, MethodAccess.DEFAULT);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported type " + split[1]);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> parentClasses = new LinkedHashSet<>();
|
||||
|
||||
//Also transform all parent classes
|
||||
for (String clazz : targets) {
|
||||
while (clazz.contains("$")) {
|
||||
clazz = clazz.substring(0, clazz.lastIndexOf("$"));
|
||||
parentClasses.add(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
classes.addAll(targets);
|
||||
classes.addAll(parentClasses);
|
||||
}
|
||||
|
||||
// Could possibly be cleaner but should do its job for now
|
||||
public void write(StringWriter writer) {
|
||||
writer.write("accessWidener\tv1\t");
|
||||
writer.write(namespace);
|
||||
writer.write("\n");
|
||||
|
||||
for (Map.Entry<String, Access> entry : classAccess.entrySet()) {
|
||||
for (String s : getAccesses(entry.getValue())) {
|
||||
writer.write(s);
|
||||
writer.write("\tclass\t");
|
||||
writer.write(entry.getKey());
|
||||
writer.write("\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, Access> entry : methodAccess.entrySet()) {
|
||||
writeEntry(writer, "method", entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, Access> entry : fieldAccess.entrySet()) {
|
||||
writeEntry(writer, "field", entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeEntry(StringWriter writer, String type, EntryTriple entryTriple, Access access) {
|
||||
for (String s : getAccesses(access)) {
|
||||
writer.write(s);
|
||||
writer.write("\t");
|
||||
writer.write(type);
|
||||
writer.write("\t");
|
||||
writer.write(entryTriple.getOwner());
|
||||
writer.write("\t");
|
||||
writer.write(entryTriple.getName());
|
||||
writer.write("\t");
|
||||
writer.write(entryTriple.getDesc());
|
||||
writer.write("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getAccesses(Access access) {
|
||||
List<String> accesses = new ArrayList<>();
|
||||
|
||||
if (access == ClassAccess.ACCESSIBLE || access == MethodAccess.ACCESSIBLE || access == FieldAccess.ACCESSIBLE || access == MethodAccess.ACCESSIBLE_EXTENDABLE || access == ClassAccess.ACCESSIBLE_EXTENDABLE || access == FieldAccess.ACCESSIBLE_MUTABLE) {
|
||||
accesses.add("accessible");
|
||||
}
|
||||
|
||||
if (access == ClassAccess.EXTENDABLE || access == MethodAccess.EXTENDABLE || access == MethodAccess.ACCESSIBLE_EXTENDABLE || access == ClassAccess.ACCESSIBLE_EXTENDABLE) {
|
||||
accesses.add("extendable");
|
||||
}
|
||||
|
||||
if (access == FieldAccess.MUTABLE || access == FieldAccess.ACCESSIBLE_MUTABLE) {
|
||||
accesses.add("mutable");
|
||||
}
|
||||
|
||||
return accesses;
|
||||
}
|
||||
|
||||
void addOrMerge(Map<EntryTriple, Access> map, EntryTriple entry, Access access) {
|
||||
if (entry == null || access == null) {
|
||||
throw new RuntimeException("Input entry or access is null");
|
||||
}
|
||||
|
||||
Access merged = null;
|
||||
|
||||
if (access instanceof ClassAccess) {
|
||||
merged = ClassAccess.DEFAULT;
|
||||
} else if (access instanceof MethodAccess) {
|
||||
merged = MethodAccess.DEFAULT;
|
||||
} else if (access instanceof FieldAccess) {
|
||||
merged = FieldAccess.DEFAULT;
|
||||
}
|
||||
|
||||
merged = mergeAccess(merged, access);
|
||||
|
||||
map.put(entry, merged);
|
||||
}
|
||||
|
||||
void addOrMerge(Map<EntryTriple, Access> map, EntryTriple entry, String access, Access defaultAccess) {
|
||||
if (entry == null || access == null) {
|
||||
throw new RuntimeException("Input entry or access is null");
|
||||
}
|
||||
|
||||
map.put(entry, applyAccess(access, map.getOrDefault(entry, defaultAccess), entry));
|
||||
}
|
||||
|
||||
public void merge(AccessWidener other) {
|
||||
if (namespace == null) {
|
||||
namespace = other.namespace;
|
||||
} else if (!namespace.equals(other.namespace)) {
|
||||
throw new RuntimeException("Namespace mismatch");
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Access> entry : other.classAccess.entrySet()) {
|
||||
if (classAccess.containsKey(entry.getKey())) {
|
||||
classAccess.replace(entry.getKey(), mergeAccess(classAccess.get(entry.getKey()), entry.getValue()));
|
||||
} else {
|
||||
classAccess.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, Access> entry : other.methodAccess.entrySet()) {
|
||||
addOrMerge(methodAccess, entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, Access> entry : other.fieldAccess.entrySet()) {
|
||||
addOrMerge(fieldAccess, entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private Access applyAccess(String input, Access access, EntryTriple entryTriple) {
|
||||
switch (input.toLowerCase(Locale.ROOT)) {
|
||||
case "accessible":
|
||||
makeClassAccessible(entryTriple);
|
||||
return access.makeAccessible();
|
||||
case "extendable":
|
||||
makeClassExtendable(entryTriple);
|
||||
return access.makeExtendable();
|
||||
case "mutable":
|
||||
return access.makeMutable();
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown access type:" + input);
|
||||
}
|
||||
}
|
||||
|
||||
private void makeClassAccessible(EntryTriple entryTriple) {
|
||||
if (entryTriple == null) return;
|
||||
classAccess.put(entryTriple.getOwner(), applyAccess("accessible", classAccess.getOrDefault(entryTriple.getOwner(), ClassAccess.DEFAULT), null));
|
||||
}
|
||||
|
||||
private void makeClassExtendable(EntryTriple entryTriple) {
|
||||
if (entryTriple == null) return;
|
||||
classAccess.put(entryTriple.getOwner(), applyAccess("extendable", classAccess.getOrDefault(entryTriple.getOwner(), ClassAccess.DEFAULT), null));
|
||||
}
|
||||
|
||||
private static Access mergeAccess(Access a, Access b) {
|
||||
Access access = a;
|
||||
|
||||
if (b == ClassAccess.ACCESSIBLE || b == MethodAccess.ACCESSIBLE || b == FieldAccess.ACCESSIBLE || b == MethodAccess.ACCESSIBLE_EXTENDABLE || b == ClassAccess.ACCESSIBLE_EXTENDABLE || b == FieldAccess.ACCESSIBLE_MUTABLE) {
|
||||
access = access.makeAccessible();
|
||||
}
|
||||
|
||||
if (b == ClassAccess.EXTENDABLE || b == MethodAccess.EXTENDABLE || b == MethodAccess.ACCESSIBLE_EXTENDABLE || b == ClassAccess.ACCESSIBLE_EXTENDABLE) {
|
||||
access = access.makeExtendable();
|
||||
}
|
||||
|
||||
if (b == FieldAccess.MUTABLE || b == FieldAccess.ACCESSIBLE_MUTABLE) {
|
||||
access = access.makeMutable();
|
||||
}
|
||||
|
||||
return access;
|
||||
}
|
||||
|
||||
public Access getClassAccess(String className) {
|
||||
return classAccess.getOrDefault(className, ClassAccess.DEFAULT);
|
||||
}
|
||||
|
||||
public Access getFieldAccess(EntryTriple entryTriple) {
|
||||
return fieldAccess.getOrDefault(entryTriple, FieldAccess.DEFAULT);
|
||||
}
|
||||
|
||||
public Access getMethodAccess(EntryTriple entryTriple) {
|
||||
return methodAccess.getOrDefault(entryTriple, MethodAccess.DEFAULT);
|
||||
}
|
||||
|
||||
public Set<String> getTargets() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static int makePublic(int i) {
|
||||
return (i & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) | Opcodes.ACC_PUBLIC;
|
||||
}
|
||||
|
||||
private static int makeProtected(int i) {
|
||||
if ((i & Opcodes.ACC_PUBLIC) != 0) {
|
||||
// Return i if public
|
||||
return i;
|
||||
}
|
||||
|
||||
return (i & ~(Opcodes.ACC_PRIVATE)) | Opcodes.ACC_PROTECTED;
|
||||
}
|
||||
|
||||
private static int makeFinalIfPrivate(int access, String name, int ownerAccess) {
|
||||
// Dont make constructors final
|
||||
if (name.equals("<init>")) {
|
||||
return access;
|
||||
}
|
||||
|
||||
// Skip interface and static methods
|
||||
if ((ownerAccess & Opcodes.ACC_INTERFACE) != 0 || (access & Opcodes.ACC_STATIC) != 0) {
|
||||
return access;
|
||||
}
|
||||
|
||||
if ((access & Opcodes.ACC_PRIVATE) != 0) {
|
||||
return access | Opcodes.ACC_FINAL;
|
||||
}
|
||||
|
||||
return access;
|
||||
}
|
||||
|
||||
private static int removeFinal(int i) {
|
||||
return i & ~Opcodes.ACC_FINAL;
|
||||
}
|
||||
|
||||
public interface Access extends AccessOperator {
|
||||
Access makeAccessible();
|
||||
|
||||
Access makeExtendable();
|
||||
|
||||
Access makeMutable();
|
||||
}
|
||||
|
||||
public enum ClassAccess implements Access {
|
||||
DEFAULT((access, name, ownerAccess) -> access),
|
||||
ACCESSIBLE((access, name, ownerAccess) -> makePublic(access)),
|
||||
EXTENDABLE((access, name, ownerAccess) -> makePublic(removeFinal(access))),
|
||||
ACCESSIBLE_EXTENDABLE((access, name, ownerAccess) -> makePublic(removeFinal(access)));
|
||||
|
||||
private final AccessOperator operator;
|
||||
|
||||
ClassAccess(AccessOperator operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeAccessible() {
|
||||
if (this == EXTENDABLE || this == ACCESSIBLE_EXTENDABLE) {
|
||||
return ACCESSIBLE_EXTENDABLE;
|
||||
}
|
||||
|
||||
return ACCESSIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeExtendable() {
|
||||
if (this == ACCESSIBLE || this == ACCESSIBLE_EXTENDABLE) {
|
||||
return ACCESSIBLE_EXTENDABLE;
|
||||
}
|
||||
|
||||
return EXTENDABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeMutable() {
|
||||
throw new UnsupportedOperationException("Classes cannot be made mutable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int apply(int access, String targetName, int ownerAccess) {
|
||||
return operator.apply(access, targetName, ownerAccess);
|
||||
}
|
||||
}
|
||||
|
||||
public enum MethodAccess implements Access {
|
||||
DEFAULT((access, name, ownerAccess) -> access),
|
||||
ACCESSIBLE((access, name, ownerAccess) -> makePublic(makeFinalIfPrivate(access, name, ownerAccess))),
|
||||
EXTENDABLE((access, name, ownerAccess) -> makeProtected(removeFinal(access))),
|
||||
ACCESSIBLE_EXTENDABLE((access, name, owner) -> makePublic(removeFinal(access)));
|
||||
|
||||
private final AccessOperator operator;
|
||||
|
||||
MethodAccess(AccessOperator operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeAccessible() {
|
||||
if (this == EXTENDABLE || this == ACCESSIBLE_EXTENDABLE) {
|
||||
return ACCESSIBLE_EXTENDABLE;
|
||||
}
|
||||
|
||||
return ACCESSIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeExtendable() {
|
||||
if (this == ACCESSIBLE || this == ACCESSIBLE_EXTENDABLE) {
|
||||
return ACCESSIBLE_EXTENDABLE;
|
||||
}
|
||||
|
||||
return EXTENDABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeMutable() {
|
||||
throw new UnsupportedOperationException("Methods cannot be made mutable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int apply(int access, String targetName, int ownerAccess) {
|
||||
return operator.apply(access, targetName, ownerAccess);
|
||||
}
|
||||
}
|
||||
|
||||
public enum FieldAccess implements Access {
|
||||
DEFAULT((access, name, ownerAccess) -> access),
|
||||
ACCESSIBLE((access, name, ownerAccess) -> makePublic(access)),
|
||||
MUTABLE((access, name, ownerAccess) -> removeFinal(access)),
|
||||
ACCESSIBLE_MUTABLE((access, name, ownerAccess) -> makePublic(removeFinal(access)));
|
||||
|
||||
private final AccessOperator operator;
|
||||
|
||||
FieldAccess(AccessOperator operator) {
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeAccessible() {
|
||||
if (this == MUTABLE || this == ACCESSIBLE_MUTABLE) {
|
||||
return ACCESSIBLE_MUTABLE;
|
||||
}
|
||||
|
||||
return ACCESSIBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeExtendable() {
|
||||
throw new UnsupportedOperationException("Fields cannot be made extendable");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Access makeMutable() {
|
||||
if (this == ACCESSIBLE || this == ACCESSIBLE_MUTABLE) {
|
||||
return ACCESSIBLE_MUTABLE;
|
||||
}
|
||||
|
||||
return MUTABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int apply(int access, String targetName, int ownerAccess) {
|
||||
return operator.apply(access, targetName, ownerAccess);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AccessOperator {
|
||||
int apply(int access, String targetName, int ownerAccess);
|
||||
}
|
||||
}
|
|
@ -41,23 +41,26 @@ import org.gradle.api.Project;
|
|||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
import org.zeroturnaround.zip.ZipUtil;
|
||||
import org.zeroturnaround.zip.transform.ByteArrayZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformer;
|
||||
import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry;
|
||||
|
||||
import net.fabricmc.accesswidener.AccessWidener;
|
||||
import net.fabricmc.accesswidener.AccessWidenerRemapper;
|
||||
import net.fabricmc.accesswidener.AccessWidenerReader;
|
||||
import net.fabricmc.accesswidener.AccessWidenerVisitor;
|
||||
import net.fabricmc.accesswidener.AccessWidenerWriter;
|
||||
import net.fabricmc.loom.LoomGradleExtension;
|
||||
import net.fabricmc.loom.processors.JarProcessor;
|
||||
import net.fabricmc.loom.util.Constants;
|
||||
import net.fabricmc.loom.util.Checksum;
|
||||
import net.fabricmc.mappings.EntryTriple;
|
||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
||||
|
||||
public class AccessWidenerJarProcessor implements JarProcessor {
|
||||
private AccessWidener accessWidener = new AccessWidener();
|
||||
private AccessWidenerReader accessWidenerReader = new AccessWidenerReader(accessWidener);
|
||||
private final Project project;
|
||||
private byte[] inputHash;
|
||||
|
||||
|
@ -76,13 +79,13 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
|||
inputHash = Checksum.sha256(loomGradleExtension.accessWidener);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(loomGradleExtension.accessWidener))) {
|
||||
accessWidener.read(reader);
|
||||
accessWidenerReader.read(reader);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to read project access widener file");
|
||||
}
|
||||
|
||||
//Remap accessWidener if its not named, allows for AE's to be written in intermediary
|
||||
if (!accessWidener.namespace.equals("named")) {
|
||||
if (!accessWidener.getNamespace().equals("named")) {
|
||||
try {
|
||||
TinyRemapper tinyRemapper = loomGradleExtension.getMinecraftMappedProvider().getTinyRemapper("official", "named");
|
||||
tinyRemapper.readClassPath(loomGradleExtension.getMinecraftMappedProvider().getRemapClasspath());
|
||||
|
@ -116,10 +119,11 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
|||
protected byte[] transform(ZipEntry zipEntry, byte[] input) {
|
||||
ClassReader reader = new ClassReader(input);
|
||||
ClassWriter writer = new ClassWriter(0);
|
||||
ClassVisitor classVisitor = AccessWidenerVisitor.createClassVisitor(Constants.ASM_VERSION, writer, accessWidener);
|
||||
|
||||
project.getLogger().lifecycle("Applying access widener to " + className);
|
||||
|
||||
reader.accept(new AccessTransformer(writer), 0);
|
||||
reader.accept(classVisitor, 0);
|
||||
return writer.toByteArray();
|
||||
}
|
||||
};
|
||||
|
@ -145,9 +149,10 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
|||
public byte[] getRemappedAccessWidener(Remapper asmRemapper) throws IOException {
|
||||
AccessWidenerRemapper remapper = new AccessWidenerRemapper(accessWidener, asmRemapper, "intermediary");
|
||||
AccessWidener remapped = remapper.remap();
|
||||
AccessWidenerWriter accessWidenerWriter = new AccessWidenerWriter(remapped);
|
||||
|
||||
try (StringWriter writer = new StringWriter()) {
|
||||
remapped.write(writer);
|
||||
accessWidenerWriter.write(writer);
|
||||
return writer.toString().getBytes();
|
||||
}
|
||||
}
|
||||
|
@ -178,78 +183,4 @@ public class AccessWidenerJarProcessor implements JarProcessor {
|
|||
|
||||
return !Arrays.equals(inputHash, hash); // TODO how do we know if the current jar as the correct access applied? save the hash of the input?
|
||||
}
|
||||
|
||||
private class AccessTransformer extends ClassVisitor {
|
||||
private String className;
|
||||
private int classAccess;
|
||||
|
||||
private AccessTransformer(ClassVisitor classVisitor) {
|
||||
super(Opcodes.ASM7, classVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
className = name;
|
||||
classAccess = access;
|
||||
super.visit(
|
||||
version,
|
||||
accessWidener.getClassAccess(name).apply(access, name, classAccess),
|
||||
name,
|
||||
signature,
|
||||
superName,
|
||||
interfaces
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) {
|
||||
super.visitInnerClass(
|
||||
name,
|
||||
outerName,
|
||||
innerName,
|
||||
accessWidener.getClassAccess(name).apply(access, name, classAccess)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
|
||||
return super.visitField(
|
||||
accessWidener.getFieldAccess(new EntryTriple(className, name, descriptor)).apply(access, name, classAccess),
|
||||
name,
|
||||
descriptor,
|
||||
signature,
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
return new AccessWidenerMethodVisitor(super.visitMethod(
|
||||
accessWidener.getMethodAccess(new EntryTriple(className, name, descriptor)).apply(access, name, classAccess),
|
||||
name,
|
||||
descriptor,
|
||||
signature,
|
||||
exceptions
|
||||
));
|
||||
}
|
||||
|
||||
private class AccessWidenerMethodVisitor extends MethodVisitor {
|
||||
AccessWidenerMethodVisitor(MethodVisitor methodVisitor) {
|
||||
super(Opcodes.ASM7, methodVisitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
|
||||
if (opcode == Opcodes.INVOKESPECIAL && owner.equals(className) && !name.equals("<init>")) {
|
||||
AccessWidener.Access methodAccess = accessWidener.getMethodAccess(new EntryTriple(owner, name, descriptor));
|
||||
|
||||
if (methodAccess != AccessWidener.MethodAccess.DEFAULT) {
|
||||
opcode = Opcodes.INVOKEVIRTUAL;
|
||||
}
|
||||
}
|
||||
|
||||
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* This file is part of fabric-loom, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2016, 2017, 2018 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.util.accesswidener;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.objectweb.asm.commons.Remapper;
|
||||
|
||||
import net.fabricmc.mappings.EntryTriple;
|
||||
|
||||
public class AccessWidenerRemapper {
|
||||
private final AccessWidener input;
|
||||
private final String to;
|
||||
private final Remapper remapper;
|
||||
|
||||
public AccessWidenerRemapper(AccessWidener input, Remapper remapper, String to) {
|
||||
this.input = input;
|
||||
this.to = to;
|
||||
this.remapper = remapper;
|
||||
}
|
||||
|
||||
public AccessWidener remap() {
|
||||
// Dont remap if we dont need to
|
||||
if (input.namespace.equals(to)) {
|
||||
return input;
|
||||
}
|
||||
|
||||
AccessWidener remapped = new AccessWidener();
|
||||
remapped.namespace = to;
|
||||
|
||||
for (Map.Entry<String, AccessWidener.Access> entry : input.classAccess.entrySet()) {
|
||||
remapped.classAccess.put(remapper.map(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, AccessWidener.Access> entry : input.methodAccess.entrySet()) {
|
||||
remapped.addOrMerge(remapped.methodAccess, remapMethod(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<EntryTriple, AccessWidener.Access> entry : input.fieldAccess.entrySet()) {
|
||||
remapped.addOrMerge(remapped.fieldAccess, remapField(entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
return remapped;
|
||||
}
|
||||
|
||||
private EntryTriple remapMethod(EntryTriple entryTriple) {
|
||||
return new EntryTriple(
|
||||
remapper.map(entryTriple.getOwner()),
|
||||
remapper.mapMethodName(entryTriple.getOwner(), entryTriple.getName(), entryTriple.getDesc()),
|
||||
remapper.mapDesc(entryTriple.getDesc())
|
||||
);
|
||||
}
|
||||
|
||||
private EntryTriple remapField(EntryTriple entryTriple) {
|
||||
return new EntryTriple(
|
||||
remapper.map(entryTriple.getOwner()),
|
||||
remapper.mapFieldName(entryTriple.getOwner(), entryTriple.getName(), entryTriple.getDesc()),
|
||||
remapper.mapDesc(entryTriple.getDesc())
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue