Java:解析Java源代码,提取方法

ulydmbyx  于 2023-01-11  发布在  Java
关注(0)|答案(8)|浏览(151)

我想解析java源代码文件,并提取方法源代码。
我需要这样的方法:

/** Returns a map with key = method name ; value = method source code */
Map<String,String> getMethods(File javaFile);

有没有一种简单的方法来实现这个目标,比如一个库来帮助我构建我的方法等等?

qxsslcnc

qxsslcnc1#

https://javaparser.org/下载java解析器
你必须写一些代码,这些代码将调用解析器......它将返回一个CompilationUnit:

InputStream in = null;
            CompilationUnit cu = null;
            try
            {
                    in = new SEDInputStream(filename);
                    cu = JavaParser.parse(in);
            }
            catch(ParseException x)
            {
                 // handle parse exceptions here.
            }
            finally
            {
                  in.close();
            }
            return cu;

注意:SEDInputStream是输入流的子类。如果需要,可以使用FileInputStream。
你需要创建一个访问者。你的访问者很简单,因为你只对方法感兴趣:

public class MethodVisitor extends VoidVisitorAdapter
  {
        public void visit(MethodDeclaration n, Object arg)
        {
             // extract method information here.
             // put in to hashmap
        }
  }

要调用访问者,请执行以下操作:

MethodVisitor visitor = new MethodVisitor();
  visitor.visit(cu, null);
e0uiprwp

e0uiprwp2#

QDOX是一个更轻量级的解析器,它只解析到方法级别,也就是说,方法主体不会被解析成语句。它或多或少地提供了你所要求的,即使你需要导航模型来找到正确的名称,因为它不按名称索引类和方法。

f0ofjuux

f0ofjuux3#

您可以使用以下解析器生成器之一来构建解析器:

  1. ANTLR
  2. JavaCC
  3. SableCC
    此外,您还可以使用(或研究其工作原理)现成的东西,例如使用JavaCC的Java Tree Builder和使用ANTLR的RefactorIt
yqhsw0fo

yqhsw0fo4#

您可以将定制doclet与JavaDoc一起使用吗?
Doclet.com可以提供更多的信息。

6tqwzwtp

6tqwzwtp5#

JavaCC是一个Java的“compiler-compiler”(解析器生成器),有很多语法文件,其中一个是Java 1.5的。

7nbnzgx9

7nbnzgx96#

我认为你可以使用ANTLR解析器生成器。
它非常容易使用,ANTLR站点有很多用Java编写的示例。
它还附带了一个eclipse插件。

vmpqdwk3

vmpqdwk37#

您可以使用此存储库。https://github.com/minqukanq/method-extractor/blob/main/README.md
method-extractor是一个用于Java和Python的解析器。

knpiaxh1

knpiaxh18#

我实现了lee的建议,不需要第三方库来实现,下面的例子打印了方法的名称(在Java 17中测试过,但应该可以在Java 1.6中使用,只需要做一些小的修改):

import com.sun.source.util.JavacTask;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.Tree;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class Main {

    public static void main(final String[] args) throws Exception {
        final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        try (final StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, StandardCharsets.UTF_8)) {
            final Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(new File(args[0])));
            final JavacTask javacTask = (JavacTask) compiler.getTask(null, fileManager, null, null, null, compilationUnits);
            final Iterable<? extends CompilationUnitTree> compilationUnitTrees = javacTask.parse();
            final ClassTree classTree = (ClassTree) compilationUnitTrees.iterator().next().getTypeDecls().get(0);
            final List<? extends Tree> classMemberList = classTree.getMembers();
            final List<MethodTree> classMethodMemberList = classMemberList.stream()
                .filter(MethodTree.class::isInstance)
                .map(MethodTree.class::cast)
                .collect(Collectors.toList());
            // just prints the names of the methods
            classMethodMemberList.stream().map(MethodTree::getName)
                .forEachOrdered(System.out::println);
        }
    }

}

请注意,除了ANTLR之外的其他解决方案不支持最新版本的Java,javaparser目前(2023年1月)不完全支持19,JavaCC根据其公开文档似乎不支持Java〉= 9。
Federico Tomassetti在2016年写道,JDK没有解析功能,我回答说他错了。我不反对第三方库,但向开发人员提供虚假信息以推广她/他的东西是不诚实的,也不是我所期望的StackOverflow的行为。我使用了自2006年12月Java 1.6发布以来Java中可用的一些类和API。

相关问题