Skip to content

Commit 20ebf41

Browse files
committed
Computation of callable signatures after type erasure (to fix duplicate signatures
issue that can occur for generic methods) Signed-off-by: Saurabh Sinha <[email protected]>
1 parent bcd58a6 commit 20ebf41

File tree

1 file changed

+63
-20
lines changed

1 file changed

+63
-20
lines changed

src/main/java/com/ibm/cldk/SymbolTable.java

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,7 @@
33
import java.io.IOException;
44
import java.nio.file.Path;
55
import java.nio.file.Paths;
6-
import java.util.ArrayList;
7-
import java.util.Collections;
8-
import java.util.HashMap;
9-
import java.util.HashSet;
10-
import java.util.LinkedHashMap;
11-
import java.util.List;
12-
import java.util.Map;
13-
import java.util.Objects;
14-
import java.util.Optional;
15-
import java.util.Set;
6+
import java.util.*;
167
import java.util.stream.Collectors;
178
import java.util.stream.IntStream;
189

@@ -25,6 +16,7 @@
2516
import com.github.javaparser.ast.nodeTypes.NodeWithJavadoc;
2617
import com.github.javaparser.ast.stmt.*;
2718
import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
19+
import com.github.javaparser.resolution.declarations.ResolvedMethodLikeDeclaration;
2820
import com.ibm.cldk.entities.*;
2921
import com.ibm.cldk.javaee.EntrypointsFinderFactory;
3022
import org.apache.commons.lang3.tuple.Pair;
@@ -501,7 +493,7 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
501493
callableNode.setFilePath(filePath);
502494

503495
// add callable signature
504-
callableNode.setSignature(callableDecl.getSignature().asString());
496+
callableNode.setSignature(getTypeErasureSignature(callableDecl));
505497

506498
// add comment associated with method/constructor
507499
callableNode.setComments(
@@ -581,11 +573,62 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
581573
callableNode.setVariableDeclarations(getVariableDeclarations(body));
582574
callableNode.setCyclomaticComplexity(getCyclomaticComplexity(callableDecl));
583575

584-
String callableSignature = (callableDecl instanceof MethodDeclaration) ? callableDecl.getSignature().asString()
585-
: callableDecl.getSignature().asString().replace(callableDecl.getSignature().getName(), "<init>");
576+
String callableSignature = getTypeErasureSignature(callableDecl);
586577
return Pair.of(callableSignature, callableNode);
587578
}
588579

580+
/**
581+
* Returns type erasure signature for the given callable. Returns regular signature if an
582+
* error occurs in getting erased types.
583+
*
584+
* @param callableDecl: Callable to compute type erasure signature for
585+
* @return String representing type erasure or regular signature
586+
*/
587+
private static String getTypeErasureSignature(CallableDeclaration callableDecl) {
588+
try {
589+
StringBuffer signature = new StringBuffer(
590+
(callableDecl instanceof MethodDeclaration) ? callableDecl.getNameAsString() : "<init>"
591+
);
592+
List<String> erasureParameterTypes = new ArrayList<>();
593+
for (Object param : callableDecl.getParameters()) {
594+
Parameter parameter = (Parameter) param;
595+
ResolvedType resolvedType = parameter.getType().resolve();
596+
if (parameter.isVarArgs()) {
597+
erasureParameterTypes.add(resolvedType.describe() + "[]");
598+
} else {
599+
erasureParameterTypes.add(resolvedType.erasure().describe());
600+
}
601+
}
602+
signature.append("(");
603+
signature.append(String.join(", ", erasureParameterTypes));
604+
signature.append(")");
605+
return signature.toString();
606+
} catch (Throwable e) {
607+
Log.warn("Could not compute type erasure signature for "+callableDecl.getSignature().asString()+
608+
"; computing regular signature");
609+
return callableDecl.getSignature().asString();
610+
}
611+
}
612+
613+
/**
614+
* Returns type erasure signature for the given method or constructor declaration
615+
* resolved for a call site.
616+
*
617+
* @param methodDecl: Resolved method/constructor to compute type erasure signature for
618+
* @return String representing type erasure signature
619+
*/
620+
private static String getTypeErasureSignature(ResolvedMethodLikeDeclaration methodDecl) {
621+
StringBuffer signature = new StringBuffer(methodDecl.getName());
622+
List<String> erasureParameterTypes = new ArrayList<>();
623+
for (int i = 0; i < methodDecl.getNumberOfParams(); i++) {
624+
erasureParameterTypes.add(methodDecl.getParam(i).getType().erasure().describe());
625+
}
626+
signature.append("(");
627+
signature.append(String.join(", ", erasureParameterTypes));
628+
signature.append(")");
629+
return signature.toString();
630+
}
631+
589632
private static boolean isEntryPointMethod(CallableDeclaration callableDecl) {
590633
return EntrypointsFinderFactory.getEntrypointFinders()
591634
.anyMatch(finder -> finder.isEntrypointMethod(callableDecl));
@@ -835,8 +878,8 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
835878
// resolve callee and get signature
836879
String calleeSignature = "";
837880
try {
838-
calleeSignature = methodCallExpr.resolve().getSignature();
839-
} catch (RuntimeException exception) {
881+
calleeSignature = getTypeErasureSignature(methodCallExpr.resolve());
882+
} catch (Throwable exception) {
840883
Log.debug("Could not resolve method call: " + methodCallExpr + ": " + exception.getMessage());
841884
}
842885

@@ -845,7 +888,7 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
845888
try {
846889
ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr.resolve();
847890
accessSpecifier = resolvedMethodDeclaration.accessSpecifier();
848-
} catch (RuntimeException exception) {
891+
} catch (Throwable exception) {
849892
Log.debug("Could not resolve access specifier for method call: " + methodCallExpr + ": "
850893
+ exception.getMessage());
851894
}
@@ -901,8 +944,8 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
901944
// resolve callee and get signature
902945
String calleeSignature = "";
903946
try {
904-
calleeSignature = objectCreationExpr.resolve().getSignature();
905-
} catch (RuntimeException exception) {
947+
calleeSignature = getTypeErasureSignature(objectCreationExpr.resolve());
948+
} catch (Throwable exception) {
906949
Log.debug("Could not resolve constructor call: " + objectCreationExpr + ": " + exception.getMessage());
907950
}
908951

@@ -1039,7 +1082,7 @@ private static String resolveExpression(Expression expression) {
10391082
if (resolvedType.isReferenceType() || resolvedType.isUnionType()) {
10401083
return resolvedType.describe();
10411084
}
1042-
} catch (RuntimeException exception) {
1085+
} catch (Throwable exception) {
10431086
Log.debug("Could not resolve expression: " + expression + ": " + exception.getMessage());
10441087
unresolvedExpressions.add(expression.toString());
10451088
}
@@ -1060,7 +1103,7 @@ private static String resolveType(Type type) {
10601103
if (!unresolvedTypes.contains(type.asString())) {
10611104
try {
10621105
return type.resolve().describe();
1063-
} catch (RuntimeException e) {
1106+
} catch (Throwable e) {
10641107
Log.warn("Could not resolve type: " + type.asString() + ": " + e.getMessage());
10651108
unresolvedTypes.add(type.asString());
10661109
}

0 commit comments

Comments
 (0)