CLOVER🍀

That was when it all began.

JavaParserのSymbolSolverでメソッド呼び出しなどを解析する

これは、なにをしたくて書いたもの?

前に、Javaのソースコードを解析できるJavaParserというライブラリーを試してみました。

Javaのソースコードを解析できるJavaParserを試す - CLOVER🍀

JavaParserはソースコードをパースしてASTを生成するものでしたが、ここからさらにシンボル解決ができるSymbolSolverを
使ってみたいと思います。

JavaParserとSymbolSolver

SymbolSolverはJavaParserの中に含まれるというか、JavaParserを使う時の依存関係で最初に紹介されます。

JavaParser - Home

GitHubリポジトリーではASTの操作までができればよいということであれば、javaparser-core(JavaParserのみ)を使えば
よいとしています。

GitHub - javaparser/javaparser: Java 1-25 Parser and Abstract Syntax Tree for Java with advanced analysis functionalities.

SymbolSolverを使うことで、パース後のASTに対する解析ができるようになります。これは実際に使っているところを
見た方が早そうなので、先に進めます…。

また例によって情報はあまりなく、サンプルはSymbolSolverを使ったものになっています。

https://github.com/javaparser/javasymbolsolver-maven-sample/blob/master/src/main/java/com/yourorganization/maven_sample/MyAnalysis.java

少し使ってみましょう。

環境

今回の環境はこちら。

$ java --version                                                                                       openjdk 25.0.2 2026-01-20
OpenJDK Runtime Environment (build 25.0.2+10-Ubuntu-124.04)
OpenJDK 64-Bit Server VM (build 25.0.2+10-Ubuntu-124.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.13 (39d686bd50d8e054301e3a68ad44781df6f80dda)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 25.0.2, vendor: Ubuntu, runtime: /usr/lib/jvm/java-25-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "6.8.0-101-generic", arch: "amd64", family: "unix"

準備

Maven依存関係など。

    <properties>
        <maven.compiler.release>25</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.github.javaparser</groupId>
            <artifactId>javaparser-symbol-solver-core</artifactId>
            <version>3.28.0</version>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>6.0.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.27.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.smallrye</groupId>
            <artifactId>jandex</artifactId>
            <version>3.5.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

今回はjavaparser-symbol-solver-coreを使います。

動作確認はテストコードで行い、サブクラスの抽出のためにJandexを含めています。

テスト用のソースコードも用意しておきます。

src/main/java/org/littlewings/javaparser/CalcService.java

package org.littlewings.javaparser;

public class CalcService {
    public int plus(int a, int b) {
        return a + b;
    }

    public int minus(int a, int b) {
        return a - b;
    }
}

src/main/java/org/littlewings/javaparser/Foo.java

package org.littlewings.javaparser;

public class Foo {
    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }
}

src/main/java/org/littlewings/javaparser/App.java

package org.littlewings.javaparser;

public class App {
    public static void main(String... args) {
        CalcService calcService = new CalcService();
        System.out.printf("1 + 2 = %d%n", calcService.plus(1, 2));

        Foo foo = new Foo();
        foo.setBar("hoge");
        System.out.printf("foo#bar = %s%n", foo.getBar());
    }
}

SymbolSolverを使ってみる

では、SymbolSolverを使ってみましょう。

テストコードの雛形はこちら。

src/test/java/JavaParserSymbolResolverTest.java

import com.github.javaparser.JavaParser;
import com.github.javaparser.JavaParserAdapter;
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.BinaryExpr;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.resolution.TypeSolver;
import com.github.javaparser.resolution.UnsolvedSymbolException;
import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import com.github.javaparser.utils.SourceRoot;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.jar.JarFile;
import java.util.stream.Stream;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class JavaParserSymbolResolverTest {

    // ここにテストを書く
}

