代码之家  ›  专栏  ›  技术社区  ›  luckcul

Eclipse JDT:如何找到JDK方法调用和ClassInstanceCreation

  •  0
  • luckcul  · 技术社区  · 7 年前

    Eclipse JDT ASTVisitor 从Java源文件中查找Java方法调用和类实例创建。

    是否来自JDK库 .

    那么,如何获得JDK库方法调用(例如:InputStream.read())和类实例(例如:new String())?


    以下是我的代码。

    JdtAstUtil。Java语言

    import java.io.BufferedInputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import org.eclipse.jdt.core.dom.AST;
    import org.eclipse.jdt.core.dom.ASTParser;
    import org.eclipse.jdt.core.dom.CompilationUnit;
    
    public class JdtAstUtil {
        /**
         * get compilation unit of source code
         * @param javaFilePath
         * @return CompilationUnit
         */
        public static CompilationUnit getCompilationUnit(String javaFilePath){
            byte[] input = null;
            try {
                BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(javaFilePath));
                input = new byte[bufferedInputStream.available()];
                bufferedInputStream.read(input);
                bufferedInputStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            ASTParser astParser = ASTParser.newParser(AST.JLS4);
            astParser.setSource(new String(input).toCharArray());
            astParser.setKind(ASTParser.K_COMPILATION_UNIT);
            astParser.setEnvironment(null, null, null, true);
            astParser.setResolveBindings(true);
            astParser.setBindingsRecovery(true);
            astParser.setUnitName("any_name");
            CompilationUnit result = (CompilationUnit) (astParser.createAST(null));
            return result;
        }
    }  
    

    import org.eclipse.jdt.core.dom.*;
    
    public class DemoVisitor extends ASTVisitor {
    
        @Override
        public boolean visit(MethodInvocation node) {
            System.out.println("MethodInvocation:\t" + node.toString());
            System.out.println("\tExpression: " + node.getExpression());
            Expression expression = node.getExpression();
            if(expression != null) {
                ITypeBinding  typeBinding = expression.resolveTypeBinding();
                if (typeBinding != null) {
                    System.out.println("\tType: " + typeBinding.getName());
                }
            }
            System.out.println("\tName: " + node.getName());
            // System.out.println("\t" + node.resolveMethodBinding());
            return true;
        }
    
        public void endVisit(ClassInstanceCreation node) {
            System.out.println("ClassInstanceCreation:\t" + node.toString());
            System.out.println("\tType: " + node.getType().toString());
        }
    }  
    

    DemoVisitorTest。Java语言

    import org.eclipse.jdt.core.dom.CompilationUnit;
    
    public class DemoVisitorTest {
    
        public DemoVisitorTest(String path) {
            CompilationUnit comp = JdtAstUtil.getCompilationUnit(path);
            DemoVisitor visitor = new DemoVisitor();
            comp.accept(visitor);
        }
        public static void main(String args[]) {
            DemoVisitorTest test = new DemoVisitorTest
                    ("/home/luckcul/developSpace/test/test.java");
        }
    }  
    

    测验Java语言

    package com.mtihc.minecraft.myhelppages;
    
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    import org.bukkit.ChatColor;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    
    public class HelpCommandExecutor implements CommandExecutor {
    
        /***
         * Copies bytes from a large (over 2GB) InputStream to an OutputStream.
         * This method uses the provided buffer, so there is no need to use a
         * BufferedInputStream.
         * @param input the InputStream to read from
        * */
        public static long copyLarge(final InputStream input,
                                     final OutputStream output, final byte[] buffer) throws IOException {
            long count = 0;
            int n;
            CommandExecutor t = new CommandExecutor(new String());
            while (EOF != (n = input.read(buffer))) {
                output.write(buffer, 0, n);
            t.test();
                count += n;
            }
            return count;
        }
    }
    

    最后,我得到了这些:

    ClassInstanceCreation:  new String()
        Type: String
    ClassInstanceCreation:  new CommandExecutor(new String())
        Type: CommandExecutor
    MethodInvocation:   input.read(buffer)
        Expression: input
        Type: InputStream
        Name: read
    MethodInvocation:   output.write(buffer,0,n)
        Expression: output
        Type: OutputStream
        Name: write
    MethodInvocation:   t.test()
        Expression: t
        Type: CommandExecutor
        Name: test
    

    在这个例子中,我只想 new String(), InputStream.read(), OutputStream.write() ,它来自JDK库。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Stephan Herrmann    7 年前

    您可能希望使用JDT的Java模型来了解所调用方法的声明类。策略的基本(未经测试)草图:

    ITypeBinding declaringType = invocation.resolveMethodBinding().getDeclaringClass();
    IJavaProject javaProject = JavaCore.create(iProject); // assumes you have an IProject
    IType type = javaProject.findType(declaringType.getQualifiedName());
    IJavaElement root = type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
    IClasspathEntry cpEntry = ((IPackageFragmentRoot) root).getRawClasspathEntry();
    

    cpEntry 应该属于 getEntryKind() CPE_CONTAINER ,及其 getPath() "org.eclipse.jdt.launching.JRE_CONTAINER" .