Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit 440461c

Browse files
committed
Add better override handling
1 parent 56baac7 commit 440461c

File tree

3 files changed

+205
-71
lines changed

3 files changed

+205
-71
lines changed

src/main/java/org/spongepowered/obfuscation/merge/MergeEngine.java

Lines changed: 10 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@
2828
import com.google.common.collect.Multimap;
2929
import org.spongepowered.despector.ast.SourceSet;
3030
import org.spongepowered.despector.ast.generic.ClassTypeSignature;
31+
import org.spongepowered.despector.ast.generic.GenericClassTypeSignature;
3132
import org.spongepowered.despector.ast.generic.MethodSignature;
33+
import org.spongepowered.despector.ast.generic.TypeArgument;
34+
import org.spongepowered.despector.ast.generic.TypeParameter;
3235
import org.spongepowered.despector.ast.generic.TypeSignature;
36+
import org.spongepowered.despector.ast.generic.TypeVariableSignature;
3337
import org.spongepowered.despector.ast.type.ClassEntry;
3438
import org.spongepowered.despector.ast.type.FieldEntry;
3539
import org.spongepowered.despector.ast.type.MethodEntry;
@@ -40,9 +44,11 @@
4044
import org.spongepowered.obfuscation.merge.data.MatchEntry;
4145
import org.spongepowered.obfuscation.merge.data.MethodGroup;
4246
import org.spongepowered.obfuscation.merge.data.MethodMatchEntry;
47+
import org.spongepowered.obfuscation.util.MethodGroupBuilder;
4348

4449
import java.util.ArrayList;
4550
import java.util.Collection;
51+
import java.util.Collections;
4652
import java.util.HashMap;
4753
import java.util.List;
4854
import java.util.Map;
@@ -418,77 +424,10 @@ private void generateSubtypes(SourceSet src, Multimap<TypeEntry, TypeEntry> subt
418424
}
419425

420426
private void generateMethodGroups() {
421-
generateMethodGroups(this.old_src, this.old_method_groups, this.old_subtypes);
422-
generateMethodGroups(this.new_src, this.new_method_groups, this.new_subtypes);
423-
}
424-
425-
private void generateMethodGroups(SourceSet src, Map<MethodEntry, MethodGroup> groups, Multimap<TypeEntry, TypeEntry> subtypes) {
426-
for (TypeEntry type : src.getAllClasses()) {
427-
for (MethodEntry mth : type.getMethods()) {
428-
MethodGroup group = groups.get(mth);
429-
if (group != null) {
430-
continue;
431-
}
432-
group = new MethodGroup(mth);
433-
if (!mth.getName().equals("<init>") && !mth.getName().equals("<clinit>")) {
434-
findRelatives(type, mth, group, subtypes);
435-
}
436-
groups.put(mth, group);
437-
}
438-
439-
for (MethodEntry mth : type.getStaticMethods()) {
440-
groups.put(mth, new MethodGroup(mth));
441-
}
442-
}
443-
}
444-
445-
private TypeEntry findHighest(TypeEntry type, MethodEntry mth) {
446-
if (type instanceof ClassEntry) {
447-
ClassEntry cls = (ClassEntry) type;
448-
TypeEntry spr = type.getSource().get(cls.getSuperclassName());
449-
if (spr != null) {
450-
TypeEntry highest = findHighest(spr, mth);
451-
if (highest != null) {
452-
return highest;
453-
}
454-
}
455-
}
456-
for (String intr : type.getInterfaces()) {
457-
TypeEntry inter = type.getSource().get(intr);
458-
if (inter != null) {
459-
TypeEntry highest = findHighest(inter, mth);
460-
if (highest != null) {
461-
return highest;
462-
}
463-
}
464-
}
465-
466-
for (MethodEntry m : type.getMethods()) {
467-
if (m.getName().equals(mth.getName()) && m.getDescription().equals(mth.getDescription())) {
468-
return type;
469-
}
470-
}
471-
return null;
472-
}
473-
474-
private void collectAll(TypeEntry type, MethodEntry mth, MethodGroup group, Multimap<TypeEntry, TypeEntry> subtypes) {
475-
476-
for (MethodEntry m : type.getMethods()) {
477-
if (m.getName().equals(mth.getName()) && m.getDescription().equals(mth.getDescription())) {
478-
group.addMethod(m);
479-
}
480-
}
481-
482-
for (TypeEntry sub : subtypes.get(type)) {
483-
collectAll(sub, mth, group, subtypes);
484-
}
485-
486-
}
487-
488-
private void findRelatives(TypeEntry owner, MethodEntry mth, MethodGroup group, Multimap<TypeEntry, TypeEntry> subtypes) {
489-
TypeEntry highest = findHighest(owner, mth);
490-
491-
collectAll(highest, mth, group, subtypes);
427+
MethodGroupBuilder old_builder = new MethodGroupBuilder(this.old_src, this.old_method_groups, this.old_subtypes);
428+
old_builder.build();
429+
MethodGroupBuilder new_builder = new MethodGroupBuilder(this.new_src, this.new_method_groups, this.new_subtypes);
430+
new_builder.build();
492431
}
493432