最初はソースコードを文字列として渡したものから始めてみましょう。

    @Test
    void gettingStarted() {
        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
        typeSolver.add(new ReflectionTypeSolver());

        JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(symbolSolver);
        JavaParserAdapter parser = JavaParserAdapter.of(new JavaParser(parserConfiguration));

        CompilationUnit compilationUnit = parser.parse("""
                public class CalcService {
                    public int plus(int a, int b) {
                        return a + b;
                    }
                
                    public int minus(int a, int b) {
                        return a - b;
                    }
                }""");

        // 2項演算子を検索
        List<BinaryExpr> binaryExprs = compilationUnit.findAll(BinaryExpr.class);

        assertThat(binaryExprs).hasSize(2);

        // a + b
        assertThat(binaryExprs.getFirst().getLeft().asNameExpr().getName().asString()).isEqualTo("a");
        assertThat(binaryExprs.getFirst().getOperator().asString()).isEqualTo("+");
        assertThat(binaryExprs.getFirst().getRight().asNameExpr().getName().asString()).isEqualTo("b");
        // a - b
        assertThat(binaryExprs.getLast().getLeft().asNameExpr().getName().asString()).isEqualTo("a");
        assertThat(binaryExprs.getLast().getOperator().asString()).isEqualTo("-");
        assertThat(binaryExprs.getLast().getRight().asNameExpr().getName().asString()).isEqualTo("b");
    }

順を追って見ていきます。

ここでは型を解決するための方法を指定します。これがTypeSolverで、CombinedTypeSolverを使うと複数の方法で
型を解決できます。ここではReflectionTypeSolverを使い、Javaの標準クラスライブラリーおよびクラスパス上の
範囲で解決できます。

        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
        typeSolver.add(new ReflectionTypeSolver());

作成したTypeSolverを使い、JavaSymbolSolverを作成します。こちらをJavaParserの設定に渡して準備完了です。

        JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(symbolSolver);
        JavaParserAdapter parser = JavaParserAdapter.of(new JavaParser(parserConfiguration));

ソースコードをパース。ここはJavaParserを単体で使った時と変わりませんね。

        CompilationUnit compilationUnit = parser.parse("""
                public class CalcService {
                    public int plus(int a, int b) {
                        return a + b;
                    }
                
                    public int minus(int a, int b) {
                        return a - b;
                    }
                }""");

そしてソースコード内で2項演算子を使っている箇所を検索します。2項演算子はBinaryExprで表現されます。

        // 2項演算子を検索
        List<BinaryExpr> binaryExprs = compilationUnit.findAll(BinaryExpr.class);

もともとのソースコードがa + ba - bの2つの2項演算子を使っていたので、これが抽出できます。

        assertThat(binaryExprs).hasSize(2);

        // a + b
        assertThat(binaryExprs.getFirst().getLeft().asNameExpr().getName().asString()).isEqualTo("a");
        assertThat(binaryExprs.getFirst().getOperator().asString()).isEqualTo("+");
        assertThat(binaryExprs.getFirst().getRight().asNameExpr().getName().asString()).isEqualTo("b");
        // a - b
        assertThat(binaryExprs.getLast().getLeft().asNameExpr().getName().asString()).isEqualTo("a");
        assertThat(binaryExprs.getLast().getOperator().asString()).isEqualTo("-");
        assertThat(binaryExprs.getLast().getRight().asNameExpr().getName().asString()).isEqualTo("b");

BinaryExprNodeのサブクラスで、これらを使って指定のノード(メソッド呼び出しなど)を検索できます。

