首页 > 解决方案 > INRIA SPOON API MethodCalls-Retrieve Callee Classes for method.getExecutable() 和 method.getTarget()

问题描述

我正在尝试使用 INRIA 开发的工具勺为我正在解析的项目提取方法调用,我已经有一个方法 mysql 表,其中存储了所有方法(methodid、methodname、classid、classname)。我正在使用以下代码来提取项目中的方法调用:

    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); 
            }


        }
    }
}

问题是我无法检索被调用者所属的类,我只能检索方法签名,这是一个问题,因为可以在多个类中找到相同的方法,例如 isWhite() 所以我当我仅根据方法名称查询我的数据库“方法”表时,最终会得到多个结果。我尝试使用它来检索被调用者所属的类 String methodCallee=calledmethod.getExecutable().getClass().getSimpleName(); 但返回:“CtExecutableReferenceImpl”。

我遇到的另一个问题是我依靠 calledmethod.getExecutable() 来提取方法被调用者。但是, calledmethod.getTarget() 本身可以包含一些被调用者,我打印了 calledmethod.getTarget() 的内容,并为其中一个调用者获得了 TARGET: getLastPly().getDestination() 。如果目标是由一系列被调用者组成的,有没有办法将它们全部分开?另外,我需要知道每个“目标被调用者”所属的类列表,我对 Spoon 很陌生,所以我真的不知道要使用哪些 API

标签: javamethodsinria-spoon

解决方案


我尝试使用它来检索被调用者所属的类 String methodCallee=calledmethod.getExecutable().getClass().getSimpleName(); 但返回:“CtExecutableReferenceImpl”。

我认为您正在寻找的方法实际上是getDeclaringType(). 该方法在界面中不可用,CtExecutable因此您必须检查您的可执行文件确实是一个实例,CtMethod并且在转换后您可以使用getDeclaringType. 见:http ://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/reflect/declaration/CtTypeMember.html#getDeclaringType--

我不确定你的第二个问题是否理解:你能提供一个例子吗?


推荐阅读