494433
public static FieldEntry createDummyField(SourceSet set, String name, TypeSignature desc, String owner) {

src/main/java/org/spongepowered/obfuscation/merge/operation/MergeUtil.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,8 @@ private static <S extends Condition> void create(Class<S> type, ConditionMerger<
840840
create(Return.class, (set, a, b) -> {
841841
if (!a.getValue().isPresent()) {
842842
return !b.getValue().isPresent();
843+
} else if (!b.getValue().isPresent()) {
844+
return false;
843845
}
844846
return merge(set, a.getValue().get(), b.getValue().get());
845847
});
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
* This file is part of SpongeAPI, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.obfuscation.util;
26+
27+
import com.google.common.collect.Multimap;
28+
import org.spongepowered.despector.ast.SourceSet;
29+
import org.spongepowered.despector.ast.generic.ClassSignature;
30+
import org.spongepowered.despector.ast.generic.GenericClassTypeSignature;
31+
import org.spongepowered.despector.ast.generic.MethodSignature;
32+
import org.spongepowered.despector.ast.generic.TypeParameter;
33+
import org.spongepowered.despector.ast.generic.TypeSignature;
34+
import org.spongepowered.despector.ast.generic.TypeVariableSignature;
35+
import org.spongepowered.despector.ast.type.ClassEntry;
36+
import org.spongepowered.despector.ast.type.MethodEntry;
37+
import org.spongepowered.despector.ast.type.TypeEntry;
38+
import org.spongepowered.obfuscation.merge.data.MethodGroup;
39+
40+
import java.util.HashSet;
41+
import java.util.Map;
42+
import java.util.Set;
43+
44+
public class MethodGroupBuilder {
45+
46+
private final SourceSet set;
47+
private final Map<MethodEntry, MethodGroup> groups;
48+
private final Multimap<TypeEntry, TypeEntry> subtypes;
49+
50+
private final Set<TypeEntry> handled = new HashSet<>();
51+
52+
public MethodGroupBuilder(SourceSet set, Map<MethodEntry, MethodGroup> groups, Multimap<TypeEntry, TypeEntry> subtypes) {
53+
this.set = set;
54+
this.groups = groups;
55+
this.subtypes = subtypes;
56+
}
57+
58+
public void build() {
59+
for (TypeEntry type : this.set.getAllClasses()) {
60+
process(type);
61+
}
62+
}
63+
64+
private void process(TypeEntry type) {
65+
if (this.handled.contains(type)) {
66+
return;
67+
}
68+
this.handled.add(type);
69+
if (type instanceof ClassEntry) {
70+
TypeEntry supr = this.set.get(((ClassEntry) type).getSuperclassName());
71+
if (supr != null) {
72+
process(supr);
73+
}
74+
}
75+
for (String intr : type.getInterfaces()) {
76+
TypeEntry intrface = this.set.get(intr);
77+
if (intrface != null) {
78+
process(intrface);
79+
}
80+
}
81+
82+
for (MethodEntry mth : type.getMethods()) {
83+
if (this.groups.get(mth) != null) {
84+
continue;
85+
}
86+
MethodGroup group = new MethodGroup(mth);
87+
this.groups.put(mth, group);
88+
if (!mth.getName().equals("<init>") && !mth.getName().equals("<clinit>")) {
89+
for (TypeEntry sub : this.subtypes.get(type)) {
90+
discoverOverrides(sub, mth.getName(), mth.getDescription(), createSubtypeSignature(sub, type, mth.getMethodSignature()), group);
91+
}
92+
}
93+
}
94+
}
95+
96+
private MethodSignature createSubtypeSignature(TypeEntry sub, TypeEntry owner, MethodSignature sig) {
97+
GenericClassTypeSignature super_sig = null;
98+
ClassSignature clssig = sub.getSignature();
99+
if (clssig.getSuperclassSignature().getName().equals(owner.getName())) {
100+
super_sig = clssig.getSuperclassSignature();
101+
} else {
102+
for (GenericClassTypeSignature intr : clssig.getInterfaceSignatures()) {
103+
if (intr.getName().equals(owner.getName())) {
104+
super_sig = intr;
105+
}
106+
}
107+
}
108+
if (super_sig == null) {
109+
throw new IllegalStateException();
110+
}
111+
112+
MethodSignature subsig = new MethodSignature();
113+
subsig.setReturnType(sig.getReturnType());
114+
subsig.getThrowsSignature().addAll(sig.getThrowsSignature());
115+
subsig.getTypeParameters().addAll(sig.getTypeParameters());
116+
outer: for (int i = 0; i < sig.getParameters().size(); i++) {
117+
TypeSignature n = sig.getParameters().get(i);
118+
if (n instanceof TypeVariableSignature) {
119+
String var = ((TypeVariableSignature) n).getIdentifier();
120+
var = var.substring(1, var.length() - 1);
121+
int j = 0;
122+
for (; j < owner.getSignature().getParameters().size(); j++) {
123+
TypeParameter param = owner.getSignature().getParameters().get(j);
124+
if (param.getIdentifier().equals(var)) {
125+
subsig.getParameters().add(super_sig.getArguments().get(j).getSignature());
126+
continue outer;
127+
}
128+
}
129+
}
130+
subsig.getParameters().add(n);
131+
}
132+
return subsig;
133+
}
134+
135+
private void discoverOverrides(TypeEntry next, String name, String desc, MethodSignature sig, MethodGroup group) {
136+
137+
MethodEntry found = null;
138+
search: for (MethodEntry mth : next.getMethods()) {
139+
if (mth.getName().equals(name)) {
140+
if (mth.getDescription().equals(desc)) {
141+
MethodGroup current = this.groups.get(mth);
142+
if (current == null) {
143+
group.addMethod(mth);
144+
this.groups.put(mth, group);
145+
} else {
146+
mergeGroups(group, current);
147+
group.addMethod(mth);
148+
this.groups.put(mth, group);
149+
}
150+
found = mth;
151+
break;
152+
}
153+
if (mth.getMethodSignature().getParameters().size() != sig.getParameters().size()) {
154+
continue;
155+
}
156+
for (int i = 0; i < mth.getMethodSignature().getParameters().size(); i++) {
157+
TypeSignature param = mth.getMethodSignature().getParameters().get(i);
158+
TypeSignature expected = sig.getParameters().get(i);
159+
if (!param.equals(expected)) {
160+
continue search;
161+
}
162+
}
163+
MethodGroup current = this.groups.get(mth);
164+
if (current == null) {
165+
group.addMethod(mth);
166+
this.groups.put(mth, group);
167+
} else {
168+
mergeGroups(group, current);
169+
}
170+
found = mth;
171+
break;
172+
}
173+
}
174+
175+
if (found != null) {
176+
for (TypeEntry sub : this.subtypes.get(next)) {
177+
discoverOverrides(sub, found.getName(), found.getDescription(), createSubtypeSignature(sub, next, found.getMethodSignature()), group);
178+
}
179+
} else {
180+
for (TypeEntry sub : this.subtypes.get(next)) {
181+
discoverOverrides(sub, name, desc, createSubtypeSignature(sub, next, sig), group);
182+
}
183+
}
184+
}
185+
186+
private void mergeGroups(MethodGroup a, MethodGroup b) {
187+
a.getMethods().addAll(b.getMethods());
188+
for (MethodEntry mth : b.getMethods()) {
189+
this.groups.put(mth, a);
190+
}
191+
}
192+
193+
}

0 commit comments

Comments
 (0)