diff options
| author | 2023-04-28 13:14:32 +0200 | |
|---|---|---|
| committer | 2023-04-28 12:14:32 +0100 | |
| commit | b73d303f3aca9610d3bad866518f21cc813a2c87 (patch) | |
| tree | 45f97f9bc6934d647b339f836f71cd865e8a1d8e | |
| parent | Bump version (diff) | |
| download | enigma-b73d303f3aca9610d3bad866518f21cc813a2c87.tar.gz enigma-b73d303f3aca9610d3bad866518f21cc813a2c87.tar.xz enigma-b73d303f3aca9610d3bad866518f21cc813a2c87.zip | |
Allow shadowing fields (#475)
* Fix Enigma not allowing to shadow static fields
* Fix mapping uniqueness verification
* Allow shadowing any field
* Fix a message
Co-authored-by: ByMartrixx <bymartrixx@gmail.com>
8 files changed, 72 insertions, 3 deletions
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java index 5f42373c..f6c0a6b8 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java | |||
| @@ -4,10 +4,13 @@ import java.util.Collection; | |||
| 4 | import java.util.HashSet; | 4 | import java.util.HashSet; |
| 5 | import java.util.List; | 5 | import java.util.List; |
| 6 | 6 | ||
| 7 | import javax.annotation.Nullable; | ||
| 8 | |||
| 7 | import cuchaz.enigma.analysis.index.InheritanceIndex; | 9 | import cuchaz.enigma.analysis.index.InheritanceIndex; |
| 8 | import cuchaz.enigma.analysis.index.JarIndex; | 10 | import cuchaz.enigma.analysis.index.JarIndex; |
| 9 | import cuchaz.enigma.translation.Translator; | 11 | import cuchaz.enigma.translation.Translator; |
| 10 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | 12 | import cuchaz.enigma.translation.mapping.tree.EntryTree; |
| 13 | import cuchaz.enigma.translation.representation.AccessFlags; | ||
| 11 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | 14 | import cuchaz.enigma.translation.representation.entry.ClassEntry; |
| 12 | import cuchaz.enigma.translation.representation.entry.Entry; | 15 | import cuchaz.enigma.translation.representation.entry.Entry; |
| 13 | import cuchaz.enigma.utils.validation.Message; | 16 | import cuchaz.enigma.utils.validation.Message; |
| @@ -41,12 +44,20 @@ public class MappingValidator { | |||
| 41 | Collection<ClassEntry> relatedClasses = getRelatedClasses(containingClass); | 44 | Collection<ClassEntry> relatedClasses = getRelatedClasses(containingClass); |
| 42 | 45 | ||
| 43 | boolean error = false; | 46 | boolean error = false; |
| 47 | Entry<?> shadowedEntry; | ||
| 44 | 48 | ||
| 45 | for (ClassEntry relatedClass : relatedClasses) { | 49 | for (ClassEntry relatedClass : relatedClasses) { |
| 50 | if (isStatic(entry) && relatedClass != containingClass) { | ||
| 51 | // static entries can only conflict with entries in the same class | ||
| 52 | continue; | ||
| 53 | } | ||
| 54 | |||
| 46 | Entry<?> relatedEntry = entry.replaceAncestor(containingClass, relatedClass); | 55 | Entry<?> relatedEntry = entry.replaceAncestor(containingClass, relatedClass); |
| 47 | Entry<?> translatedEntry = deobfuscator.translate(relatedEntry); | 56 | Entry<?> translatedEntry = deobfuscator.translate(relatedEntry); |
| 48 | 57 | ||
| 49 | List<? extends Entry<?>> translatedSiblings = obfToDeobf.getSiblings(relatedEntry).stream().map(deobfuscator::translate).toList(); | 58 | List<? extends Entry<?>> translatedSiblings = obfToDeobf.getSiblings(relatedEntry).stream() |
| 59 | .map(deobfuscator::translate) | ||
| 60 | .toList(); | ||
| 50 | 61 | ||
| 51 | if (!isUnique(translatedEntry, translatedSiblings, name)) { | 62 | if (!isUnique(translatedEntry, translatedSiblings, name)) { |
| 52 | Entry<?> parent = translatedEntry.getParent(); | 63 | Entry<?> parent = translatedEntry.getParent(); |
| @@ -58,6 +69,14 @@ public class MappingValidator { | |||
| 58 | } | 69 | } |
| 59 | 70 | ||
| 60 | error = true; | 71 | error = true; |
| 72 | } else if ((shadowedEntry = getShadowedEntry(translatedEntry, translatedSiblings, name)) != null) { | ||
| 73 | Entry<?> parent = shadowedEntry.getParent(); | ||
| 74 | |||
| 75 | if (parent != null) { | ||
| 76 | vc.raise(Message.SHADOWED_NAME_CLASS, name, parent); | ||
| 77 | } else { | ||
| 78 | vc.raise(Message.SHADOWED_NAME, name); | ||
| 79 | } | ||
| 61 | } | 80 | } |
| 62 | } | 81 | } |
| 63 | 82 | ||
| @@ -77,11 +96,35 @@ public class MappingValidator { | |||
| 77 | 96 | ||
| 78 | private boolean isUnique(Entry<?> entry, List<? extends Entry<?>> siblings, String name) { | 97 | private boolean isUnique(Entry<?> entry, List<? extends Entry<?>> siblings, String name) { |
| 79 | for (Entry<?> sibling : siblings) { | 98 | for (Entry<?> sibling : siblings) { |
| 80 | if (entry.canConflictWith(sibling) && sibling.getName().equals(name)) { | 99 | if (canConflict(entry, sibling) && sibling.getName().equals(name)) { |
| 81 | return false; | 100 | return false; |
| 82 | } | 101 | } |
| 83 | } | 102 | } |
| 84 | 103 | ||
| 85 | return true; | 104 | return true; |
| 86 | } | 105 | } |
| 106 | |||
| 107 | private boolean canConflict(Entry<?> entry, Entry<?> sibling) { | ||
| 108 | return entry.canConflictWith(sibling); | ||
| 109 | } | ||
| 110 | |||
| 111 | @Nullable | ||
| 112 | private Entry<?> getShadowedEntry(Entry<?> entry, List<? extends Entry<?>> siblings, String name) { | ||
| 113 | for (Entry<?> sibling : siblings) { | ||
| 114 | if (canShadow(entry, sibling) && sibling.getName().equals(name)) { | ||
| 115 | return sibling; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | return null; | ||
| 120 | } | ||
| 121 | |||
| 122 | private boolean canShadow(Entry<?> entry, Entry<?> sibling) { | ||
| 123 | return entry.canShadow(sibling); | ||
| 124 | } | ||
| 125 | |||
| 126 | private boolean isStatic(Entry<?> entry) { | ||
| 127 | AccessFlags accessFlags = index.getEntryIndex().getEntryAccess(entry); | ||
| 128 | return accessFlags != null && accessFlags.isStatic(); | ||
| 129 | } | ||
| 87 | } | 130 | } |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java index be5f0b38..8659b402 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java | |||
| @@ -122,6 +122,11 @@ public class ClassEntry extends ParentedEntry<ClassEntry> implements Comparable< | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | @Override | 124 | @Override |
| 125 | public boolean canShadow(Entry<?> entry) { | ||
| 126 | return false; | ||
| 127 | } | ||
| 128 | |||
| 129 | @Override | ||
| 125 | public void validateName(ValidationContext vc, String name) { | 130 | public void validateName(ValidationContext vc, String name) { |
| 126 | IdentifierValidation.validateClassName(vc, name, this.isInnerClass()); | 131 | IdentifierValidation.validateClassName(vc, name, this.isInnerClass()); |
| 127 | } | 132 | } |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java index 9615ca8e..71425e0f 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java | |||
| @@ -108,6 +108,8 @@ public interface Entry<P extends Entry<?>> extends Translatable { | |||
| 108 | 108 | ||
| 109 | boolean canConflictWith(Entry<?> entry); | 109 | boolean canConflictWith(Entry<?> entry); |
| 110 | 110 | ||
| 111 | boolean canShadow(Entry<?> entry); | ||
| 112 | |||
| 111 | default ClassEntry getContainingClass() { | 113 | default ClassEntry getContainingClass() { |
| 112 | ClassEntry last = null; | 114 | ClassEntry last = null; |
| 113 | Entry<?> current = this; | 115 | Entry<?> current = this; |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java index c1592a43..b4ad1bac 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java | |||
| @@ -85,7 +85,12 @@ public class FieldEntry extends ParentedEntry<ClassEntry> implements Comparable< | |||
| 85 | 85 | ||
| 86 | @Override | 86 | @Override |
| 87 | public boolean canConflictWith(Entry<?> entry) { | 87 | public boolean canConflictWith(Entry<?> entry) { |
| 88 | return entry instanceof FieldEntry && ((FieldEntry) entry).parent.equals(parent); | 88 | return false; |
| 89 | } | ||
| 90 | |||
| 91 | @Override | ||
| 92 | public boolean canShadow(Entry<?> entry) { | ||
| 93 | return entry instanceof FieldEntry; | ||
| 89 | } | 94 | } |
| 90 | 95 | ||
| 91 | @Override | 96 | @Override |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java index d22188b2..9d0bbedd 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java | |||
| @@ -85,6 +85,11 @@ public class LocalVariableEntry extends ParentedEntry<MethodEntry> implements Co | |||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | @Override | 87 | @Override |
| 88 | public boolean canShadow(Entry<?> entry) { | ||
| 89 | return false; | ||
| 90 | } | ||
| 91 | |||
| 92 | @Override | ||
| 88 | public String toString() { | 93 | public String toString() { |
| 89 | return this.parent + "(" + this.index + ":" + this.name + ")"; | 94 | return this.parent + "(" + this.index + ":" + this.name + ")"; |
| 90 | } | 95 | } |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java index 6fc3f0a0..5ccb9081 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java | |||
| @@ -98,6 +98,11 @@ public class MethodEntry extends ParentedEntry<ClassEntry> implements Comparable | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | @Override | 100 | @Override |
| 101 | public boolean canShadow(Entry<?> entry) { | ||
| 102 | return entry instanceof MethodEntry; | ||
| 103 | } | ||
| 104 | |||
| 105 | @Override | ||
| 101 | public String toString() { | 106 | public String toString() { |
| 102 | return this.getFullName() + this.descriptor; | 107 | return this.getFullName() + this.descriptor; |
| 103 | } | 108 | } |
diff --git a/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java b/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java index b7e67f2b..9dbbb187 100644 --- a/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java +++ b/enigma/src/main/java/cuchaz/enigma/utils/validation/Message.java | |||
| @@ -17,6 +17,8 @@ public class Message { | |||
| 17 | public static final Message UNKNOWN_RECORD_GETTER = create(Type.ERROR, "unknown_record_getter"); | 17 | public static final Message UNKNOWN_RECORD_GETTER = create(Type.ERROR, "unknown_record_getter"); |
| 18 | 18 | ||
| 19 | public static final Message STYLE_VIOLATION = create(Type.WARNING, "style_violation"); | 19 | public static final Message STYLE_VIOLATION = create(Type.WARNING, "style_violation"); |
| 20 | public static final Message SHADOWED_NAME_CLASS = create(Type.WARNING, "shadowed_name_class"); | ||
| 21 | public static final Message SHADOWED_NAME = create(Type.WARNING, "shadowed_name"); | ||
| 20 | 22 | ||
| 21 | public final Type type; | 23 | public final Type type; |
| 22 | public final String textKey; | 24 | public final String textKey; |
diff --git a/enigma/src/main/resources/lang/en_us.json b/enigma/src/main/resources/lang/en_us.json index 82f2d371..3919b9e2 100644 --- a/enigma/src/main/resources/lang/en_us.json +++ b/enigma/src/main/resources/lang/en_us.json | |||
| @@ -217,6 +217,8 @@ | |||
| 217 | "validation.message.illegal_doc_comment_end": "Javadoc comment cannot contain the character sequence '*/'.", | 217 | "validation.message.illegal_doc_comment_end": "Javadoc comment cannot contain the character sequence '*/'.", |
| 218 | "validation.message.reserved_identifier": "'%s' is a reserved identifier.", | 218 | "validation.message.reserved_identifier": "'%s' is a reserved identifier.", |
| 219 | "validation.message.unknown_record_getter": "Could not find a matching record component getter for %s", | 219 | "validation.message.unknown_record_getter": "Could not find a matching record component getter for %s", |
| 220 | "validation.message.shadowed_name_class": "Name '%s' shadows another in '%s'.", | ||
| 221 | "validation.message.shadowed_name": "Name '%s' shadows another entry.", | ||
| 220 | 222 | ||
| 221 | "crash.title": "%s - Crash Report", | 223 | "crash.title": "%s - Crash Report", |
| 222 | "crash.summary": "%s has crashed! =(", | 224 | "crash.summary": "%s has crashed! =(", |