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