JavaParser使用

应用场景:在考试系统中,对每一份编程答案,系统需要计算圈复杂度:默认圈复杂度为1,每一个方法里面有指定代码块:if/while等时,圈复杂度+1

添加依赖

<!--        javaparser-->
        <dependency>
            <groupId>com.github.javaparser</groupId>
            <artifactId>javaparser-core</artifactId>
            <version>3.23.0</version> <!-- 请检查并使用最新版本 -->
        </dependency>

相关类的源码阅读

StaticJavaParser

StaticJavaParser类是JavaParser库中的一个静态工具类,用于解析、分析和操作Java源代码。它提供了一系列静态方法,可以用来解析Java源代码文件,获取源代码的抽象语法树(AST),以及对AST进行遍历、修改和生成新的源代码。

通过StaticJavaParser类,我们可以方便地将Java源代码解析成AST,然后通过遍历AST来分析源代码的结构和内容。我们也可以修改AST中的节点,然后重新生成新的源代码。

StaticJavaParser类也提供了一些方便的方法,例如parse、parseBodyDeclaration、parseExpression等,用于解析特定类型的Java代码片段。

可以看到和parse方法有关源码如下,参数可以是输入流、文件、文件路径、阅读器、代码段:

public static CompilationUnit parse(final InputStream in) {
        return (CompilationUnit)handleResult(newParser().parse(in));
    }

public static CompilationUnit parse(final File file) throws FileNotFoundException {
        return (CompilationUnit)handleResult(newParser().parse(file));
    }

public static CompilationUnit parse(final Path path) throws IOException {
        return (CompilationUnit)handleResult(newParser().parse(path));
    }

public static CompilationUnit parse(final Reader reader) {
        return (CompilationUnit)handleResult(newParser().parse(reader));
    }

public static CompilationUnit parse(String code) {
        return (CompilationUnit)handleResult(newParser().parse(code));
    }

CompilationUnit

CompilationUnit 是 JavaParser 中的一个重要类,表示了 Java 源代码的编译单元,即一个 Java 源代码文件。它包含了该源文件中的所有类、接口、注解、枚举、包声明、导入声明以及它们的注释信息等

MethodDeclaration.class

这个类的主要作用是表示一个方法声明,并提供了一些方法来获取和操作方法的属性,比如返回类型、方法体等。包含的属性有方法的返回类型和代码块。

public class MethodDeclaration extends CallableDeclaration<MethodDeclaration> implements NodeWithType<MethodDeclaration, Type>, NodeWithOptionalBlockStmt<MethodDeclaration>, NodeWithJavadoc<MethodDeclaration>, NodeWithDeclaration, NodeWithSimpleName<MethodDeclaration>, NodeWithParameters<MethodDeclaration>, NodeWithThrownExceptions<MethodDeclaration>, NodeWithTypeParameters<MethodDeclaration>, NodeWithAccessModifiers<MethodDeclaration>, NodeWithAbstractModifier<MethodDeclaration>, NodeWithStaticModifier<MethodDeclaration>, NodeWithFinalModifier<MethodDeclaration>, NodeWithStrictfpModifier<MethodDeclaration>, Resolvable<ResolvedMethodDeclaration> {
    private Type type;
    @OptionalProperty
    private BlockStmt body;
}

Node.findAll()

在当前节点及其子节点中查找特定类型的节点,并将所有找到的节点存储在一个列表中返回

 public <T extends Node> List<T> findAll(Class<T> nodeType) {
        List<T> found = new ArrayList();
        Objects.requireNonNull(found);
        this.walk(nodeType, found::add);
        return found;
    }

不同的代码块也组成了一个类,以IfStmt.class为例,所以可以在每一个method中通过findAll()来找可以增加复杂度的节点,同时让圈复杂度+1

public class IfStmt extends Statement implements NodeWithCondition<IfStmt> {
    private Expression condition;
    private Statement thenStmt;
    @OptionalProperty
    private Statement elseStmt;

实现代码


//计算一个java源代码的圈复杂度
private int calculateComplexityForMethod(String filePath) {
        AtomicInteger complexity_sum = new AtomicInteger();
        try (FileInputStream in = new FileInputStream(filePath)) {
            CompilationUnit cu = StaticJavaParser.parse(in);
            cu.findAll(MethodDeclaration.class).forEach(method -> {
                complexity = 1;
                method.findAll(IfStmt.class).forEach(ifStmt -> complexity++);
                method.findAll(WhileStmt.class).forEach(whileStmt -> complexity++);
                method.findAll(ForStmt.class).forEach(forStmt -> complexity++);
                method.findAll(ConditionalExpr.class).forEach(conditionalExpr -> complexity++);
                method.findAll(BinaryExpr.class, expr -> expr.getOperator() == BinaryExpr.Operator.AND ||
                        expr.getOperator() == BinaryExpr.Operator.OR).forEach(binaryExpr -> complexity++);
//                System.out.println("Complexity for method " + method.getNameAsString() + ": " + complexity);
                complexity_sum.addAndGet(complexity);
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return complexity_sum.get();
    }

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值