diff --git a/buildSrc/src/main/java/Aw2AtTask.java b/buildSrc/src/main/java/Aw2AtTask.java index c881ff85..b9805b0c 100644 --- a/buildSrc/src/main/java/Aw2AtTask.java +++ b/buildSrc/src/main/java/Aw2AtTask.java @@ -98,7 +98,8 @@ of this software and associated documentation files (the "Software"), to deal */ public static AccessTransformSet toAccessTransformSet(final BufferedReader reader) throws IOException { - AccessTransformSet atSet = AccessTransformSet.create(); + // TODO: Remove copied classes once https://github.com/architectury/at/pull/1 is released + AccessTransformSet atSet = new at.AccessTransformSetImpl(); new AccessWidenerReader(new AccessWidenerVisitor() { @Override diff --git a/buildSrc/src/main/java/at/AccessTransformSetImpl.java b/buildSrc/src/main/java/at/AccessTransformSetImpl.java new file mode 100644 index 00000000..029ed4e0 --- /dev/null +++ b/buildSrc/src/main/java/at/AccessTransformSetImpl.java @@ -0,0 +1,97 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Architectury + * Copyright (c) 2018 Minecrell (https://github.com/Minecrell) + * + * 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 at; + +import dev.architectury.at.AccessTransformSet; +import net.fabricmc.mappingio.tree.MappingTreeView; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public class AccessTransformSetImpl implements AccessTransformSet { + + private final Map classes = new LinkedHashMap<>(); + + @Override + public Map getClasses() { + return Collections.unmodifiableMap(this.classes); + } + + @Override + public Optional getClass(String name) { + Objects.requireNonNull(name, "name"); + return Optional.ofNullable(this.classes.get(name.replace('.', '/'))); + } + + @Override + public Class getOrCreateClass(String name) { + Objects.requireNonNull(name, "name"); + return this.classes.computeIfAbsent(name.replace('.', '/'), n -> new ClassAccessTransformSetImpl(this, n)); + } + + @Override + public Optional removeClass(String name) { + Objects.requireNonNull(name, "name"); + return Optional.ofNullable(this.classes.remove(name.replace('.', '/'))); + } + + @Override + public AccessTransformSet remap(MappingTreeView mappings, String from, String to) { + throw new UnsupportedOperationException(); + } + + @Override + public void merge(AccessTransformSet other) { + other.getClasses().forEach((name, classSet) -> getOrCreateClass(name).merge(classSet)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof AccessTransformSetImpl)) { + return false; + } + + AccessTransformSetImpl that = (AccessTransformSetImpl) o; + return this.classes.equals(that.classes); + } + + @Override + public int hashCode() { + return this.classes.hashCode(); + } + + @Override + public String toString() { + return "AccessTransformSet{" + classes + '}'; + } + +} diff --git a/buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java b/buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java new file mode 100644 index 00000000..79e6219c --- /dev/null +++ b/buildSrc/src/main/java/at/ClassAccessTransformSetImpl.java @@ -0,0 +1,256 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 Architectury + * Copyright (c) 2018 Minecrell (https://github.com/Minecrell) + * + * 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 at; + +import dev.architectury.at.AccessTransform; +import dev.architectury.at.AccessTransformSet; +import org.cadixdev.bombe.analysis.InheritanceProvider; +import org.cadixdev.bombe.type.signature.MethodSignature; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; + +class ClassAccessTransformSetImpl implements AccessTransformSet.Class { + + private final AccessTransformSet parent; + private final String name; + + private AccessTransform classTransform = AccessTransform.EMPTY; + private AccessTransform allFields = AccessTransform.EMPTY; + private AccessTransform allMethods = AccessTransform.EMPTY; + + private final Map fields = new LinkedHashMap<>(); + private final Map methods = new LinkedHashMap<>(); + + private boolean complete; + + ClassAccessTransformSetImpl(AccessTransformSet parent, String name) { + this.parent = parent; + this.name = name; + } + + @Override + public AccessTransformSet getParent() { + return parent; + } + + @Override + public String getName() { + return name; + } + + @Override + public AccessTransform get() { + return this.classTransform; + } + + @Override + public AccessTransform merge(AccessTransform transform) { + return this.classTransform = this.classTransform.merge(transform); + } + + @Override + public AccessTransform replace(AccessTransform transform) { + return this.classTransform = Objects.requireNonNull(transform, "transform"); + } + + @Override + public AccessTransform allFields() { + return this.allFields; + } + + @Override + public AccessTransform mergeAllFields(AccessTransform transform) { + return this.allFields = this.allFields.merge(transform); + } + + @Override + public AccessTransform replaceAllFields(AccessTransform transform) { + return this.allFields = Objects.requireNonNull(transform, "transform"); + } + + @Override + public AccessTransform allMethods() { + return this.allMethods; + } + + @Override + public AccessTransform mergeAllMethods(AccessTransform transform) { + return this.allMethods = this.allMethods.merge(transform); + } + + @Override + public AccessTransform replaceAllMethods(AccessTransform transform) { + return this.allMethods = Objects.requireNonNull(transform, "transform"); + } + + @Override + public Map getFields() { + return Collections.unmodifiableMap(this.fields); + } + + @Override + public AccessTransform getField(String name) { + return this.fields.getOrDefault(Objects.requireNonNull(name, "name"), this.allFields); + } + + @Override + public AccessTransform mergeField(String name, AccessTransform transform) { + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.fields.getOrDefault(name, AccessTransform.EMPTY); + } + return this.fields.merge(name, transform, AccessTransform::merge); + } + + @Override + public AccessTransform replaceField(String name, AccessTransform transform) { + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.fields.remove(name); + } + return this.fields.put(name, transform); + } + + @Override + public Map getMethods() { + return Collections.unmodifiableMap(this.methods); + } + + @Override + public AccessTransform getMethod(MethodSignature signature) { + return this.methods.getOrDefault(Objects.requireNonNull(signature, "signature"), this.allMethods); + } + + @Override + public AccessTransform mergeMethod(MethodSignature signature, AccessTransform transform) { + Objects.requireNonNull(signature, "signature"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.methods.getOrDefault(signature, AccessTransform.EMPTY); + } + return this.methods.merge(signature, transform, AccessTransform::merge); + } + + @Override + public AccessTransform replaceMethod(MethodSignature signature, AccessTransform transform) { + Objects.requireNonNull(signature, "signature"); + Objects.requireNonNull(transform, "transform"); + + if (transform.isEmpty()) { + return this.methods.remove(signature); + } + return this.methods.put(signature, transform); + } + + @Override + public void merge(AccessTransformSet.Class other) { + Objects.requireNonNull(other, "other"); + + merge(other.get()); + mergeAllFields(other.allFields()); + mergeAllMethods(other.allMethods()); + + other.getFields().forEach(this::mergeField); + other.getMethods().forEach(this::mergeMethod); + } + + @Override + public boolean isComplete() { + return this.complete; + } + + @Override + public void complete(InheritanceProvider provider, InheritanceProvider.ClassInfo info) { + if (this.complete) { + return; + } + + for (InheritanceProvider.ClassInfo parent : info.provideParents(provider)) { + AccessTransformSet.Class parentAts = getParent().getOrCreateClass(parent.getName()); + parentAts.complete(provider, parent); + + parentAts.getMethods().forEach((signature, transform) -> { + if (info.overrides(signature, parent)) { + mergeMethod(signature, transform); + } + }); + } + + this.complete = true; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ClassAccessTransformSetImpl)) { + return false; + } + + ClassAccessTransformSetImpl that = (ClassAccessTransformSetImpl) o; + return this.classTransform.equals(that.classTransform) && + this.allFields.equals(that.allFields) && + this.allMethods.equals(that.allMethods) && + this.fields.equals(that.fields) && + this.methods.equals(that.methods); + } + + @Override + public int hashCode() { + return Objects.hash(this.classTransform, this.allFields, this.allMethods, this.fields, this.methods); + } + + @Override + public String toString() { + StringJoiner joiner = new StringJoiner(", ", "AccessTransformSet.Class{", "}"); + if (!this.classTransform.isEmpty()) { + joiner.add(this.classTransform.toString()); + } + if (!this.allFields.isEmpty()) { + joiner.add("allFields=" + this.allFields); + } + if (!this.allMethods.isEmpty()) { + joiner.add("allMethods=" + this.allMethods); + } + if (!this.fields.isEmpty()) { + joiner.add("fields=" + this.fields); + } + if (!this.methods.isEmpty()) { + joiner.add("method=" + this.methods); + } + return joiner.toString(); + } +}