Skip to content

Commit aa8d673

Browse files
author
emmanue1
committed
Improve the generation of generic local variables
1 parent afd3af5 commit aa8d673

File tree

9 files changed

+238
-113
lines changed

9 files changed

+238
-113
lines changed

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/processor/ConvertClassFileProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ protected List<ClassFileFieldDeclaration> convertFields(TypeMaker parser, Annota
128128

129129
for (Field field : fields) {
130130
BaseAnnotationReference annotationReferences = convertAnnotationReferences(converter, field);
131-
Type typeField = parser.parseFieldSignature(field);
131+
Type typeField = parser.parseFieldSignature(classFile, field);
132132
ExpressionVariableInitializer variableInitializer = convertFieldInitializer(field, typeField);
133133
FieldDeclarator fieldDeclarator = new FieldDeclarator(field.getName(), variableInitializer);
134134

@@ -168,15 +168,15 @@ protected List<ClassFileConstructorOrMethodDeclaration> convertMethods(TypeMaker
168168
}
169169

170170
if ("<init>".equals(name)) {
171-
TypeMaker.MethodTypes methodTypes = parser.parseConstructorSignature(method);
171+
TypeMaker.MethodTypes methodTypes = parser.parseConstructorSignature(classFile, method);
172172
list.add(new ClassFileConstructorDeclaration(
173173
bodyDeclaration, classFile, method, annotationReferences, methodTypes.typeParameters,
174174
methodTypes.parameterTypes, methodTypes.exceptions, firstLineNumber));
175175
} else if ("<clinit>".equals(name)) {
176176
list.add(new ClassFileStaticInitializerDeclaration(bodyDeclaration, classFile, method, firstLineNumber));
177177
} else {
178178
ClassFileMethodDeclaration methodDeclaration;
179-
TypeMaker.MethodTypes methodTypes = parser.parseMethodSignature(method);
179+
TypeMaker.MethodTypes methodTypes = parser.parseMethodSignature(classFile, method);
180180
list.add(methodDeclaration = new ClassFileMethodDeclaration(
181181
bodyDeclaration, classFile, method, annotationReferences, name, methodTypes.typeParameters,
182182
methodTypes.returnedType, methodTypes.parameterTypes, methodTypes.exceptions, defaultAnnotationValue,

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/util/ByteCodeParser.java

Lines changed: 68 additions & 64 deletions
Large diffs are not rendered by default.

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/util/LocalVariableMaker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ protected void initLocalVariablesFromAttributes(Method method) {
192192
if (dimension == 0) {
193193
lv = new PrimitiveLocalVariable(index, startPc, PrimitiveType.getPrimitiveType(descriptor.charAt(0)), name);
194194
} else {
195-
lv = new ObjectLocalVariable(typeMaker, index, startPc, typeMaker.parseTypeSignature(descriptor.substring(dimension)).createType(dimension), name);
195+
lv = new ObjectLocalVariable(typeMaker, index, startPc, typeMaker.makeFromSignature(descriptor.substring(dimension)).createType(dimension), name);
196196
}
197197
}
198198

@@ -209,7 +209,7 @@ protected void initLocalVariablesFromAttributes(Method method) {
209209

210210
for (LocalVariableType lv : localVariableTypeTable.getLocalVariableTypeTable()) {
211211
updateTypeVisitor.setLocalVariableType(lv);
212-
typeMaker.parseTypeSignature(lv.getSignature()).accept(updateTypeVisitor);
212+
typeMaker.makeFromSignature(lv.getSignature()).accept(updateTypeVisitor);
213213
}
214214
}
215215
}

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/util/TypeMaker.java

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
* http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
3232
*/
3333
public class TypeMaker {
34-
protected HashMap<String, MethodTypes> signatureToMethodTypes = new HashMap<>(1024);
3534
protected HashMap<String, Type> signatureToType = new HashMap<>(1024);
35+
protected HashMap<String, Type> internalTypeNameFieldNameToType = new HashMap<>(1024);
36+
protected HashMap<String, MethodTypes> internalTypeNameMethodNameDescriptorToMethodTypes = new HashMap<>(1024);
37+
protected HashMap<String, MethodTypes> signatureToMethodTypes = new HashMap<>(1024);
3638

3739
public TypeMaker(Loader loader) {
3840
this.loader = loader;
@@ -119,20 +121,22 @@ public TypeTypes parseClassFileSignature(ClassFile classFile) {
119121
return typeTypes;
120122
}
121123

122-
public MethodTypes parseConstructorSignature(Method method) {
124+
public MethodTypes parseConstructorSignature(ClassFile classFile, Method method) {
125+
String key = classFile.getInternalTypeName() + ":<init>" + method.getDescriptor();
123126
AttributeSignature attributeSignature = method.getAttribute("Signature");
127+
MethodTypes methodTypes;
124128

125129
if (attributeSignature == null) {
126-
return parseMethodSignature(method.getDescriptor(), method);
130+
methodTypes = parseMethodSignature(method.getDescriptor(), method);
127131
} else {
128132
// Signature does not contain synthetic parameterTypes like outer type name, for example.
129133
MethodTypes mt1 = parseMethodSignature(attributeSignature.getSignature(), method);
130134
MethodTypes mt2 = parseMethodSignature(method.getDescriptor(), method);
131135

132136
if (mt1.parameterTypes.size() == mt2.parameterTypes.size()) {
133-
return mt1;
137+
methodTypes = mt1;
134138
} else if (mt1.parameterTypes.isEmpty() && (mt1.typeParameters == null)) {
135-
return mt2;
139+
methodTypes = mt2;
136140
} else {
137141
DefaultList<Type> parameters = new DefaultList<>(mt2.parameterTypes);
138142

@@ -146,24 +150,38 @@ public MethodTypes parseConstructorSignature(Method method) {
146150
mt3.returnedType = mt1.returnedType;
147151
mt3.exceptions = mt1.exceptions;
148152

149-
return mt3;
153+
methodTypes = mt3;
150154
}
151155
}
156+
157+
internalTypeNameMethodNameDescriptorToMethodTypes.put(key, methodTypes);
158+
159+
return methodTypes;
152160
}
153161

154-
public MethodTypes parseMethodSignature(Method method) {
162+
public MethodTypes parseMethodSignature(ClassFile classFile, Method method) {
163+
String key = classFile.getInternalTypeName() + ':' + method.getName() + method.getDescriptor();
155164
AttributeSignature attributeSignature = method.getAttribute("Signature");
156165
String signature = (attributeSignature == null) ? method.getDescriptor() : attributeSignature.getSignature();
157-
return parseMethodSignature(signature, method);
166+
MethodTypes methodTypes = parseMethodSignature(signature, method);
167+
168+
internalTypeNameMethodNameDescriptorToMethodTypes.put(key, methodTypes);
169+
170+
return methodTypes;
158171
}
159172

160-
public Type parseFieldSignature(Field field) {
173+
public Type parseFieldSignature(ClassFile classFile, Field field) {
174+
String key = classFile.getInternalTypeName() + ':' + field.getName();
161175
AttributeSignature attributeSignature = field.getAttribute("Signature");
162176
String signature = (attributeSignature == null) ? field.getDescriptor() : attributeSignature.getSignature();
163-
return parseTypeSignature(signature);
177+
Type type = makeFromSignature(signature);
178+
179+
internalTypeNameFieldNameToType.put(key, type);
180+
181+
return type;
164182
}
165183

166-
public Type parseTypeSignature(String signature) {
184+
public Type makeFromSignature(String signature) {
167185
Type type = signatureToType.get(signature);
168186

169187
if (type == null) {
@@ -175,16 +193,6 @@ public Type parseTypeSignature(String signature) {
175193
return type;
176194
}
177195

178-
public DefaultList<Type> parseParameterTypes(String signature) {
179-
MethodTypes methodTypes = parseMethodSignature(signature, null);
180-
return (methodTypes==null) ? DefaultList.<Type>emptyList() : methodTypes.parameterTypes;
181-
}
182-
183-
public Type parseReturnedType(String signature) {
184-
MethodTypes methodTypes = parseMethodSignature(signature, null);
185-
return (methodTypes==null) ? null : methodTypes.returnedType;
186-
}
187-
188196
public static int countDimension(String descriptor) {
189197
int count = 0;
190198

@@ -1252,4 +1260,48 @@ private static void skipAttributes(ClassFileReader reader) {
12521260
reader.skip(attributeLength);
12531261
}
12541262
}
1263+
1264+
public MethodTypes makeMethodTypes(String descriptor) {
1265+
return parseMethodSignature(descriptor, null);
1266+
}
1267+
1268+
public MethodTypes makeMethodTypes(ObjectType objectType, String methodName, String descriptor) {
1269+
if (objectType.getDimension() == 0) {
1270+
String key = objectType.getInternalName() + ':' + methodName + descriptor;
1271+
1272+
if (internalTypeNameMethodNameDescriptorToMethodTypes.containsKey(key)) {
1273+
MethodTypes methodTypes = internalTypeNameMethodNameDescriptorToMethodTypes.get(key);
1274+
1275+
if (methodTypes != null) {
1276+
if (methodTypes.typeParameters == null) {
1277+
return methodTypes;
1278+
}
1279+
}
1280+
} else {
1281+
// Search method
1282+
// ...
1283+
}
1284+
}
1285+
1286+
return parseMethodSignature(descriptor, null);
1287+
}
1288+
1289+
public Type makeFieldType(ObjectType objectType, String fieldName, String descriptor) {
1290+
if (objectType.getDimension() == 0) {
1291+
String key = objectType.getInternalName() + ':' + fieldName;
1292+
1293+
if (internalTypeNameFieldNameToType.containsKey(key)) {
1294+
Type type = internalTypeNameFieldNameToType.get(key);
1295+
1296+
if (type != null) {
1297+
return type;
1298+
}
1299+
} else {
1300+
// Search field
1301+
// ...
1302+
}
1303+
}
1304+
1305+
return makeFromSignature(descriptor);
1306+
}
12551307
}

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/visitor/InitEnumVisitor.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99

1010
import org.jd.core.v1.model.javasyntax.AbstractJavaSyntaxVisitor;
1111
import org.jd.core.v1.model.javasyntax.declaration.*;
12-
import org.jd.core.v1.model.javasyntax.expression.BaseExpression;
13-
import org.jd.core.v1.model.javasyntax.expression.Expressions;
14-
import org.jd.core.v1.model.javasyntax.expression.IntegerConstantExpression;
15-
import org.jd.core.v1.model.javasyntax.expression.NewExpression;
12+
import org.jd.core.v1.model.javasyntax.expression.*;
1613
import org.jd.core.v1.model.javasyntax.statement.Statements;
1714
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.javasyntax.declaration.*;
1815
import org.jd.core.v1.util.DefaultList;
@@ -98,8 +95,14 @@ public void visit(FieldDeclarator declaration) {
9895

9996
@Override
10097
public void visit(NewExpression expression) {
101-
Expressions parameters = (Expressions)expression.getParameters();
102-
IntegerConstantExpression ice = (IntegerConstantExpression)parameters.get(1);
98+
Expressions<Expression> parameters = (Expressions)expression.getParameters();
99+
Expression exp = parameters.get(1);
100+
101+
if (exp.getClass() == CastExpression.class) {
102+
exp = ((CastExpression)exp).getExpression();
103+
}
104+
105+
IntegerConstantExpression ice = (IntegerConstantExpression)exp;
103106

104107
lineNumber = expression.getLineNumber();
105108
index = ice.getValue();

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/visitor/UpdateBridgeMethodVisitor.java

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,29 @@ protected Expression updateExpression(Expression expression) {
6767
}
6868

6969
Class expClass = exp.getClass();
70+
71+
if (expClass == CastExpression.class) {
72+
exp = ((CastExpression)exp).getExpression();
73+
expClass = exp.getClass();
74+
}
75+
7076
int parameterTypesCount = methodBridgeDeclaration.getParameterTypes().size();
7177

7278
if (expClass == FieldReferenceExpression.class) {
7379
FieldReferenceExpression fre = (FieldReferenceExpression) exp;
7480

75-
expression = (parameterTypesCount == 0) ? fre.getExpression() : mie1.getParameters().getFirst();
81+
if (parameterTypesCount == 0) {
82+
expression = fre.getExpression();
83+
} else {
84+
expression = mie1.getParameters().getFirst();
85+
if (expression.getClass() == CastExpression.class) {
86+
CastExpression ce = (CastExpression)expression;
87+
if (ce.getType().getDescriptor().equals(ce.getExpression().getType().getDescriptor())) {
88+
// Remove cast expression
89+
expression = ce.getExpression();
90+
}
91+
}
92+
}
7693

7794
return new FieldReferenceExpression(mie1.getLineNumber(), mie1.getType(), expression, fre.getInternalTypeName(), fre.getName(), fre.getDescriptor());
7895
} else if (expClass == ClassFileMethodInvocationExpression.class) {
@@ -99,18 +116,36 @@ protected Expression updateExpression(Expression expression) {
99116
}
100117
}
101118

102-
return new MethodInvocationExpression(mie1.getLineNumber(), mie2.getType(), mie1Parameters.getFirst(), mie2.getInternalTypeName(), mie2.getName(), mie2.getDescriptor(), newParameters);
119+
expression = mie1Parameters.getFirst();
120+
if (expression.getClass() == CastExpression.class) {
121+
CastExpression ce = (CastExpression)expression;
122+
if (ce.getType().getDescriptor().equals(ce.getExpression().getType().getDescriptor())) {
123+
// Remove cast expression
124+
expression = ce.getExpression();
125+
}
126+
}
127+
128+
return new MethodInvocationExpression(mie1.getLineNumber(), mie2.getType(), expression, mie2.getInternalTypeName(), mie2.getName(), mie2.getDescriptor(), newParameters);
103129
}
104130
} else if (expClass == BinaryOperatorExpression.class) {
105131
BinaryOperatorExpression boe = (BinaryOperatorExpression) exp;
106132
FieldReferenceExpression fre = (FieldReferenceExpression) boe.getLeftExpression();
107133

108134
if (parameterTypesCount == 1) {
135+
expression = mie1.getParameters().getFirst();
136+
if (expression.getClass() == CastExpression.class) {
137+
CastExpression ce = (CastExpression)expression;
138+
if (ce.getType().getDescriptor().equals(ce.getExpression().getType().getDescriptor())) {
139+
// Remove cast expression
140+
expression = ce.getExpression();
141+
}
142+
}
143+
109144
return new BinaryOperatorExpression(
110145
mie1.getLineNumber(), mie1.getType(),
111146
new FieldReferenceExpression(fre.getType(), fre.getExpression(), fre.getInternalTypeName(), fre.getName(), fre.getDescriptor()),
112147
boe.getOperator(),
113-
mie1.getParameters().getFirst(),
148+
expression,
114149
boe.getPriority());
115150
} else if (parameterTypesCount == 2) {
116151
DefaultList<Expression> parameters = mie1.getParameters().getList();
@@ -126,7 +161,18 @@ protected Expression updateExpression(Expression expression) {
126161
PostOperatorExpression poe = (PostOperatorExpression)exp;
127162
FieldReferenceExpression fre = (FieldReferenceExpression) poe.getExpression();
128163

129-
expression = (parameterTypesCount == 0) ? fre.getExpression() : mie1.getParameters().getFirst();
164+
if (parameterTypesCount == 0) {
165+
expression = fre.getExpression();
166+
} else {
167+
expression = mie1.getParameters().getFirst();
168+
if (expression.getClass() == CastExpression.class) {
169+
CastExpression ce = (CastExpression)expression;
170+
if (ce.getType().getDescriptor().equals(ce.getExpression().getType().getDescriptor())) {
171+
// Remove cast expression
172+
expression = ce.getExpression();
173+
}
174+
}
175+
}
130176

131177
return new PostOperatorExpression(
132178
mie1.getLineNumber(),
@@ -136,7 +182,18 @@ protected Expression updateExpression(Expression expression) {
136182
PreOperatorExpression poe = (PreOperatorExpression)exp;
137183
FieldReferenceExpression fre = (FieldReferenceExpression) poe.getExpression();
138184

139-
expression = (parameterTypesCount == 0) ? fre.getExpression() : mie1.getParameters().getFirst();
185+
if (parameterTypesCount == 0) {
186+
expression = fre.getExpression();
187+
} else {
188+
expression = mie1.getParameters().getFirst();
189+
if (expression.getClass() == CastExpression.class) {
190+
CastExpression ce = (CastExpression)expression;
191+
if (ce.getType().getDescriptor().equals(ce.getExpression().getType().getDescriptor())) {
192+
// Remove cast expression
193+
expression = ce.getExpression();
194+
}
195+
}
196+
}
140197

141198
return new PreOperatorExpression(
142199
mie1.getLineNumber(),
@@ -223,6 +280,12 @@ private boolean checkBridgeMethodDeclaration(ClassFileMethodDeclaration bridgeMe
223280
}
224281

225282
Class expClass = exp.getClass();
283+
284+
if (expClass == CastExpression.class) {
285+
exp = ((CastExpression)exp).getExpression();
286+
expClass = exp.getClass();
287+
}
288+
226289
int parameterTypesCount = bridgeMethodDeclaration.getParameterTypes().size();
227290

228291
if (expClass == FieldReferenceExpression.class) {
@@ -329,6 +392,10 @@ private boolean checkBridgeMethodDeclaration(ClassFileMethodDeclaration bridgeMe
329392
}
330393

331394
private boolean checkLocalVariableReference(BaseExpression expression, int index) {
395+
if (expression.getClass() == CastExpression.class) {
396+
expression = ((CastExpression)expression).getExpression();
397+
}
398+
332399
if (expression.getClass() != ClassFileLocalVariableReferenceExpression.class) {
333400
return false;
334401
}

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/visitor/UpdateIntegerConstantTypeVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ protected BaseExpression updateExpressions(List<Type> types, BaseExpression expr
346346
}
347347

348348
protected Expression updateExpression(Type type, Expression expression) {
349-
assert (type != TYPE_VOID);
349+
assert type != TYPE_VOID : "UpdateIntegerConstantTypeVisitor.updateExpression(type, expr) : try to set 'void' to a numeric expression";
350350

351351
if (type != expression.getType()) {
352352
Class clazz = expression.getClass();

src/test/java/org/jd/core/v1/ClassFileToJavaSourceTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.util.HashMap;
3030
import java.util.Map;
3131

32-
3332
public class ClassFileToJavaSourceTest extends TestCase {
3433
protected DeserializeClassFileProcessor deserializer = new DeserializeClassFileProcessor();
3534
protected ClassFileToJavaSyntaxProcessor converter = new ClassFileToJavaSyntaxProcessor();
@@ -2062,7 +2061,7 @@ public void testJdk170GenericClass() throws Exception {
20622061
assertTrue(source.indexOf("public <T, S extends T> List<? extends Number> copy2(List<? super T> dest, List<S> src) throws InvalidParameterException, ClassCastException") != -1);
20632062
assertTrue(source.indexOf("public <T1, T2 extends Exception> List<? extends Number> print(List<? super T1> list) throws T2, InvalidParameterException") != -1);
20642063

2065-
assertTrue(source.matches(PatternMaker.make(": 100 */", "return (T1)call(0);")));
2064+
assertTrue(source.matches(PatternMaker.make(": 100 */", "return call(0);")));
20662065
assertTrue(source.matches(PatternMaker.make(": 104 */", "return (T1)this;")));
20672066

20682067
assertTrue(source.indexOf("/* 104: 104 */") != -1);

0 commit comments

Comments
 (0)