I am trying to extract method calls for a project that I am parsing using the tool spoon developed by INRIA, I already have a methods mysql table where I stored all the methods (methodid, methodname, classid, classname ). I am using the following code to extract the methodcalls within my project:
SpoonAPI spoon = new Launcher();
spoon.addInputResource("C:\\Users\\mouna\\Downloads\\chess and gantt code\\workspace_codeBase\\Chess\\src");
spoon.getEnvironment().setAutoImports(true);
spoon.getEnvironment().setNoClasspath(true);
CtModel model = spoon.buildModel();
//List<String> classnames= new ArrayList<String>();
// Interact with model
Factory factory = spoon.getFactory();
ClassFactory classFactory = factory.Class();
MethodFactory methodFactory = factory.Method();
List<methodcalls> methodcallsList = new ArrayList<methodcalls>();
for(CtType<?> clazz : classFactory.getAll()) {
for(CtMethod<?> method :clazz.getMethods()) {
String methname=method.getSimpleName();
System.out.println("CALLER METHOD=====>"+methname);
List<CtInvocation> methodcalls = method.getElements(new TypeFilter<>(CtInvocation.class));
for( CtInvocation calledmethod: methodcalls) {
//CALLEE EXECUTABLE
String CALLEENAME= calledmethod.getExecutable().getSignature().toString();
String methodCallee=calledmethod.getExecutable().toString();
if(calledmethod.getTarget()!=null) {
//CALLEE TARGET
String CALLEENAMETARGET= calledmethod.getTarget().toString();
System.out.println("TARGET: "+ CALLEENAMETARGET);
}
//CALLEE METHOD INFORMATION
ResultSet callingmethodsrefined2 = st.executeQuery("SELECT methods.* from methods where methods.methodname='"+CALLEENAME+"' ");
while(callingmethodsrefined2.next()) {
String CALLEECLASSNAME = callingmethodsrefined2.getString("classname");
String CALLEECLASSID = callingmethodsrefined2.getString("classid");
String CALLEEID = callingmethodsrefined2.getString("id");
System.out.println("CALLEE CLASS NAME: "+ CALLEECLASSNAME);
}
//CALLER METHOD INFORMATION
String CALLERCLASSNAME=clazz.getQualifiedName() ;
String CallerMethod= method.getSignature();
ResultSet callingmethodsrefined = st.executeQuery("SELECT methods.* from methods where methods.methodname='"+CallerMethod+"'and methods.classname='"+CALLERCLASSNAME+"'");
if(callingmethodsrefined.next()) {
String CallerMethodID = callingmethodsrefined.getString("id");
String CALLERCLASSNAME = callingmethodsrefined.getString("classname");
String CALLERCLASSID = callingmethodsrefined.getString("classid");
System.out.println("CALLEE METHOD ID: "+ CALLEEID);
}
String fullcaller= CALLERCLASSNAME+"."+CallerMethod;
String fullcallee= CALLEECLASSNAME+"."+CALLEENAME;
methodcalls methodcall= new methodcalls(CALLEEID, fullcaller, CALLEECLASSNAME, CallerMethodID, fullcallee, CALLERCLASSNAME);
if( methodcall.contains(methodcallsList, methodcall)==false && CallerMethodID!=null && CALLEEID!=null) {
String statement = "INSERT INTO `methodcalls`(`callermethodid`, `callername`, `callerclass`, `callerclassid`,`fullcaller`,`calleemethodid`, `calleename`, `calleeclass`, `calleeclassid`, `fullcallee`) VALUES ('"+CallerMethodID +"','" +CallerMethod+"','" +CALLERCLASSNAME+"','" +CALLERCLASSID+"','" +fullcaller+"','" +CALLEEID+"','" +CALLEENAME+"','" +CALLEECLASSNAME+"','" +CALLEECLASSID+"','" +fullcallee+"')";
st.executeUpdate(statement);
methodcallsList.add(methodcall);
}
}
}
}
The problem is that I am not able to retrieve the class to which the callee belongs, I am only able to retrieve the method signature, this is a problem since the same method like for example isWhite() can be found in multiple classes so I will end up with multiple results when I query my database "methods" table only based on the method name. I have tried using this to retrieve the class to which the callee belongs to String methodCallee=calledmethod.getExecutable().getClass().getSimpleName(); but that returned: "CtExecutableReferenceImpl".
Another problem that I have is that I am relying on calledmethod.getExecutable() to extract the method callees. However, calledmethod.getTarget() can contain in itself some callees, I printed the content of calledmethod.getTarget() and I got TARGET: getLastPly().getDestination() for one of the callers. In case the target is made of a succession of callees, is there a way to separate all of them? Also, I need to know the list of classes that each of these "target callees" belongs to, I am pretty new to Spoon so I don't really know which APIs to use