11package com .ibm .cldk ;
22
3- import java .io .IOException ;
4- import java .nio .file .Path ;
5- 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 ;
16- import java .util .stream .Collectors ;
17- import java .util .stream .IntStream ;
18-
193import com .github .javaparser .*;
204import com .github .javaparser .ast .*;
215import com .github .javaparser .ast .body .*;
226import com .github .javaparser .ast .comments .Comment ;
237import com .github .javaparser .ast .comments .JavadocComment ;
248import com .github .javaparser .ast .expr .*;
259import com .github .javaparser .ast .nodeTypes .NodeWithJavadoc ;
26- import com .github .javaparser .ast .stmt .*;
27- import com .github .javaparser .printer .lexicalpreservation .LexicalPreservingPrinter ;
28- import com .ibm .cldk .entities .*;
29- import com .ibm .cldk .javaee .EntrypointsFinderFactory ;
30- import org .apache .commons .lang3 .tuple .Pair ;
31-
3210import com .github .javaparser .ast .nodeTypes .NodeWithName ;
11+ import com .github .javaparser .ast .stmt .*;
3312import com .github .javaparser .ast .type .ReferenceType ;
3413import com .github .javaparser .ast .type .Type ;
14+ import com .github .javaparser .printer .lexicalpreservation .LexicalPreservingPrinter ;
3515import com .github .javaparser .resolution .declarations .ResolvedMethodDeclaration ;
16+ import com .github .javaparser .resolution .declarations .ResolvedMethodLikeDeclaration ;
3617import com .github .javaparser .resolution .types .ResolvedType ;
3718import com .github .javaparser .symbolsolver .JavaSymbolSolver ;
3819import com .github .javaparser .symbolsolver .resolution .typesolvers .CombinedTypeSolver ;
4223import com .github .javaparser .utils .SourceRoot ;
4324import com .google .common .collect .Table ;
4425import com .google .common .collect .Tables ;
26+ import com .ibm .cldk .entities .*;
4527import com .ibm .cldk .javaee .CRUDFinderFactory ;
28+ import com .ibm .cldk .javaee .EntrypointsFinderFactory ;
4629import com .ibm .cldk .javaee .utils .enums .CRUDOperationType ;
4730import com .ibm .cldk .javaee .utils .enums .CRUDQueryType ;
4831import com .ibm .cldk .utils .Log ;
32+ import java .io .IOException ;
33+ import java .nio .file .Path ;
34+ import java .nio .file .Paths ;
35+ import java .util .*;
36+ import java .util .regex .Pattern ;
37+ import java .util .stream .Collectors ;
38+ import java .util .stream .IntStream ;
39+ import org .apache .commons .lang3 .tuple .Pair ;
4940
5041@ SuppressWarnings ({"unchecked" , "rawtypes" })
5142public class SymbolTable {
@@ -501,7 +492,7 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
501492 callableNode .setFilePath (filePath );
502493
503494 // add callable signature
504- callableNode .setSignature (callableDecl . getSignature (). asString ( ));
495+ callableNode .setSignature (getTypeErasureSignature ( callableDecl ));
505496
506497 // add comment associated with method/constructor
507498 callableNode .setComments (
@@ -581,11 +572,62 @@ private static Pair<String, Callable> processCallableDeclaration(CallableDeclara
581572 callableNode .setVariableDeclarations (getVariableDeclarations (body ));
582573 callableNode .setCyclomaticComplexity (getCyclomaticComplexity (callableDecl ));
583574
584- String callableSignature = (callableDecl instanceof MethodDeclaration ) ? callableDecl .getSignature ().asString ()
585- : callableDecl .getSignature ().asString ().replace (callableDecl .getSignature ().getName (), "<init>" );
575+ String callableSignature = getTypeErasureSignature (callableDecl );
586576 return Pair .of (callableSignature , callableNode );
587577 }
588578
579+ /**
580+ * Returns type erasure signature for the given callable. Returns regular signature if an
581+ * error occurs in getting erased types.
582+ *
583+ * @param callableDecl: Callable to compute type erasure signature for
584+ * @return String representing type erasure or regular signature
585+ */
586+ private static String getTypeErasureSignature (CallableDeclaration callableDecl ) {
587+ try {
588+ StringBuilder signature = new StringBuilder (
589+ (callableDecl instanceof MethodDeclaration ) ? callableDecl .getNameAsString () : "<init>"
590+ );
591+ List <String > erasureParameterTypes = new ArrayList <>();
592+ for (Object param : callableDecl .getParameters ()) {
593+ Parameter parameter = (Parameter ) param ;
594+ ResolvedType resolvedType = parameter .getType ().resolve ();
595+ if (parameter .isVarArgs ()) {
596+ erasureParameterTypes .add (resolvedType .describe () + "[]" );
597+ } else {
598+ erasureParameterTypes .add (resolvedType .erasure ().describe ());
599+ }
600+ }
601+ signature .append ("(" );
602+ signature .append (String .join (", " , erasureParameterTypes ));
603+ signature .append (")" );
604+ return signature .toString ();
605+ } catch (Throwable e ) {
606+ Log .warn ("Could not compute type erasure signature for " +callableDecl .getSignature ().asString ()+
607+ "; computing regular signature" );
608+ return callableDecl .getSignature ().asString ();
609+ }
610+ }
611+
612+ /**
613+ * Returns type erasure signature for the given method or constructor declaration
614+ * resolved for a call site.
615+ *
616+ * @param methodDecl: Resolved method/constructor to compute type erasure signature for
617+ * @return String representing type erasure signature
618+ */
619+ private static String getTypeErasureSignature (ResolvedMethodLikeDeclaration methodDecl ) {
620+ StringBuilder signature = new StringBuilder (methodDecl .getName ());
621+ List <String > erasureParameterTypes = new ArrayList <>();
622+ for (int i = 0 ; i < methodDecl .getNumberOfParams (); i ++) {
623+ erasureParameterTypes .add (methodDecl .getParam (i ).getType ().erasure ().describe ());
624+ }
625+ signature .append ("(" );
626+ signature .append (String .join (", " , erasureParameterTypes ));
627+ signature .append (")" );
628+ return signature .toString ();
629+ }
630+
589631 private static boolean isEntryPointMethod (CallableDeclaration callableDecl ) {
590632 return EntrypointsFinderFactory .getEntrypointFinders ()
591633 .anyMatch (finder -> finder .isEntrypointMethod (callableDecl ));
@@ -835,8 +877,8 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
835877 // resolve callee and get signature
836878 String calleeSignature = "" ;
837879 try {
838- calleeSignature = methodCallExpr .resolve (). getSignature ( );
839- } catch (RuntimeException exception ) {
880+ calleeSignature = getTypeErasureSignature ( methodCallExpr .resolve ());
881+ } catch (Throwable exception ) {
840882 Log .debug ("Could not resolve method call: " + methodCallExpr + ": " + exception .getMessage ());
841883 }
842884
@@ -845,12 +887,12 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
845887 try {
846888 ResolvedMethodDeclaration resolvedMethodDeclaration = methodCallExpr .resolve ();
847889 accessSpecifier = resolvedMethodDeclaration .accessSpecifier ();
848- } catch (RuntimeException exception ) {
890+ } catch (Throwable exception ) {
849891 Log .debug ("Could not resolve access specifier for method call: " + methodCallExpr + ": "
850892 + exception .getMessage ());
851893 }
852894 // resolve arguments of the method call to types
853- List <String > arguments = methodCallExpr .getArguments ().stream ().map (SymbolTable ::resolveExpression )
895+ List <String > argumentTypes = methodCallExpr .getArguments ().stream ().map (SymbolTable ::resolveExpression )
854896 .collect (Collectors .toList ());
855897 // Get argument string from the callsite
856898 List <String > listOfArgumentStrings = methodCallExpr .getArguments ().stream ().map (Expression ::toString )
@@ -886,7 +928,7 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
886928
887929
888930 callSites .add (createCallSite (methodCallExpr , methodCallExpr .getNameAsString (), receiverName , declaringType ,
889- arguments , returnType , calleeSignature , isStaticCall , false , crudOperation , crudQuery ,
931+ argumentTypes , listOfArgumentStrings , returnType , calleeSignature , isStaticCall , false , crudOperation , crudQuery ,
890932 accessSpecifier ));
891933 }
892934
@@ -895,14 +937,18 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
895937 String instantiatedType = resolveType (objectCreationExpr .getType ());
896938
897939 // resolve arguments of the constructor call to types
898- List <String > arguments = objectCreationExpr .getArguments ().stream ().map (SymbolTable ::resolveExpression )
940+ List <String > argumentTypes = objectCreationExpr .getArguments ().stream ().map (SymbolTable ::resolveExpression )
941+ .collect (Collectors .toList ());
942+
943+ // get argument expressions for constructor call
944+ List <String > argumentExpressions = objectCreationExpr .getArguments ().stream ().map (Expression ::toString )
899945 .collect (Collectors .toList ());
900946
901947 // resolve callee and get signature
902948 String calleeSignature = "" ;
903949 try {
904- calleeSignature = objectCreationExpr .resolve (). getSignature ( );
905- } catch (RuntimeException exception ) {
950+ calleeSignature = getTypeErasureSignature ( objectCreationExpr .resolve ());
951+ } catch (Throwable exception ) {
906952 Log .debug ("Could not resolve constructor call: " + objectCreationExpr + ": " + exception .getMessage ());
907953 }
908954
@@ -911,7 +957,7 @@ private static List<CallSite> getCallSites(Optional<BlockStmt> callableBody) {
911957 .add (createCallSite (objectCreationExpr , "<init>" ,
912958 objectCreationExpr .getScope ().isPresent () ? objectCreationExpr .getScope ().get ().toString ()
913959 : "" ,
914- instantiatedType , arguments , instantiatedType , calleeSignature , false , true , null , null ,
960+ instantiatedType , argumentTypes , argumentExpressions , instantiatedType , calleeSignature , false , true , null , null ,
915961 AccessSpecifier .NONE ));
916962 }
917963
@@ -962,17 +1008,24 @@ private static Optional<CRUDOperationType> findCRUDOperation(String declaringTyp
9621008 * @param calleeName
9631009 * @param receiverExpr
9641010 * @param receiverType
965- * @param arguments
1011+ * @param argumentTypes
1012+ * @param argumentExpr
1013+ * @param returnType
1014+ * @param calleeSignature
9661015 * @param isStaticCall
9671016 * @param isConstructorCall
1017+ * @param crudOperation,
1018+ * @param crudQuery,
1019+ * @param accessSpecifier
9681020 * @return
9691021 */
9701022 private static CallSite createCallSite (
9711023 Expression callExpr ,
9721024 String calleeName ,
9731025 String receiverExpr ,
9741026 String receiverType ,
975- List <String > arguments ,
1027+ List <String > argumentTypes ,
1028+ List <String > argumentExpr ,
9761029 String returnType ,
9771030 String calleeSignature ,
9781031 boolean isStaticCall ,
@@ -998,7 +1051,8 @@ private static CallSite createCallSite(
9981051 callSite .setMethodName (calleeName );
9991052 callSite .setReceiverExpr (receiverExpr );
10001053 callSite .setReceiverType (receiverType );
1001- callSite .setArgumentTypes (arguments );
1054+ callSite .setArgumentTypes (argumentTypes );
1055+ callSite .setArgumentExpr (argumentExpr );
10021056 callSite .setReturnType (returnType );
10031057 callSite .setCalleeSignature (calleeSignature );
10041058 callSite .setStaticCall (isStaticCall );
@@ -1039,7 +1093,7 @@ private static String resolveExpression(Expression expression) {
10391093 if (resolvedType .isReferenceType () || resolvedType .isUnionType ()) {
10401094 return resolvedType .describe ();
10411095 }
1042- } catch (RuntimeException exception ) {
1096+ } catch (Throwable exception ) {
10431097 Log .debug ("Could not resolve expression: " + expression + ": " + exception .getMessage ());
10441098 unresolvedExpressions .add (expression .toString ());
10451099 }
@@ -1060,7 +1114,7 @@ private static String resolveType(Type type) {
10601114 if (!unresolvedTypes .contains (type .asString ())) {
10611115 try {
10621116 return type .resolve ().describe ();
1063- } catch (RuntimeException e ) {
1117+ } catch (Throwable e ) {
10641118 Log .warn ("Could not resolve type: " + type .asString () + ": " + e .getMessage ());
10651119 unresolvedTypes .add (type .asString ());
10661120 }
@@ -1079,6 +1133,20 @@ private static String resolveType(Type type) {
10791133 * project
10801134 * @throws IOException
10811135 */
1136+ private static final String [] EXCLUDED_SOURCE_ROOTS = {
1137+ Paths .get ("src" , "test" , "resources" ).toString (),
1138+ Paths .get ("src" , "it" , "resources" ).toString (),
1139+ Paths .get ("src" , "xdocs-examples" ).toString ()
1140+ };
1141+ private static boolean excludeSourceRoot (Path sourceRoot ) {
1142+ for (String excludedSrcRoot : EXCLUDED_SOURCE_ROOTS ) {
1143+ if (Pattern .compile (excludedSrcRoot ).matcher (sourceRoot .toString ()).find ()) {
1144+ return true ;
1145+ }
1146+ }
1147+ return false ;
1148+ }
1149+
10821150 public static Pair <Map <String , JavaCompilationUnit >, Map <String , List <Problem >>> extractAll (Path projectRootPath )
10831151 throws IOException {
10841152 SymbolSolverCollectionStrategy symbolSolverCollectionStrategy = new SymbolSolverCollectionStrategy ();
@@ -1088,6 +1156,9 @@ public static Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>>
10881156 Map <String , JavaCompilationUnit > symbolTable = new LinkedHashMap <>();
10891157 Map <String , List <Problem >> parseProblems = new HashMap <>();
10901158 for (SourceRoot sourceRoot : projectRoot .getSourceRoots ()) {
1159+ if (excludeSourceRoot (sourceRoot .getRoot ())) {
1160+ continue ;
1161+ }
10911162 for (ParseResult <CompilationUnit > parseResult : sourceRoot .tryToParse ()) {
10921163 if (parseResult .isSuccessful ()) {
10931164 CompilationUnit compilationUnit = LexicalPreservingPrinter .setup (parseResult .getResult ().get ());
0 commit comments