summaryrefslogtreecommitdiff
path: root/enigma/src/main/java/cuchaz
diff options
context:
space:
mode:
authorGravatar 2xsaiko2020-10-02 22:07:23 +0200
committerGravatar 2xsaiko2020-10-02 22:07:23 +0200
commitafe703cd033ef168ee606458e0edd3c1c4a84518 (patch)
treec93729ca040d6ab9a9e63469c0db410d9620a97e /enigma/src/main/java/cuchaz
parentAdd retranslate support to editor context menu (diff)
downloadenigma-fork-afe703cd033ef168ee606458e0edd3c1c4a84518.tar.gz
enigma-fork-afe703cd033ef168ee606458e0edd3c1c4a84518.tar.xz
enigma-fork-afe703cd033ef168ee606458e0edd3c1c4a84518.zip
Revert "Merge pull request #299 from thiakil/validation-changes"
This reverts commit 112a49dccb1fe7792366112bc829352462cd298c, reversing changes made to b8f06abafc47065f980a94c4ddf7be70cee83411.
Diffstat (limited to 'enigma/src/main/java/cuchaz')
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java116
-rw-r--r--enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java21
2 files changed, 26 insertions, 111 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 a84b0fb..f9f3b88 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java
@@ -1,19 +1,15 @@
1package cuchaz.enigma.translation.mapping; 1package cuchaz.enigma.translation.mapping;
2 2
3import java.util.Collection; 3import java.util.Collection;
4import java.util.Objects; 4import java.util.HashSet;
5import java.util.Set;
6import java.util.stream.Collectors; 5import java.util.stream.Collectors;
7 6
8import cuchaz.enigma.analysis.index.InheritanceIndex; 7import cuchaz.enigma.analysis.index.InheritanceIndex;
9import cuchaz.enigma.analysis.index.JarIndex; 8import cuchaz.enigma.analysis.index.JarIndex;
10import cuchaz.enigma.translation.Translator; 9import cuchaz.enigma.translation.Translator;
11import cuchaz.enigma.translation.mapping.tree.EntryTree; 10import cuchaz.enigma.translation.mapping.tree.EntryTree;
12import cuchaz.enigma.translation.representation.AccessFlags;
13import cuchaz.enigma.translation.representation.entry.ClassEntry; 11import cuchaz.enigma.translation.representation.entry.ClassEntry;
14import cuchaz.enigma.translation.representation.entry.DefEntry;
15import cuchaz.enigma.translation.representation.entry.Entry; 12import cuchaz.enigma.translation.representation.entry.Entry;
16import cuchaz.enigma.translation.representation.entry.FieldEntry;
17import cuchaz.enigma.utils.validation.Message; 13import cuchaz.enigma.utils.validation.Message;
18import cuchaz.enigma.utils.validation.ValidationContext; 14import cuchaz.enigma.utils.validation.ValidationContext;
19 15
@@ -39,16 +35,18 @@ public class MappingValidator {
39 35
40 private void validateUnique(ValidationContext vc, Entry<?> entry, String name) { 36 private void validateUnique(ValidationContext vc, Entry<?> entry, String name) {
41 ClassEntry containingClass = entry.getContainingClass(); 37 ClassEntry containingClass = entry.getContainingClass();
42 InheritanceIndex inheritanceIndex = index.getInheritanceIndex(); 38 Collection<ClassEntry> relatedClasses = getRelatedClasses(containingClass);
39
40 for (ClassEntry relatedClass : relatedClasses) {
41 Entry<?> relatedEntry = entry.replaceAncestor(containingClass, relatedClass);
42 Entry<?> translatedEntry = deobfuscator.translate(relatedEntry);
43
44 Collection<Entry<?>> translatedSiblings = obfToDeobf.getSiblings(relatedEntry).stream()
45 .map(deobfuscator::translate)
46 .collect(Collectors.toList());
43 47
44 //Step 1, check it's unique within its own siblings 48 if (!isUnique(translatedEntry, translatedSiblings, name)) {
45 Collection<Entry<?>> directTranslatedSiblings = obfToDeobf.getSiblings(entry).stream() 49 Entry<?> parent = translatedEntry.getParent();
46 .map(deobfuscator::translate)
47 .collect(Collectors.toList());
48 for (Entry<?> sibling : directTranslatedSiblings) {
49 if (entry.canConflictWith(sibling) && sibling.getName().equals(name) && !isSynthetic(entry) && !isSynthetic(sibling)) {
50 // allow clash if one is synthetic and the other is not
51 Entry<?> parent = entry.getParent();
52 if (parent != null) { 50 if (parent != null) {
53 vc.raise(Message.NONUNIQUE_NAME_CLASS, name, parent); 51 vc.raise(Message.NONUNIQUE_NAME_CLASS, name, parent);
54 } else { 52 } else {
@@ -56,88 +54,26 @@ public class MappingValidator {
56 } 54 }
57 } 55 }
58 } 56 }
59
60 //Step 2, check ancestors, ignoring members invisible to children
61 Set<ClassEntry> ancestors = inheritanceIndex.getAncestors(containingClass);
62 for (ClassEntry ancestor : ancestors) {
63 Entry<?> reparentedEntry = entry.replaceAncestor(containingClass, ancestor);
64 Entry<?> translatedEntry = Objects.requireNonNull(deobfuscator.translate(reparentedEntry), "Translation failed");
65 Collection<Entry<?>> translatedSiblings = obfToDeobf.getSiblings(reparentedEntry).stream()
66 .filter(it->!entry.equals(it))//e.g. for root classes, ensure we dont match the name against itself
67 .filter(this::isVisibleToChildren)
68 .collect(Collectors.toList());
69 for (Entry<?> parentSibling : translatedSiblings) {
70 Entry<?> parentSiblingTranslated = Objects.requireNonNull(deobfuscator.translate(parentSibling), "Translation failed");
71 if (translatedEntry.canConflictWith(parentSiblingTranslated) && parentSiblingTranslated.getName().equals(name) && !isAcceptableOverride(parentSibling, entry)) {
72 Entry<?> parent = translatedEntry.getParent();
73 if (parent != null) {
74 vc.raise(Message.NONUNIQUE_NAME_CLASS, name, parent);
75 } else {
76 vc.raise(Message.NONUNIQUE_NAME, name);
77 }
78 }
79 }
80 }
81
82 //Step 3, if this entry is visible to children, see if it clashes with any of their names
83 if (isVisibleToChildren(entry)) {
84 Collection<ClassEntry> children = inheritanceIndex.getDescendants(containingClass);
85 for (ClassEntry child : children) {
86 Entry<?> reparentedEntry = entry.replaceAncestor(containingClass, child);
87 Entry<?> translatedEntry = Objects.requireNonNull(deobfuscator.translate(reparentedEntry), "Translation failed");
88 Collection<Entry<?>> siblings = obfToDeobf.getSiblings(reparentedEntry).stream()
89 .filter(it->!entry.equals(it))//e.g. for root classes, ensure we dont match the name against itself
90 .collect(Collectors.toList());
91 for (Entry<?> childSibling : siblings) {
92 Entry<?> childSiblingTranslated = Objects.requireNonNull(deobfuscator.translate(childSibling), "Translation failed");
93 if (translatedEntry.canConflictWith(childSiblingTranslated) && childSiblingTranslated.getName().equals(name) && !isAcceptableOverride(entry, childSibling)) {
94 Entry<?> parent = translatedEntry.getParent();
95 if (parent != null) {
96 vc.raise(Message.NONUNIQUE_NAME_CLASS, name, parent);
97 } else {
98 vc.raise(Message.NONUNIQUE_NAME, name);
99 }
100 }
101 }
102 }
103 }
104 } 57 }
105 58
106 private boolean isVisibleToChildren(Entry<?> entry) { 59 private Collection<ClassEntry> getRelatedClasses(ClassEntry classEntry) {
107 if (entry instanceof DefEntry) { 60 InheritanceIndex inheritanceIndex = index.getInheritanceIndex();
108 return !((DefEntry<?>) entry).getAccess().isPrivate();
109 }
110 AccessFlags accessFlags = index.getEntryIndex().getEntryAccess(entry);
111 if (accessFlags != null) {
112 return !accessFlags.isPrivate();
113 }
114 return true;//unknown, assume yes
115 }
116
117 private boolean isAcceptableOverride(Entry<?> ancestor, Entry<?> descendent) {
118 if (ancestor instanceof FieldEntry && descendent instanceof FieldEntry){
119 return true;//fields don't apply here
120 }
121
122 AccessFlags ancestorFlags = findAccessFlags(ancestor);
123 AccessFlags descendentFlags = findAccessFlags(descendent);
124
125 if (ancestorFlags == null || descendentFlags == null) {
126 return false;//we can't make any assumptions
127 }
128 61
129 //bad == accessLevel < superAccessLevel 62 Collection<ClassEntry> relatedClasses = new HashSet<>();
130 return !(descendentFlags.getAccessLevel() < ancestorFlags.getAccessLevel()); 63 relatedClasses.add(classEntry);
131 } 64 relatedClasses.addAll(inheritanceIndex.getChildren(classEntry));
65 relatedClasses.addAll(inheritanceIndex.getAncestors(classEntry));
132 66
133 private boolean isSynthetic(Entry<?> entry) { 67 return relatedClasses;
134 AccessFlags accessFlags = findAccessFlags(entry);
135 return accessFlags != null && accessFlags.isSynthetic();
136 } 68 }
137 69
138 private AccessFlags findAccessFlags(Entry<?> entry) { 70 private boolean isUnique(Entry<?> entry, Collection<Entry<?>> siblings, String name) {
139 return (entry instanceof DefEntry) ? ((DefEntry<?>) entry).getAccess() : index.getEntryIndex() 71 for (Entry<?> sibling : siblings) {
140 .getEntryAccess(entry); 72 if (entry.canConflictWith(sibling) && sibling.getName().equals(name)) {
73 return false;
74 }
75 }
76 return true;
141 } 77 }
142 78
143} 79}
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java b/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java
index aa48a5b..b280eef 100644
--- a/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java
+++ b/enigma/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java
@@ -8,10 +8,6 @@ import java.lang.reflect.Modifier;
8public class AccessFlags { 8public class AccessFlags {
9 public static final AccessFlags PRIVATE = new AccessFlags(Opcodes.ACC_PRIVATE); 9 public static final AccessFlags PRIVATE = new AccessFlags(Opcodes.ACC_PRIVATE);
10 public static final AccessFlags PUBLIC = new AccessFlags(Opcodes.ACC_PUBLIC); 10 public static final AccessFlags PUBLIC = new AccessFlags(Opcodes.ACC_PUBLIC);
11 public static final int ACCESS_LEVEL_PUBLIC = 4;
12 public static final int ACCESS_LEVEL_PROTECTED = 3;
13 public static final int ACCESS_LEVEL_PACKAGE_LOCAL = 2;
14 public static final int ACCESS_LEVEL_PRIVATE = 1;
15 11
16 private int flags; 12 private int flags;
17 13
@@ -93,23 +89,6 @@ public class AccessFlags {
93 return this.flags; 89 return this.flags;
94 } 90 }
95 91
96 /**
97 * Adapted from https://github.com/JetBrains/intellij-community/blob/6472c347db91d11bbf02895a767198f9d884b119/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java#L389
98 * @return visibility access level on a 'weakness scale'
99 */
100 public int getAccessLevel() {
101 if (isPrivate()) {
102 return ACCESS_LEVEL_PRIVATE;
103 }
104 if (isProtected()) {
105 return ACCESS_LEVEL_PROTECTED;
106 }
107 if (isPublic()) {
108 return ACCESS_LEVEL_PUBLIC;
109 }
110 return ACCESS_LEVEL_PACKAGE_LOCAL;
111 }
112
113 @Override 92 @Override
114 public boolean equals(Object obj) { 93 public boolean equals(Object obj) {
115 return obj instanceof AccessFlags && ((AccessFlags) obj).flags == flags; 94 return obj instanceof AccessFlags && ((AccessFlags) obj).flags == flags;