summaryrefslogtreecommitdiff
path: root/src/main/java/oml
diff options
context:
space:
mode:
authorGravatar Thiakil2018-07-24 22:36:08 +0800
committerGravatar Thiakil2018-07-24 22:36:08 +0800
commit8537f73abcf45e4380cf86d29404f61f0c9d88fe (patch)
tree4183f6931d0d01d322fb4317eb31794f109bbe36 /src/main/java/oml
parentmissed a semicolon (diff)
downloadenigma-8537f73abcf45e4380cf86d29404f61f0c9d88fe.tar.gz
enigma-8537f73abcf45e4380cf86d29404f61f0c9d88fe.tar.xz
enigma-8537f73abcf45e4380cf86d29404f61f0c9d88fe.zip
more custom source transformers
Diffstat (limited to 'src/main/java/oml')
-rw-r--r--src/main/java/oml/ast/transformers/InvalidIdentifierFix.java29
-rw-r--r--src/main/java/oml/ast/transformers/Java8Generics.java107
-rw-r--r--src/main/java/oml/ast/transformers/VaragsFixer.java197
3 files changed, 333 insertions, 0 deletions
diff --git a/src/main/java/oml/ast/transformers/InvalidIdentifierFix.java b/src/main/java/oml/ast/transformers/InvalidIdentifierFix.java
new file mode 100644
index 00000000..3e052ded
--- /dev/null
+++ b/src/main/java/oml/ast/transformers/InvalidIdentifierFix.java
@@ -0,0 +1,29 @@
1package oml.ast.transformers;
2
3import com.strobel.decompiler.languages.java.ast.AstNode;
4import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor;
5import com.strobel.decompiler.languages.java.ast.Identifier;
6import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform;
7
8/**
9 * Created by Thiakil on 13/07/2018.
10 */
11public class InvalidIdentifierFix implements IAstTransform {
12 @Override
13 public void run(AstNode compilationUnit) {
14 compilationUnit.acceptVisitor(new Visitor(), null);
15 }
16
17 class Visitor extends DepthFirstAstVisitor<Void,Void>{
18 @Override
19 public Void visitIdentifier(Identifier node, Void data) {
20 super.visitIdentifier(node, data);
21 if (node.getName().equals("do") || node.getName().equals("if")){
22 Identifier newIdentifier = Identifier.create(node.getName() + "_", node.getStartLocation());
23 newIdentifier.copyUserDataFrom(node);
24 node.replaceWith(newIdentifier);
25 }
26 return null;
27 }
28 }
29}
diff --git a/src/main/java/oml/ast/transformers/Java8Generics.java b/src/main/java/oml/ast/transformers/Java8Generics.java
new file mode 100644
index 00000000..0f8a84c1
--- /dev/null
+++ b/src/main/java/oml/ast/transformers/Java8Generics.java
@@ -0,0 +1,107 @@
1package oml.ast.transformers;
2
3import com.strobel.assembler.metadata.BuiltinTypes;
4import com.strobel.assembler.metadata.CommonTypeReferences;
5import com.strobel.assembler.metadata.Flags;
6import com.strobel.assembler.metadata.IGenericInstance;
7import com.strobel.assembler.metadata.IMemberDefinition;
8import com.strobel.assembler.metadata.JvmType;
9import com.strobel.assembler.metadata.MemberReference;
10import com.strobel.assembler.metadata.MethodDefinition;
11import com.strobel.assembler.metadata.TypeDefinition;
12import com.strobel.assembler.metadata.TypeReference;
13import com.strobel.decompiler.languages.java.ast.ArrayCreationExpression;
14import com.strobel.decompiler.languages.java.ast.AstNode;
15import com.strobel.decompiler.languages.java.ast.AstNodeCollection;
16import com.strobel.decompiler.languages.java.ast.AstType;
17import com.strobel.decompiler.languages.java.ast.CastExpression;
18import com.strobel.decompiler.languages.java.ast.ComposedType;
19import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor;
20import com.strobel.decompiler.languages.java.ast.Expression;
21import com.strobel.decompiler.languages.java.ast.Identifier;
22import com.strobel.decompiler.languages.java.ast.InvocationExpression;
23import com.strobel.decompiler.languages.java.ast.Keys;
24import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression;
25import com.strobel.decompiler.languages.java.ast.ObjectCreationExpression;
26import com.strobel.decompiler.languages.java.ast.Roles;
27import com.strobel.decompiler.languages.java.ast.SimpleType;
28import com.strobel.decompiler.languages.java.ast.WildcardType;
29import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform;
30
31/**
32 * Created by Thiakil on 12/07/2018.
33 */
34public class Java8Generics implements IAstTransform {
35
36 @Override
37 public void run(AstNode compilationUnit) {
38 compilationUnit.acceptVisitor(new Visitor(), null);
39 }
40
41 static class Visitor extends DepthFirstAstVisitor<Void,Void>{
42
43 @Override
44 public Void visitInvocationExpression(InvocationExpression node, Void data) {
45 super.visitInvocationExpression(node, data);
46 if (node.getTarget() instanceof MemberReferenceExpression){
47 MemberReferenceExpression referenceExpression = (MemberReferenceExpression) node.getTarget();
48 if (referenceExpression.getTypeArguments().stream().map(t->{
49 TypeReference tr = t.toTypeReference();
50 if (tr.getDeclaringType() != null){//ensure that inner types are resolved so we can get the TypeDefinition below
51 TypeReference resolved = tr.resolve();
52 if (resolved != null)
53 return resolved;
54 }
55 return tr;
56 }).anyMatch(t -> t.isWildcardType() || (t instanceof TypeDefinition && ((TypeDefinition) t).isAnonymous()))) {
57 //these are invalid for invocations, let the compiler work it out
58 referenceExpression.getTypeArguments().clear();
59 } else if (referenceExpression.getTypeArguments().stream().allMatch(t->t.toTypeReference().equals(CommonTypeReferences.Object))){
60 //all are <Object>, thereby redundant and/or bad
61 referenceExpression.getTypeArguments().clear();
62 }
63 }
64 return null;
65 }
66
67 @Override
68 public Void visitObjectCreationExpression(ObjectCreationExpression node, Void data) {
69 super.visitObjectCreationExpression(node, data);
70 AstType type = node.getType();
71 if (type instanceof SimpleType && !((SimpleType) type).getTypeArguments().isEmpty()){
72 SimpleType simpleType = (SimpleType) type;
73 AstNodeCollection<AstType> typeArguments = simpleType.getTypeArguments();
74 if (typeArguments.size() == 1 && typeArguments.firstOrNullObject().toTypeReference().equals(CommonTypeReferences.Object)){
75 //all are <Object>, thereby redundant and/or bad
76 typeArguments.firstOrNullObject().getChildByRole(Roles.IDENTIFIER).replaceWith(Identifier.create(""));
77 }
78 }
79 return null;
80 }
81
82 @Override
83 public Void visitCastExpression(CastExpression node, Void data) {
84 boolean doReplace = false;
85 TypeReference typeReference = node.getType().toTypeReference();
86 if (typeReference.isArray() && typeReference.getElementType().isGenericType()){
87 doReplace = true;
88 } else if (typeReference.isGenericType()) {
89 Expression target = node.getExpression();
90 if (typeReference instanceof IGenericInstance && ((IGenericInstance)typeReference).getTypeArguments().stream().anyMatch(t->t.isWildcardType())){
91 doReplace = true;
92 } else if (target instanceof InvocationExpression) {
93 InvocationExpression invocationExpression = (InvocationExpression)target;
94 if (invocationExpression.getTarget() instanceof MemberReferenceExpression && !((MemberReferenceExpression) invocationExpression.getTarget()).getTypeArguments().isEmpty()) {
95 ((MemberReferenceExpression) invocationExpression.getTarget()).getTypeArguments().clear();
96 doReplace = true;
97 }
98 }
99 }
100 super.visitCastExpression(node, data);
101 if (doReplace){
102 node.replaceWith(node.getExpression());
103 }
104 return null;
105 }
106 }
107}
diff --git a/src/main/java/oml/ast/transformers/VaragsFixer.java b/src/main/java/oml/ast/transformers/VaragsFixer.java
new file mode 100644
index 00000000..cd711ae0
--- /dev/null
+++ b/src/main/java/oml/ast/transformers/VaragsFixer.java
@@ -0,0 +1,197 @@
1package oml.ast.transformers;
2
3import com.strobel.assembler.metadata.MemberReference;
4import com.strobel.assembler.metadata.MetadataFilters;
5import com.strobel.assembler.metadata.MetadataHelper;
6import com.strobel.assembler.metadata.MethodBinder;
7import com.strobel.assembler.metadata.MethodDefinition;
8import com.strobel.assembler.metadata.MethodReference;
9import com.strobel.assembler.metadata.TypeReference;
10import com.strobel.core.StringUtilities;
11import com.strobel.core.VerifyArgument;
12import com.strobel.decompiler.DecompilerContext;
13import com.strobel.decompiler.languages.java.ast.ArrayCreationExpression;
14import com.strobel.decompiler.languages.java.ast.ArrayInitializerExpression;
15import com.strobel.decompiler.languages.java.ast.AstNode;
16import com.strobel.decompiler.languages.java.ast.AstNodeCollection;
17import com.strobel.decompiler.languages.java.ast.CastExpression;
18import com.strobel.decompiler.languages.java.ast.ContextTrackingVisitor;
19import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor;
20import com.strobel.decompiler.languages.java.ast.Expression;
21import com.strobel.decompiler.languages.java.ast.InvocationExpression;
22import com.strobel.decompiler.languages.java.ast.JavaResolver;
23import com.strobel.decompiler.languages.java.ast.Keys;
24import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression;
25import com.strobel.decompiler.languages.java.ast.ObjectCreationExpression;
26import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform;
27import com.strobel.decompiler.semantics.ResolveResult;
28
29import java.util.ArrayList;
30import java.util.List;
31
32/**
33 * Created by Thiakil on 12/07/2018.
34 */
35public class VaragsFixer implements IAstTransform {
36 private final DecompilerContext _context;
37
38 public VaragsFixer(final DecompilerContext context) {
39 _context = VerifyArgument.notNull(context, "context");
40 }
41
42 @Override
43 public void run(AstNode compilationUnit) {
44 compilationUnit.acceptVisitor(new Visitor(_context), null);
45 }
46
47 class Visitor extends ContextTrackingVisitor<Void> {
48 private final JavaResolver _resolver;
49 protected Visitor(DecompilerContext context) {
50 super(context);
51 _resolver = new JavaResolver(context);
52 }
53
54 //remove `new Object[0]` on varagrs as the normal tranformer doesnt do them
55 @Override
56 public Void visitInvocationExpression(InvocationExpression node, Void data) {
57 super.visitInvocationExpression(node, data);
58 MemberReference definition = node.getUserData(Keys.MEMBER_REFERENCE);
59 if (definition instanceof MethodDefinition && ((MethodDefinition) definition).isVarArgs()){
60 AstNodeCollection<Expression> arguments = node.getArguments();
61 Expression lastParam = arguments.lastOrNullObject();
62 if (!lastParam.isNull() && lastParam instanceof ArrayCreationExpression){
63 ArrayCreationExpression varargArray = (ArrayCreationExpression)lastParam;
64 if (varargArray.getInitializer().isNull() || varargArray.getInitializer().getElements().isEmpty()){
65 lastParam.remove();
66 } else {
67 for (Expression e : varargArray.getInitializer().getElements()){
68 arguments.insertBefore(varargArray, e.clone());
69 }
70 varargArray.remove();
71 }
72 }
73 }
74 return null;
75 }
76
77 //applies the vararg transform to object creation
78 @Override
79 public Void visitObjectCreationExpression(ObjectCreationExpression node, Void data) {
80 super.visitObjectCreationExpression(node, data);
81 final AstNodeCollection<Expression> arguments = node.getArguments();
82 final Expression lastArgument = arguments.lastOrNullObject();
83
84 Expression arrayArg = lastArgument;
85
86 if (arrayArg instanceof CastExpression)
87 arrayArg = ((CastExpression) arrayArg).getExpression();
88
89 if (arrayArg == null ||
90 arrayArg.isNull() ||
91 !(arrayArg instanceof ArrayCreationExpression &&
92 node.getTarget() instanceof MemberReferenceExpression)) {
93
94 return null;
95 }
96
97 final ArrayCreationExpression newArray = (ArrayCreationExpression) arrayArg;
98 final MemberReferenceExpression target = (MemberReferenceExpression) node.getTarget();
99
100 if (!newArray.getAdditionalArraySpecifiers().hasSingleElement()) {
101 return null;
102 }
103
104 final MethodReference method = (MethodReference) node.getUserData(Keys.MEMBER_REFERENCE);
105
106 if (method == null) {
107 return null;
108 }
109
110 final MethodDefinition resolved = method.resolve();
111
112 if (resolved == null || !resolved.isVarArgs()) {
113 return null;
114 }
115
116 final List<MethodReference> candidates;
117 final Expression invocationTarget = target.getTarget();
118
119 if (invocationTarget == null || invocationTarget.isNull()) {
120 candidates = MetadataHelper.findMethods(
121 context.getCurrentType(),
122 MetadataFilters.matchName(resolved.getName())
123 );
124 }
125 else {
126 final ResolveResult targetResult = _resolver.apply(invocationTarget);
127
128 if (targetResult == null || targetResult.getType() == null) {
129 return null;
130 }
131
132 candidates = MetadataHelper.findMethods(
133 targetResult.getType(),
134 MetadataFilters.matchName(resolved.getName())
135 );
136 }
137
138 final List<TypeReference> argTypes = new ArrayList<>();
139
140 for (final Expression argument : arguments) {
141 final ResolveResult argResult = _resolver.apply(argument);
142
143 if (argResult == null || argResult.getType() == null) {
144 return null;
145 }
146
147 argTypes.add(argResult.getType());
148 }
149
150 final MethodBinder.BindResult c1 = MethodBinder.selectMethod(candidates, argTypes);
151
152 if (c1.isFailure() || c1.isAmbiguous()) {
153 return null;
154 }
155
156 argTypes.remove(argTypes.size() - 1);
157
158 final ArrayInitializerExpression initializer = newArray.getInitializer();
159 final boolean hasElements = !initializer.isNull() && !initializer.getElements().isEmpty();
160
161 if (hasElements) {
162 for (final Expression argument : initializer.getElements()) {
163 final ResolveResult argResult = _resolver.apply(argument);
164
165 if (argResult == null || argResult.getType() == null) {
166 return null;
167 }
168
169 argTypes.add(argResult.getType());
170 }
171 }
172
173 final MethodBinder.BindResult c2 = MethodBinder.selectMethod(candidates, argTypes);
174
175 if (c2.isFailure() ||
176 c2.isAmbiguous() ||
177 !StringUtilities.equals(c2.getMethod().getErasedSignature(), c1.getMethod().getErasedSignature())) {
178
179 return null;
180 }
181
182 lastArgument.remove();
183
184 if (!hasElements) {
185 lastArgument.remove();
186 return null;
187 }
188
189 for (final Expression newArg : initializer.getElements()) {
190 newArg.remove();
191 arguments.add(newArg);
192 }
193
194 return null;
195 }
196 }
197}