Skip to content

Commit fafc656

Browse files
author
emmanue1
committed
Fix generic cast missing
1 parent 405b0c7 commit fafc656

10 files changed

+178
-93
lines changed

src/main/java/org/jd/core/v1/service/converter/classfiletojavasyntax/model/javasyntax/expression/ClassFileMethodInvocationExpression.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,20 @@
1313
import org.jd.core.v1.model.javasyntax.type.BaseType;
1414
import org.jd.core.v1.model.javasyntax.type.BaseTypeParameter;
1515
import org.jd.core.v1.model.javasyntax.type.Type;
16-
import org.jd.core.v1.service.converter.classfiletojavasyntax.util.AbstractTypeParametersToTypeArgumentsBinder;
1716

1817
public class ClassFileMethodInvocationExpression extends MethodInvocationExpression {
19-
protected AbstractTypeParametersToTypeArgumentsBinder binder;
2018
protected BaseTypeParameter typeParameters;
2119
protected BaseType parameterTypes;
2220
protected boolean bound = false;
2321

2422
public ClassFileMethodInvocationExpression(
25-
AbstractTypeParametersToTypeArgumentsBinder binder,
2623
int lineNumber, BaseTypeParameter typeParameters, Type type, Expression expression,
2724
String internalTypeName, String name, String descriptor, BaseType parameterTypes, BaseExpression parameters) {
2825
super(lineNumber, type, expression, internalTypeName, name, descriptor, parameters);
29-
this.binder = binder;
3026
this.typeParameters = typeParameters;
3127
this.parameterTypes = parameterTypes;
3228
}
3329

34-
public AbstractTypeParametersToTypeArgumentsBinder getBinder() {
35-
return binder;
36-
}
37-
3830
public BaseTypeParameter getTypeParameters() {
3931
return typeParameters;
4032
}

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,6 @@ public void updateNewExpression(ClassFileNewExpression ne, String descriptor, Ty
3333
ne.set(descriptor, clone(methodTypes.parameterTypes), parameters);
3434
}
3535

36-
public static void staticBindParameterTypesWithArgumentTypes(Type type, Expression expression) {
37-
if (expression.isMethodInvocationExpression()) {
38-
ClassFileMethodInvocationExpression mie = (ClassFileMethodInvocationExpression)expression;
39-
AbstractTypeParametersToTypeArgumentsBinder binder = mie.getBinder();
40-
41-
if (binder != null) {
42-
binder.bindParameterTypesWithArgumentTypes(type, mie);
43-
}
44-
}
45-
}
46-
4736
protected static BaseType clone(BaseType parameterTypes) {
4837
if ((parameterTypes != null) && parameterTypes.isList()) {
4938
switch (parameterTypes.size()) {

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

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ public ClassFileConstructorInvocationExpression newConstructorInvocationExpressi
5555

5656
Map<String, TypeArgument> bindings = new HashMap<>();
5757
BaseType parameterTypes = clone(methodTypes.parameterTypes);
58-
populateBindings(bindings, null, null, null, methodTypes.typeParameters, TYPE_OBJECT, null, parameterTypes, parameters);
58+
BaseTypeParameter methodTypeParameters = methodTypes.typeParameters;
59+
60+
populateBindings(bindings, null, null, null, methodTypeParameters, TYPE_OBJECT, null, null, null);
5961

6062
parameterTypes = bind(bindings, parameterTypes);
6163
bindParameters(parameterTypes, parameters);
@@ -81,7 +83,7 @@ public ClassFileSuperConstructorInvocationExpression newSuperConstructorInvocati
8183
BaseTypeArgument typeArguments = typeTypes.superType.getTypeArguments();
8284
BaseTypeParameter methodTypeParameters = methodTypes.typeParameters;
8385

84-
populateBindings(bindings, null, typeParameters, typeArguments, methodTypeParameters, TYPE_OBJECT, null, parameterTypes, parameters);
86+
populateBindings(bindings, null, typeParameters, typeArguments, methodTypeParameters, TYPE_OBJECT, null, null, null);
8587
}
8688
}
8789

@@ -96,7 +98,7 @@ public ClassFileMethodInvocationExpression newMethodInvocationExpression(
9698
int lineNumber, Expression expression, ObjectType objectType, String name, String descriptor,
9799
TypeMaker.MethodTypes methodTypes, BaseExpression parameters) {
98100
return new ClassFileMethodInvocationExpression(
99-
this, lineNumber, methodTypes.typeParameters, methodTypes.returnedType, expression,
101+
lineNumber, methodTypes.typeParameters, methodTypes.returnedType, expression,
100102
objectType.getInternalName(), name, descriptor, clone(methodTypes.parameterTypes), parameters);
101103
}
102104

@@ -114,20 +116,20 @@ public FieldReferenceExpression newFieldReferenceExpression(
114116
ObjectType ot = (ObjectType) type;
115117

116118
if (ot.getTypeArguments() != null) {
117-
Map<String, TypeArgument> bindings;
118119
TypeMaker.TypeTypes typeTypes = typeMaker.makeTypeTypes(expressionObjectType.getInternalName());
119120

120121
if (typeTypes == null) {
121-
bindings = contextualBindings;
122+
type = (Type)bind(contextualBindings, type);
122123
} else {
123-
bindings = new HashMap<>();
124+
Map<String, TypeArgument> bindings = new HashMap<>();
124125
BaseTypeParameter typeParameters = typeTypes.typeParameters;
125126
BaseTypeArgument typeArguments = expressionObjectType.getTypeArguments();
127+
boolean partialBinding = populateBindings(bindings, expression, typeParameters, typeArguments, null, TYPE_OBJECT, null, null, null);
126128

127-
populateBindings(bindings, expression, typeParameters, typeArguments, null, TYPE_OBJECT, null, null, null);
129+
if (!partialBinding) {
130+
type = (Type) bind(bindings, type);
131+
}
128132
}
129-
130-
type = (Type)bind(bindings, type);
131133
}
132134
}
133135
}
@@ -381,7 +383,7 @@ public void visit(MethodInvocationExpression expression) {
381383

382384
if (exp.isSuperExpression()) {
383385
typeTypes = typeMaker.makeTypeTypes(internalTypeName);
384-
typeArguments = (typeTypes.superType == null) ? null : typeTypes.superType.getTypeArguments();
386+
typeArguments = (typeTypes == null || typeTypes.superType == null) ? null : typeTypes.superType.getTypeArguments();
385387
} else if (exp.isMethodInvocationExpression()) {
386388
Type t = getExpressionType((ClassFileMethodInvocationExpression) exp);
387389
if ((t != null) && t.isObjectType()) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public ClassFileMethodInvocationExpression newMethodInvocationExpression(
2929
int lineNumber, Expression expression, ObjectType objectType, String name, String descriptor,
3030
TypeMaker.MethodTypes methodTypes, BaseExpression parameters) {
3131
return new ClassFileMethodInvocationExpression(
32-
this, lineNumber, methodTypes.typeParameters, methodTypes.returnedType, expression,
32+
lineNumber, methodTypes.typeParameters, methodTypes.returnedType, expression,
3333
objectType.getInternalName(), name, descriptor, clone(methodTypes.parameterTypes), parameters);
3434
}
3535

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public static Expression create(Expression expression, int lineNumber, String ty
5959
}
6060
}
6161

62-
return new ClassFileMethodInvocationExpression(null, lineNumber, null, ObjectType.TYPE_STRING, expression, typeName, "toString", "()Ljava/lang/String;", null, null);
62+
return new ClassFileMethodInvocationExpression(lineNumber, null, ObjectType.TYPE_STRING, expression, typeName, "toString", "()Ljava/lang/String;", null, null);
6363
}
6464

6565
public static Expression create(String recipe, BaseExpression parameters) {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,10 @@ private Type loadFieldType(ObjectType objectType, String fieldName, String descr
12281228
return type;
12291229
}
12301230

1231+
public void setMethodReturnedType(String internalTypeName, String methodName, String descriptor, Type type) {
1232+
makeMethodTypes(internalTypeName, methodName, descriptor).returnedType = type;
1233+
}
1234+
12311235
public MethodTypes makeMethodTypes(String descriptor) {
12321236
return parseMethodSignature(descriptor, null);
12331237
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (c) 2008, 2019 Emmanuel Dupuy.
3+
* This project is distributed under the GPLv3 license.
4+
* This is a Copyleft license that gives the user the right to use,
5+
* copy and modify the code freely for non-commercial purposes.
6+
*/
7+
8+
package org.jd.core.v1.service.converter.classfiletojavasyntax.visitor;
9+
10+
import org.jd.core.v1.model.classfile.ConstantPool;
11+
import org.jd.core.v1.model.classfile.Method;
12+
import org.jd.core.v1.model.classfile.attribute.AttributeCode;
13+
import org.jd.core.v1.model.classfile.constant.ConstantMemberRef;
14+
import org.jd.core.v1.model.classfile.constant.ConstantNameAndType;
15+
import org.jd.core.v1.model.javasyntax.AbstractJavaSyntaxVisitor;
16+
import org.jd.core.v1.model.javasyntax.declaration.*;
17+
import org.jd.core.v1.model.javasyntax.type.*;
18+
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.javasyntax.declaration.ClassFileBodyDeclaration;
19+
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.javasyntax.declaration.ClassFileMethodDeclaration;
20+
import org.jd.core.v1.service.converter.classfiletojavasyntax.util.TypeMaker;
21+
22+
public class UpdateBridgeMethodTypeVisitor extends AbstractJavaSyntaxVisitor {
23+
protected TypeMaker typeMaker;
24+
25+
public UpdateBridgeMethodTypeVisitor(TypeMaker typeMaker) {
26+
this.typeMaker = typeMaker;
27+
}
28+
29+
@Override
30+
public void visit(BodyDeclaration declaration) {
31+
ClassFileBodyDeclaration bodyDeclaration = (ClassFileBodyDeclaration)declaration;
32+
33+
safeAcceptListDeclaration(bodyDeclaration.getMethodDeclarations());
34+
safeAcceptListDeclaration(bodyDeclaration.getInnerTypeDeclarations());
35+
}
36+
37+
@Override
38+
public void visit(MethodDeclaration declaration) {
39+
if (declaration.isStatic() && declaration.getReturnedType().isObjectType() && declaration.getName().startsWith("access$")) {
40+
TypeMaker.TypeTypes typeTypes = typeMaker.makeTypeTypes(declaration.getReturnedType().getInternalName());
41+
42+
if ((typeTypes != null) && (typeTypes.typeParameters != null)) {
43+
ClassFileMethodDeclaration cfmd = (ClassFileMethodDeclaration) declaration;
44+
Method method = cfmd.getMethod();
45+
byte[] code = method.<AttributeCode>getAttribute("Code").getCode();
46+
int offset = 0;
47+
int opcode = code[offset] & 255;
48+
49+
while (((21 <= opcode) && (opcode <= 45)) || // ILOAD, LLOAD, FLOAD, DLOAD, ..., ILOAD_0 ... ILOAD_3, ..., ALOAD_1, ..., ALOAD_3
50+
((89 <= opcode) && (opcode <= 95))) { // DUP, ..., DUP2_X2, SWAP
51+
opcode = code[++offset] & 255;
52+
}
53+
54+
switch (opcode) {
55+
case 178: case 179: case 180: case 181: // GETSTATIC, PUTSTATIC, GETFIELD, PUTFIELD
56+
int index = ((code[++offset] & 255) << 8) | (code[++offset] & 255);
57+
ConstantPool constants = method.getConstants();
58+
ConstantMemberRef constantMemberRef = constants.getConstant(index);
59+
String typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
60+
ConstantNameAndType constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
61+
String name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
62+
String descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
63+
Type type = typeMaker.makeFieldType(typeName, name, descriptor);
64+
65+
// Update returned generic type of bridge method
66+
typeMaker.setMethodReturnedType(typeName, cfmd.getName(), cfmd.getDescriptor(), type);
67+
break;
68+
case 182: case 183: case 184: case 185: // INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE
69+
index = ((code[++offset] & 255) << 8) | (code[++offset] & 255);
70+
constants = method.getConstants();
71+
constantMemberRef = constants.getConstant(index);
72+
typeName = constants.getConstantTypeName(constantMemberRef.getClassIndex());
73+
constantNameAndType = constants.getConstant(constantMemberRef.getNameAndTypeIndex());
74+
name = constants.getConstantUtf8(constantNameAndType.getNameIndex());
75+
descriptor = constants.getConstantUtf8(constantNameAndType.getDescriptorIndex());
76+
TypeMaker.MethodTypes methodTypes = typeMaker.makeMethodTypes(typeName, name, descriptor);
77+
78+
// Update returned generic type of bridge method
79+
typeMaker.setMethodReturnedType(typeName, cfmd.getName(), cfmd.getDescriptor(), methodTypes.returnedType);
80+
break;
81+
}
82+
}
83+
}
84+
}
85+
86+
@Override public void visit(ConstructorDeclaration declaration) {}
87+
@Override public void visit(StaticInitializerDeclaration declaration) {}
88+
89+
@Override
90+
public void visit(ClassDeclaration declaration) {
91+
safeAccept(declaration.getBodyDeclaration());
92+
}
93+
94+
@Override
95+
public void visit(InterfaceDeclaration declaration) {
96+
safeAccept(declaration.getBodyDeclaration());
97+
}
98+
99+
@Override public void visit(AnnotationDeclaration declaration) {}
100+
@Override public void visit(EnumDeclaration declaration) {}
101+
}

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.javasyntax.expression.ClassFileLocalVariableReferenceExpression;
2121
import org.jd.core.v1.service.converter.classfiletojavasyntax.model.javasyntax.expression.ClassFileMethodInvocationExpression;
2222
import org.jd.core.v1.service.converter.classfiletojavasyntax.util.TypeMaker;
23-
import org.jd.core.v1.service.converter.classfiletojavasyntax.util.AbstractTypeParametersToTypeArgumentsBinder;
2423
import org.jd.core.v1.util.DefaultList;
2524

2625
import java.util.HashMap;
@@ -45,13 +44,7 @@ public boolean init(ClassFileBodyDeclaration bodyDeclaration) {
4544

4645
@Override
4746
public void visit(MethodInvocationExpression expression) {
48-
Expression exp = expression.getExpression();
49-
50-
expression.setExpression(updateExpression(exp));
51-
52-
if (exp != expression.getExpression()) {
53-
AbstractTypeParametersToTypeArgumentsBinder.staticBindParameterTypesWithArgumentTypes(expression.getType(), expression);
54-
}
47+
expression.setExpression(updateExpression(expression.getExpression()));
5548

5649
if (expression.getParameters() != null) {
5750
expression.setParameters(updateBaseExpression(expression.getParameters()));
@@ -107,7 +100,7 @@ protected Expression updateExpression(Expression expression) {
107100
if (methodTypes != null) {
108101
if (mie2.getExpression().isObjectTypeReferenceExpression()) {
109102
// Static method invocation
110-
return new ClassFileMethodInvocationExpression(null, mie1.getLineNumber(), null, methodTypes.returnedType, mie2.getExpression(), mie2.getInternalTypeName(), mie2.getName(), mie2.getDescriptor(), methodTypes.parameterTypes, mie1.getParameters());
103+
return new ClassFileMethodInvocationExpression(mie1.getLineNumber(), null, methodTypes.returnedType, mie2.getExpression(), mie2.getInternalTypeName(), mie2.getName(), mie2.getDescriptor(), methodTypes.parameterTypes, mie1.getParameters());
111104
} else {
112105
BaseExpression mie1Parameters = mie1.getParameters();
113106
BaseExpression newParameters = null;
@@ -125,7 +118,7 @@ protected Expression updateExpression(Expression expression) {
125118
break;
126119
}
127120

128-
return new ClassFileMethodInvocationExpression(mie1.getBinder(), mie1.getLineNumber(), null, methodTypes.returnedType, mie1Parameters.getFirst(), mie2.getInternalTypeName(), mie2.getName(), mie2.getDescriptor(), methodTypes.parameterTypes, newParameters);
121+
return new ClassFileMethodInvocationExpression(mie1.getLineNumber(), null, methodTypes.returnedType, mie1Parameters.getFirst(), mie2.getInternalTypeName(), mie2.getName(), mie2.getDescriptor(), methodTypes.parameterTypes, newParameters);
129122
}
130123
}
131124
} else if (exp.isBinaryOperatorExpression()) {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
public class UpdateJavaSyntaxTreeStep0Visitor extends AbstractJavaSyntaxVisitor {
1616
protected UpdateOuterFieldTypeVisitor updateOuterFieldTypeVisitor;
17+
protected UpdateBridgeMethodTypeVisitor updateBridgeMethodTypeVisitor;
1718

1819
public UpdateJavaSyntaxTreeStep0Visitor(TypeMaker typeMaker) {
19-
updateOuterFieldTypeVisitor = new UpdateOuterFieldTypeVisitor(typeMaker);
20+
this.updateOuterFieldTypeVisitor = new UpdateOuterFieldTypeVisitor(typeMaker);
21+
this.updateBridgeMethodTypeVisitor = new UpdateBridgeMethodTypeVisitor(typeMaker);
2022
}
2123

2224
@Override
@@ -26,6 +28,7 @@ public void visit(BodyDeclaration declaration) {
2628

2729
if (genericTypesSupported) {
2830
updateOuterFieldTypeVisitor.safeAcceptListDeclaration(bodyDeclaration.getInnerTypeDeclarations());
31+
updateBridgeMethodTypeVisitor.visit(declaration);
2932
}
3033
}
3134

0 commit comments

Comments
 (0)