これは、なにをしたくて書いたもの?
前に、Javaのソースコードを解析できるJavaParserというライブラリーを試してみました。
Javaのソースコードを解析できるJavaParserを試す - CLOVER🍀
JavaParserはソースコードをパースしてASTを生成するものでしたが、ここからさらにシンボル解決ができるSymbolSolverを
使ってみたいと思います。
JavaParserとSymbolSolver
SymbolSolverはJavaParserの中に含まれるというか、JavaParserを使う時の依存関係で最初に紹介されます。
GitHubリポジトリーではASTの操作までができればよいということであれば、javaparser-core(JavaParserのみ)を使えば
よいとしています。
SymbolSolverを使うことで、パース後のASTに対する解析ができるようになります。これは実際に使っているところを
見た方が早そうなので、先に進めます…。
また例によって情報はあまりなく、サンプルはSymbolSolverを使ったものになっています。
少し使ってみましょう。
環境
今回の環境はこちら。
$ 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 + b、a - 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");
BinaryExprはNodeのサブクラスで、これらを使って指定のノード(メソッド呼び出しなど)を検索できます。
次はプロジェクトのソースコード内で検索してみましょう。
@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#plus、Foo#setBar、Foo#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を使って、メソッド呼び出しなどを解析してみました。
最初のとっかかりがちょっと???だったのですが、動かしてみるとだいたい雰囲気がわかったのでなんとかなりました。
ここからさらに深堀りするかはちょっとわかりませんが、こういうライブラリーがあることを覚えておくと意外と役に立つのではと
思ったりします。