3333import com.ibm.cldk.entities.*;
3434import com.ibm.cldk.utils.Log;
3535import org.apache.commons.lang3.tuple.Pair;
36+ import org.checkerframework.checker.units.qual.C;
3637
3738import java.io.IOException;
3839import java.nio.file.Path;
@@ -110,8 +111,7 @@ private static JavaCompilationUnit processCompilationUnit(CompilationUnit parseR
110111 cUnit.setTypeDeclarations(parseResult.findAll(TypeDeclaration.class).stream().filter(typeDecl -> typeDecl.getFullyQualifiedName().isPresent()).map(typeDecl -> {
111112 // get type name and initialize the type object
112113 String typeName = typeDecl.getFullyQualifiedName().get().toString();
113- com.ibm.cldk.entities.Type typeNode = new com.ibm.cldk.entities.Type();
114-
114+ com.ibm.cldk.entities.Type typeNode = new com.ibm.cldk.entities.Type();;
115115 if (typeDecl instanceof ClassOrInterfaceDeclaration) {
116116 ClassOrInterfaceDeclaration classDecl = (ClassOrInterfaceDeclaration) typeDecl;
117117
@@ -146,8 +146,26 @@ private static JavaCompilationUnit processCompilationUnit(CompilationUnit parseR
146146
147147 // Add enum constants
148148 typeNode.setEnumConstants(enumDecl.getEntries().stream().map(SymbolTable::processEnumConstantDeclaration).collect(Collectors.toList()));
149+ }
150+ else if (typeDecl instanceof RecordDeclaration) {
151+ RecordDeclaration recordDecl = (RecordDeclaration) typeDecl;
149152
150- } else {
153+ // Set that this is a record declaration
154+ typeNode.setRecordDeclaration(typeDecl.isRecordDeclaration());
155+
156+ // Add interfaces implemented by record
157+ typeNode.setImplementsList(recordDecl.getImplementedTypes().stream().map(SymbolTable::resolveType).collect(Collectors.toList()));
158+
159+ // Add record modifiers
160+ typeNode.setModifiers(recordDecl.getModifiers().stream().map(m -> m.toString().strip()).collect(Collectors.toList()));
161+
162+ // Add record annotations
163+ typeNode.setAnnotations(recordDecl.getAnnotations().stream().map(a -> a.toString().strip()).collect(Collectors.toList()));
164+
165+ // Add record components
166+ typeNode.setRecordComponents(processRecordComponents(recordDecl));
167+ }
168+ else {
151169 // TODO: handle AnnotationDeclaration, RecordDeclaration
152170 // set the common type attributes only
153171 Log.warn("Found unsupported type declaration: " + typeDecl.toString());
@@ -162,7 +180,6 @@ private static JavaCompilationUnit processCompilationUnit(CompilationUnit parseR
162180 typeNode.setClassOrInterfaceDeclaration(typeDecl.isClassOrInterfaceDeclaration());
163181 typeNode.setEnumDeclaration(typeDecl.isEnumDeclaration());
164182 typeNode.setAnnotationDeclaration(typeDecl.isAnnotationDeclaration());
165- typeNode.setRecordDeclaration(typeDecl.isRecordDeclaration());
166183
167184 // Add class comment
168185 typeNode.setComment(typeDecl.getComment().isPresent() ? typeDecl.getComment().get().asString() : "");
@@ -196,6 +213,40 @@ private static JavaCompilationUnit processCompilationUnit(CompilationUnit parseR
196213 return cUnit;
197214 }
198215
216+
217+ private static List<RecordComponent> processRecordComponents(RecordDeclaration recordDecl) {
218+ return recordDecl.getParameters().stream().map(
219+ parameter -> {
220+ RecordComponent recordComponent = new RecordComponent();
221+ recordComponent.setName(parameter.getNameAsString());
222+ recordComponent.setType(resolveType(parameter.getType()));
223+ recordComponent.setAnnotations(parameter.getAnnotations().stream().map(a -> a.toString().strip()).collect(Collectors.toList()));
224+ recordComponent.setModifiers(parameter.getModifiers().stream().map(a -> a.toString().strip()).collect(Collectors.toList()));
225+ recordComponent.setVarArgs(parameter.isVarArgs());
226+ recordComponent.setDefaultValue(mapRecordConstructorDefaults(recordDecl).getOrDefault(parameter.getNameAsString(), null));
227+ return recordComponent;
228+ }
229+ ).collect(Collectors.toList());
230+ }
231+
232+ private static Map<String, Object> mapRecordConstructorDefaults(RecordDeclaration recordDecl) {
233+
234+ return recordDecl.getCompactConstructors().stream()
235+ .flatMap(constructor -> constructor.findAll(AssignExpr.class).stream()) // Flatten all assignments
236+ .filter(assignExpr -> assignExpr.getTarget().isNameExpr()) // Ensure assignment is to a parameter
237+ .collect(Collectors.toMap(
238+ assignExpr -> assignExpr.getTarget().asNameExpr().getNameAsString(), // Key: Parameter Name
239+ assignExpr -> Optional.ofNullable(assignExpr.getValue()).map(valueExpr -> { // Value: Default Value
240+ return valueExpr.isStringLiteralExpr() ? valueExpr.asStringLiteralExpr().asString()
241+ : valueExpr.isBooleanLiteralExpr() ? valueExpr.asBooleanLiteralExpr().getValue()
242+ : valueExpr.isCharLiteralExpr() ? valueExpr.asCharLiteralExpr().getValue()
243+ : valueExpr.isDoubleLiteralExpr() ? valueExpr.asDoubleLiteralExpr().asDouble()
244+ : valueExpr.isIntegerLiteralExpr() ? valueExpr.asIntegerLiteralExpr().asNumber()
245+ : valueExpr.isLongLiteralExpr() ? valueExpr.asLongLiteralExpr().asNumber()
246+ : valueExpr.isNullLiteralExpr() ? null
247+ : valueExpr.toString();}).orElse("null"))); // Default: store as a string
248+ }
249+
199250 private static boolean isEntryPointClass(TypeDeclaration typeDecl) {
200251 return isSpringEntrypointClass(typeDecl) || isStrutsEntryPointClass(typeDecl) || isCamelEntryPointClass(typeDecl) || isJaxRSEntrypointClass(typeDecl) || isJakartaServletEntryPointClass(typeDecl);
201252
@@ -904,7 +955,7 @@ private static String resolveType(Type type) {
904955 public static Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>> extractAll(Path projectRootPath) throws IOException {
905956 SymbolSolverCollectionStrategy symbolSolverCollectionStrategy = new SymbolSolverCollectionStrategy();
906957 ProjectRoot projectRoot = symbolSolverCollectionStrategy.collect(projectRootPath);
907- javaSymbolSolver = (JavaSymbolSolver) symbolSolverCollectionStrategy.getParserConfiguration().getSymbolResolver().get();
958+ javaSymbolSolver = (JavaSymbolSolver) symbolSolverCollectionStrategy.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_21). getSymbolResolver().get();
908959 Map<String, JavaCompilationUnit> symbolTable = new LinkedHashMap<>();
909960 Map<String, List<Problem>> parseProblems = new HashMap<>();
910961 for (SourceRoot sourceRoot : projectRoot.getSourceRoots()) {
@@ -927,7 +978,7 @@ public static Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>>
927978 CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
928979 combinedTypeSolver.add(new ReflectionTypeSolver());
929980
930- ParserConfiguration parserConfiguration = new ParserConfiguration();
981+ ParserConfiguration parserConfiguration = new ParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_21) ;
931982 parserConfiguration.setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
932983
933984 JavaParser javaParser = new JavaParser(parserConfiguration);
@@ -958,7 +1009,8 @@ public static Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>>
9581009 SymbolSolverCollectionStrategy symbolSolverCollectionStrategy = new SymbolSolverCollectionStrategy();
9591010 ProjectRoot projectRoot = symbolSolverCollectionStrategy.collect(projectRootPath);
9601011 javaSymbolSolver = (JavaSymbolSolver) symbolSolverCollectionStrategy.getParserConfiguration().getSymbolResolver().get();
961- ParserConfiguration parserConfiguration = new ParserConfiguration();
1012+ Log.info("Setting parser language level to JAVA_21");
1013+ ParserConfiguration parserConfiguration = new ParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_21);
9621014 parserConfiguration.setSymbolResolver(javaSymbolSolver);
9631015
9641016 // create java parser with the configuration
@@ -972,6 +1024,7 @@ public static Pair<Map<String, JavaCompilationUnit>, Map<String, List<Problem>>>
9721024 ParseResult<CompilationUnit> parseResult = javaParser.parse(javaFilePath);
9731025 if (parseResult.isSuccessful()) {
9741026 CompilationUnit compilationUnit = parseResult.getResult().get();
1027+ System.out.println("Successfully parsed file: " + javaFilePath.toString());
9751028 symbolTable.put(compilationUnit.getStorage().get().getPath().toString(), processCompilationUnit(compilationUnit));
9761029 } else {
9771030 Log.error(parseResult.getProblems().toString());
0 commit comments