次はプロジェクトのソースコード内で検索してみましょう。

    @Test
    void queryInSrc() throws IOException {
        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
        typeSolver.add(new ReflectionTypeSolver());
        typeSolver.add(new JavaParserTypeSolver(Path.of("src/main/java")));

        JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(symbolSolver);
        JavaParserAdapter parser = JavaParserAdapter.of(new JavaParser(parserConfiguration));

        CompilationUnit compilationUnit = parser.parse(Path.of("src/main/java/org/littlewings/javaparser/App.java"));

        // メソッド呼び出しを検索
        List<MethodCallExpr> methodCallExprs = compilationUnit.findAll(MethodCallExpr.class).stream().filter(mcr -> {
            ResolvedMethodDeclaration resolvedMethodDeclaration = mcr.resolve();
            return resolvedMethodDeclaration.getQualifiedName().startsWith("org.littlewings.javaparser");
        }).toList();

        assertThat(methodCallExprs).hasSize(3);

        // calcService.plus(1, 2)
        assertThat(methodCallExprs.getFirst().resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.CalcService.plus");
        assertThat(methodCallExprs.getFirst().resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.getFirst().resolve().getClassName()).isEqualTo("CalcService");
        assertThat(methodCallExprs.getFirst().resolve().getName()).isEqualTo("plus");
        assertThat(methodCallExprs.getFirst().getArguments().getFirst().get().asLiteralExpr().toString()).isEqualTo("1");
        assertThat(methodCallExprs.getFirst().getArguments().getLast().get().asLiteralExpr().toString()).isEqualTo("2");

        // foo.setBar("hoge")
        assertThat(methodCallExprs.get(1).resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.Foo.setBar");
        assertThat(methodCallExprs.get(1).resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.get(1).resolve().getClassName()).isEqualTo("Foo");
        assertThat(methodCallExprs.get(1).resolve().getName()).isEqualTo("setBar");
        assertThat(methodCallExprs.get(1).getArguments().getFirst().get().asLiteralExpr().toString()).isEqualTo("\"hoge\"");

        // foo.getBar()
        assertThat(methodCallExprs.getLast().resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.Foo.getBar");
        assertThat(methodCallExprs.getLast().resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.getLast().resolve().getClassName()).isEqualTo("Foo");
        assertThat(methodCallExprs.getLast().resolve().getName()).isEqualTo("getBar");
        assertThat(methodCallExprs.getLast().getArguments()).isEmpty();
    }

今度はTypeSolverの対象にプロジェクトのソースコードを加えます。ここで使うのがJavaParserTypeSolverです。

        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
        typeSolver.add(new ReflectionTypeSolver());
        typeSolver.add(new JavaParserTypeSolver(Path.of("src/main/java")));

ソースコードをパース。

        CompilationUnit compilationUnit = parser.parse(Path.of("src/main/java/org/littlewings/javaparser/App.java"));

今度はメソッド呼び出しを検索。対象は自パッケージのものに絞っています。

        // メソッド呼び出しを検索
        List<MethodCallExpr> methodCallExprs = compilationUnit.findAll(MethodCallExpr.class).stream().filter(mcr -> {
            ResolvedMethodDeclaration resolvedMethodDeclaration = mcr.resolve();
            return resolvedMethodDeclaration.getQualifiedName().startsWith("org.littlewings.javaparser");
        }).toList();

Appクラスにはこう書かれていたので

    public static void main(String... args) {
        CalcService calcService = new CalcService();
        System.out.printf("1 + 2 = %d%n", calcService.plus(1, 2));

        Foo foo = new Foo();
        foo.setBar("hoge");
        System.out.printf("foo#bar = %s%n", foo.getBar());
    }

CalcService#plusFoo#setBarFoo#getBarが一致することになります。

        assertThat(methodCallExprs).hasSize(3);

        // calcService.plus(1, 2)
        assertThat(methodCallExprs.getFirst().resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.CalcService.plus");
        assertThat(methodCallExprs.getFirst().resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.getFirst().resolve().getClassName()).isEqualTo("CalcService");
        assertThat(methodCallExprs.getFirst().resolve().getName()).isEqualTo("plus");
        assertThat(methodCallExprs.getFirst().getArguments().getFirst().get().asLiteralExpr().toString()).isEqualTo("1");
        assertThat(methodCallExprs.getFirst().getArguments().getLast().get().asLiteralExpr().toString()).isEqualTo("2");

        // foo.setBar("hoge")
        assertThat(methodCallExprs.get(1).resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.Foo.setBar");
        assertThat(methodCallExprs.get(1).resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.get(1).resolve().getClassName()).isEqualTo("Foo");
        assertThat(methodCallExprs.get(1).resolve().getName()).isEqualTo("setBar");
        assertThat(methodCallExprs.get(1).getArguments().getFirst().get().asLiteralExpr().toString()).isEqualTo("\"hoge\"");

        // foo.getBar()
        assertThat(methodCallExprs.getLast().resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.Foo.getBar");
        assertThat(methodCallExprs.getLast().resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.getLast().resolve().getClassName()).isEqualTo("Foo");
        assertThat(methodCallExprs.getLast().resolve().getName()).isEqualTo("getBar");
        assertThat(methodCallExprs.getLast().getArguments()).isEmpty();

もちろん、絞り込まなければSystem.out.printlnも対象に挙がってきます。

こちらのJavaParserTypeSolverの効果なのですが、もしここから外した場合は

        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
        typeSolver.add(new ReflectionTypeSolver());
        typeSolver.add(new JavaParserTypeSolver(Path.of("src/main/java")));

このようにCalcServiceのメソッド呼び出しがシンボル解決できなくなります。

    @Test
    void queryInSrcFail() throws IOException {
        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
        typeSolver.add(new ReflectionTypeSolver());

        JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);
        ParserConfiguration parserConfiguration = new ParserConfiguration().setSymbolResolver(symbolSolver);
        JavaParserAdapter parser = JavaParserAdapter.of(new JavaParser(parserConfiguration));

        CompilationUnit compilationUnit = parser.parse(Path.of("src/main/java/org/littlewings/javaparser/App.java"));

        assertThatThrownBy(() -> compilationUnit.findAll(MethodCallExpr.class).stream().filter(mcr -> {
            ResolvedMethodDeclaration resolvedMethodDeclaration = mcr.resolve();
            return resolvedMethodDeclaration.getQualifiedName().startsWith("org.littlewings.javaparser");
        }).toList())
                .isExactlyInstanceOf(UnsolvedSymbolException.class)
                .hasMessage("Unsolved symbol : CalcService");
    }

というわけで、これでシンボル解決の範囲が決まることがわかりましたね。他にもJARファイルを対象にするJarTypeSolverなどが
あります。

またプロジェクト内のソースコードをまるごとパースする方法もあります。この場合はSourceRootを使います。

    @Test
    void queryInProjectSrc() throws IOException {
        CombinedTypeSolver typeSolver = new CombinedTypeSolver();
        typeSolver.add(new ReflectionTypeSolver());
        typeSolver.add(new JavaParserTypeSolver("src/main/java"));

        JavaSymbolSolver symbolSolver = new JavaSymbolSolver(typeSolver);

        SourceRoot sourceRoot = new SourceRoot(Path.of("src/main/java"));
        sourceRoot.getParserConfiguration().setSymbolResolver(symbolSolver);

        // SourceRoot配下の全ソースをパース
        sourceRoot.tryToParse();

        // メソッド呼び出しを検索
        List<MethodCallExpr> methodCallExprs = sourceRoot.getCompilationUnits()
                .stream()
                .flatMap(cu -> cu.findAll(MethodCallExpr.class).stream().filter(mcr -> {
                    ResolvedMethodDeclaration resolvedMethodDeclaration = mcr.resolve();
                    return resolvedMethodDeclaration.getQualifiedName().startsWith("org.littlewings.javaparser");
                }))
                .toList();

        assertThat(methodCallExprs).hasSize(3);

        // calcService.plus(1, 2)
        assertThat(methodCallExprs.getFirst().resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.CalcService.plus");
        assertThat(methodCallExprs.getFirst().resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.getFirst().resolve().getClassName()).isEqualTo("CalcService");
        assertThat(methodCallExprs.getFirst().resolve().getName()).isEqualTo("plus");
        assertThat(methodCallExprs.getFirst().getArguments().getFirst().get().asLiteralExpr().toString()).isEqualTo("1");
        assertThat(methodCallExprs.getFirst().getArguments().getLast().get().asLiteralExpr().toString()).isEqualTo("2");

        // foo.setBar("hoge")
        assertThat(methodCallExprs.get(1).resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.Foo.setBar");
        assertThat(methodCallExprs.get(1).resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.get(1).resolve().getClassName()).isEqualTo("Foo");
        assertThat(methodCallExprs.get(1).resolve().getName()).isEqualTo("setBar");
        assertThat(methodCallExprs.get(1).getArguments().getFirst().get().asLiteralExpr().toString()).isEqualTo("\"hoge\"");

        // foo.getBar()
        assertThat(methodCallExprs.getLast().resolve().getQualifiedName()).isEqualTo("org.littlewings.javaparser.Foo.getBar");
        assertThat(methodCallExprs.getLast().resolve().getPackageName()).isEqualTo("org.littlewings.javaparser");
        assertThat(methodCallExprs.getLast().resolve().getClassName()).isEqualTo("Foo");
        assertThat(methodCallExprs.getLast().resolve().getName()).isEqualTo("getBar");
        assertThat(methodCallExprs.getLast().getArguments()).isEmpty();
    }

最後に、TypeSolverの実装クラスとNodeのサブクラスを載せておきましょう。Jandexで取得します。

TypeSolverインターフェースの実装クラス。これでシンボルの解決範囲が決まるわけですね。

    @Test
    void typeSolvers() throws IOException {
        Indexer indexer = new Indexer();

        try (JarFile jarFile = new JarFile("/path/to/.m2/repository/com/github/javaparser/javaparser-symbol-solver-core/3.28.0/javaparser-symbol-solver-core-3.28.0.jar")) {
            Collections.list(jarFile.entries()).stream()
                    .filter(entry -> entry.getName().endsWith(".class"))
                    .forEach(entry -> {
                        try (InputStream is = jarFile.getInputStream(entry)) {
                            indexer.index(is);
                        } catch (IOException e) {
                            throw new UncheckedIOException(e);
                        }
                    });
        }

        Index index = indexer.complete();

        Collection<ClassInfo> typeSolverImplementationClasses =
                index.getAllKnownImplementations(DotName.createSimple(TypeSolver.class));

        assertThat(typeSolverImplementationClasses.stream().map(ClassInfo::name)).containsExactlyInAnyOrder(
                Stream.of(
                        com.github.javaparser.symbolsolver.resolution.typesolvers.ClassLoaderTypeSolver.class,
                        com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver.class,
                        com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver.class,
                        com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver.class,
                        com.github.javaparser.symbolsolver.resolution.typesolvers.MemoryTypeSolver.class,
                        com.github.javaparser.symbolsolver.resolution.typesolvers.AarTypeSolver.class,
                        com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver.class
                ).map(DotName::createSimple).toList().toArray(new DotName[0])
        );
    }

Nodeのサブクラス。今回は検索に使いましたが、本来はJavaParserがソースコードを解析した結果のことです。
なので、JavaParserに含まれるクラス群です。

    @Test
    void nodeTypes() throws IOException {
        Indexer indexer = new Indexer();

        try (JarFile jarFile = new JarFile("/path/to/.m2/repository/com/github/javaparser/javaparser-core/3.28.0/javaparser-core-3.28.0.jar")) {
            Collections.list(jarFile.entries()).stream()
                    .filter(entry -> entry.getName().endsWith(".class"))
                    .forEach(entry -> {
                        try (InputStream is = jarFile.getInputStream(entry)) {
                            indexer.index(is);
                        } catch (IOException e) {
                            throw new UncheckedIOException(e);
                        }
                    });
        }

        Index index = indexer.complete();

        Collection<ClassInfo> nodeSubClasses =
                index.getAllKnownSubclasses(DotName.createSimple(Node.class));

        assertThat(nodeSubClasses.stream().map(ClassInfo::name)).containsExactlyInAnyOrder(
                Stream.of(
                        com.github.javaparser.ast.ArrayCreationLevel.class,
                        com.github.javaparser.ast.CompilationUnit.class,
                        com.github.javaparser.ast.ImportDeclaration.class,
                        com.github.javaparser.ast.Modifier.class,
                        com.github.javaparser.ast.PackageDeclaration.class,
                        com.github.javaparser.ast.body.AnnotationDeclaration.class,
                        com.github.javaparser.ast.body.AnnotationMemberDeclaration.class,
                        com.github.javaparser.ast.body.BodyDeclaration.class,
                        com.github.javaparser.ast.body.CallableDeclaration.class,
                        com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.class,
                        com.github.javaparser.ast.body.CompactConstructorDeclaration.class,
                        com.github.javaparser.ast.body.ConstructorDeclaration.class,
                        com.github.javaparser.ast.body.EnumConstantDeclaration.class,
                        com.github.javaparser.ast.body.EnumDeclaration.class,
                        com.github.javaparser.ast.body.FieldDeclaration.class,
                        com.github.javaparser.ast.body.InitializerDeclaration.class,
                        com.github.javaparser.ast.body.MethodDeclaration.class,
                        com.github.javaparser.ast.body.Parameter.class,
                        com.github.javaparser.ast.body.ReceiverParameter.class,
                        com.github.javaparser.ast.body.RecordDeclaration.class,
                        com.github.javaparser.ast.body.TypeDeclaration.class,
                        com.github.javaparser.ast.body.VariableDeclarator.class,
                        com.github.javaparser.ast.comments.BlockComment.class,
                        com.github.javaparser.ast.comments.Comment.class,
                        com.github.javaparser.ast.comments.JavadocComment.class,
                        com.github.javaparser.ast.comments.LineComment.class,
                        com.github.javaparser.ast.comments.MarkdownComment.class,
                        com.github.javaparser.ast.comments.TraditionalJavadocComment.class,
                        com.github.javaparser.ast.expr.AnnotationExpr.class,
                        com.github.javaparser.ast.expr.ArrayAccessExpr.class,
                        com.github.javaparser.ast.expr.ArrayCreationExpr.class,
                        com.github.javaparser.ast.expr.ArrayInitializerExpr.class,
                        com.github.javaparser.ast.expr.AssignExpr.class,
                        com.github.javaparser.ast.expr.BinaryExpr.class,
                        com.github.javaparser.ast.expr.BooleanLiteralExpr.class,
                        com.github.javaparser.ast.expr.CastExpr.class,
                        com.github.javaparser.ast.expr.CharLiteralExpr.class,
                        com.github.javaparser.ast.expr.ClassExpr.class,
                        com.github.javaparser.ast.expr.ComponentPatternExpr.class,
                        com.github.javaparser.ast.expr.ConditionalExpr.class,
                        com.github.javaparser.ast.expr.DoubleLiteralExpr.class,
                        com.github.javaparser.ast.expr.EnclosedExpr.class,
                        com.github.javaparser.ast.expr.Expression.class,
                        com.github.javaparser.ast.expr.FieldAccessExpr.class,
                        com.github.javaparser.ast.expr.InstanceOfExpr.class,
                        com.github.javaparser.ast.expr.IntegerLiteralExpr.class,
                        com.github.javaparser.ast.expr.LambdaExpr.class,
                        com.github.javaparser.ast.expr.LiteralExpr.class,
                        com.github.javaparser.ast.expr.LiteralStringValueExpr.class,
                        com.github.javaparser.ast.expr.LongLiteralExpr.class,
                        com.github.javaparser.ast.expr.MarkerAnnotationExpr.class,
                        com.github.javaparser.ast.expr.MatchAllPatternExpr.class,
                        com.github.javaparser.ast.expr.MemberValuePair.class,
                        com.github.javaparser.ast.expr.MethodCallExpr.class,
                        com.github.javaparser.ast.expr.MethodReferenceExpr.class,
                        com.github.javaparser.ast.expr.Name.class,
                        com.github.javaparser.ast.expr.NameExpr.class,
                        com.github.javaparser.ast.expr.NormalAnnotationExpr.class,
                        com.github.javaparser.ast.expr.NullLiteralExpr.class,
                        com.github.javaparser.ast.expr.ObjectCreationExpr.class,
                        com.github.javaparser.ast.expr.PatternExpr.class,
                        com.github.javaparser.ast.expr.RecordPatternExpr.class,
                        com.github.javaparser.ast.expr.SimpleName.class,
                        com.github.javaparser.ast.expr.SingleMemberAnnotationExpr.class,
                        com.github.javaparser.ast.expr.StringLiteralExpr.class,
                        com.github.javaparser.ast.expr.SuperExpr.class,
                        com.github.javaparser.ast.expr.SwitchExpr.class,
                        com.github.javaparser.ast.expr.TextBlockLiteralExpr.class,
                        com.github.javaparser.ast.expr.ThisExpr.class,
                        com.github.javaparser.ast.expr.TypeExpr.class,
                        com.github.javaparser.ast.expr.TypePatternExpr.class,
                        com.github.javaparser.ast.expr.UnaryExpr.class,
                        com.github.javaparser.ast.expr.VariableDeclarationExpr.class,
                        com.github.javaparser.ast.modules.ModuleDeclaration.class,
                        com.github.javaparser.ast.modules.ModuleDirective.class,
                        com.github.javaparser.ast.modules.ModuleExportsDirective.class,
                        com.github.javaparser.ast.modules.ModuleOpensDirective.class,
                        com.github.javaparser.ast.modules.ModuleProvidesDirective.class,
                        com.github.javaparser.ast.modules.ModuleRequiresDirective.class,
                        com.github.javaparser.ast.modules.ModuleUsesDirective.class,
                        com.github.javaparser.ast.stmt.AssertStmt.class,
                        com.github.javaparser.ast.stmt.BlockStmt.class,
                        com.github.javaparser.ast.stmt.BreakStmt.class,
                        com.github.javaparser.ast.stmt.CatchClause.class,
                        com.github.javaparser.ast.stmt.ContinueStmt.class,
                        com.github.javaparser.ast.stmt.DoStmt.class,
                        com.github.javaparser.ast.stmt.EmptyStmt.class,
                        com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt.class,
                        com.github.javaparser.ast.stmt.ExpressionStmt.class,
                        com.github.javaparser.ast.stmt.ForEachStmt.class,
                        com.github.javaparser.ast.stmt.ForStmt.class,
                        com.github.javaparser.ast.stmt.IfStmt.class,
                        com.github.javaparser.ast.stmt.LabeledStmt.class,
                        com.github.javaparser.ast.stmt.LocalClassDeclarationStmt.class,
                        com.github.javaparser.ast.stmt.LocalRecordDeclarationStmt.class,
                        com.github.javaparser.ast.stmt.ReturnStmt.class,
                        com.github.javaparser.ast.stmt.Statement.class,
                        com.github.javaparser.ast.stmt.SwitchEntry.class,
                        com.github.javaparser.ast.stmt.SwitchStmt.class,
                        com.github.javaparser.ast.stmt.SynchronizedStmt.class,
                        com.github.javaparser.ast.stmt.ThrowStmt.class,
                        com.github.javaparser.ast.stmt.TryStmt.class,
                        com.github.javaparser.ast.stmt.UnparsableStmt.class,
                        com.github.javaparser.ast.stmt.WhileStmt.class,
                        com.github.javaparser.ast.stmt.YieldStmt.class,
                        com.github.javaparser.ast.type.ArrayType.class,
                        com.github.javaparser.ast.type.ClassOrInterfaceType.class,
                        com.github.javaparser.ast.type.IntersectionType.class,
                        com.github.javaparser.ast.type.PrimitiveType.class,
                        com.github.javaparser.ast.type.ReferenceType.class,
                        com.github.javaparser.ast.type.Type.class,
                        com.github.javaparser.ast.type.TypeParameter.class,
                        com.github.javaparser.ast.type.UnionType.class,
                        com.github.javaparser.ast.type.UnknownType.class,
                        com.github.javaparser.ast.type.VarType.class,
                        com.github.javaparser.ast.type.VoidType.class,
                        com.github.javaparser.ast.type.WildcardType.class
                ).map(DotName::createSimple).toList().toArray(new DotName[0])
        );
    }

それぞれが各文法に対応する感じですね。

おわりに

JavaParserのSymbolSolverを使って、メソッド呼び出しなどを解析してみました。

最初のとっかかりがちょっと???だったのですが、動かしてみるとだいたい雰囲気がわかったのでなんとかなりました。

ここからさらに深堀りするかはちょっとわかりませんが、こういうライブラリーがあることを覚えておくと意外と役に立つのではと
思ったりします。