From aae6087f90bd847af1c909b6d64aee803c2602c5 Mon Sep 17 00:00:00 2001 From: Dave Friedel Date: Wed, 23 Jul 2025 06:10:17 -0400 Subject: [PATCH] Hot Fix: nestedclasses resolved empty nestedclasses --- IronJava.Core/AST/Builders/AstBuilder.cs | 163 ++++++++++++++++++++--- IronJava.Core/IronJava.Core.csproj | 2 +- TestNestedTypes.cs | 58 ++++++++ samples/IronJava.Sample/Program.cs | 77 +++++++++++ 4 files changed, 284 insertions(+), 16 deletions(-) create mode 100644 TestNestedTypes.cs diff --git a/IronJava.Core/AST/Builders/AstBuilder.cs b/IronJava.Core/AST/Builders/AstBuilder.cs index 45b79b1..64030bd 100644 --- a/IronJava.Core/AST/Builders/AstBuilder.cs +++ b/IronJava.Core/AST/Builders/AstBuilder.cs @@ -196,12 +196,12 @@ namespace MarketAlly.IronJava.Core.AST.Builders var typeParameters = BuildTypeParameters(context.typeParameters()); var superClass = context.superclass() != null ? BuildTypeReference(context.superclass().classType()) : null; var interfaces = BuildInterfaces(context.superinterfaces()); - var members = BuildClassMembers(context.classBody()); + var bodyResult = BuildClassBody(context.classBody()); var javaDoc = ExtractJavaDoc(context); return new ClassDeclaration( location, name, modifiers, annotations, typeParameters, - superClass, interfaces, members, new List(), javaDoc, false + superClass, interfaces, bodyResult.Members, bodyResult.NestedTypes, javaDoc, false ); } @@ -213,12 +213,12 @@ namespace MarketAlly.IronJava.Core.AST.Builders var name = context.identifier().GetText(); var typeParameters = BuildTypeParameters(context.typeParameters()); var extendedInterfaces = BuildExtendedInterfaces(context.extendsInterfaces()); - var members = BuildInterfaceMembers(context.interfaceBody()); + var bodyResult = BuildInterfaceBody(context.interfaceBody()); var javaDoc = ExtractJavaDoc(context); return new InterfaceDeclaration( location, name, modifiers, annotations, typeParameters, - extendedInterfaces, members, new List(), javaDoc + extendedInterfaces, bodyResult.Members, bodyResult.NestedTypes, javaDoc ); } @@ -231,12 +231,15 @@ namespace MarketAlly.IronJava.Core.AST.Builders var interfaces = BuildInterfaces(context.superinterfaces()); var enumBody = context.enumBody(); var constants = BuildEnumConstants(enumBody.enumConstantList()); - var members = BuildEnumMembers(enumBody.enumBodyDeclarations()); + var bodyResult = BuildEnumBody(enumBody.enumBodyDeclarations()); var javaDoc = ExtractJavaDoc(context); return new EnumDeclaration( location, name, modifiers, annotations, - interfaces, constants, members, new List(), javaDoc + interfaces, constants, + bodyResult?.Members ?? new List(), + bodyResult?.NestedTypes ?? new List(), + javaDoc ); } @@ -249,6 +252,7 @@ namespace MarketAlly.IronJava.Core.AST.Builders var members = BuildAnnotationMembers(context.annotationTypeBody()); var javaDoc = ExtractJavaDoc(context); + // Annotations don't support nested types in Java return new AnnotationDeclaration( location, name, modifiers, annotations, members, new List(), javaDoc ); @@ -667,6 +671,54 @@ namespace MarketAlly.IronJava.Core.AST.Builders return members; } + private ClassBodyResult BuildClassBody(Java9Parser.ClassBodyContext context) + { + var result = new ClassBodyResult(); + + foreach (var declaration in context.classBodyDeclaration()) + { + if (declaration.classMemberDeclaration() != null) + { + var classMemberContext = declaration.classMemberDeclaration(); + + // Check if it's a nested type declaration + if (classMemberContext.classDeclaration() != null) + { + var nestedType = Visit(classMemberContext.classDeclaration()) as TypeDeclaration; + if (nestedType != null) result.NestedTypes.Add(nestedType); + } + else if (classMemberContext.interfaceDeclaration() != null) + { + var nestedType = Visit(classMemberContext.interfaceDeclaration()) as TypeDeclaration; + if (nestedType != null) result.NestedTypes.Add(nestedType); + } + else + { + // It's a regular member (field or method) + var member = BuildClassMember(classMemberContext); + if (member != null) result.Members.Add(member); + } + } + else if (declaration.instanceInitializer() != null) + { + var initializer = BuildInstanceInitializer(declaration.instanceInitializer()); + if (initializer != null) result.Members.Add(initializer); + } + else if (declaration.staticInitializer() != null) + { + var initializer = BuildStaticInitializer(declaration.staticInitializer()); + if (initializer != null) result.Members.Add(initializer); + } + else if (declaration.constructorDeclaration() != null) + { + var constructor = BuildConstructor(declaration.constructorDeclaration()); + if (constructor != null) result.Members.Add(constructor); + } + } + + return result; + } + private MemberDeclaration? BuildClassMember(Java9Parser.ClassMemberDeclarationContext context) { if (context.fieldDeclaration() != null) @@ -677,15 +729,8 @@ namespace MarketAlly.IronJava.Core.AST.Builders { return BuildMethodDeclaration(context.methodDeclaration()); } - else if (context.classDeclaration() != null) - { - return Visit(context.classDeclaration()) as MemberDeclaration; - } - else if (context.interfaceDeclaration() != null) - { - return Visit(context.interfaceDeclaration()) as MemberDeclaration; - } - + // Nested types are now handled in BuildClassBody + return null; } @@ -1040,6 +1085,37 @@ namespace MarketAlly.IronJava.Core.AST.Builders return members; } + private ClassBodyResult BuildInterfaceBody(Java9Parser.InterfaceBodyContext context) + { + var result = new ClassBodyResult(); + + foreach (var declaration in context.interfaceMemberDeclaration()) + { + if (declaration.constantDeclaration() != null) + { + var constant = BuildConstantDeclaration(declaration.constantDeclaration()); + if (constant != null) result.Members.Add(constant); + } + else if (declaration.interfaceMethodDeclaration() != null) + { + var method = BuildInterfaceMethodDeclaration(declaration.interfaceMethodDeclaration()); + if (method != null) result.Members.Add(method); + } + else if (declaration.classDeclaration() != null) + { + var nestedType = Visit(declaration.classDeclaration()) as TypeDeclaration; + if (nestedType != null) result.NestedTypes.Add(nestedType); + } + else if (declaration.interfaceDeclaration() != null) + { + var nestedType = Visit(declaration.interfaceDeclaration()) as TypeDeclaration; + if (nestedType != null) result.NestedTypes.Add(nestedType); + } + } + + return result; + } + private FieldDeclaration? BuildConstantDeclaration(Java9Parser.ConstantDeclarationContext context) { var location = GetSourceRange(context); @@ -1172,6 +1248,56 @@ namespace MarketAlly.IronJava.Core.AST.Builders return members; } + private ClassBodyResult? BuildEnumBody(Java9Parser.EnumBodyDeclarationsContext? context) + { + if (context == null) return null; + + var result = new ClassBodyResult(); + + foreach (var declaration in context.classBodyDeclaration()) + { + if (declaration.classMemberDeclaration() != null) + { + var classMemberContext = declaration.classMemberDeclaration(); + + // Check if it's a nested type declaration + if (classMemberContext.classDeclaration() != null) + { + var nestedType = Visit(classMemberContext.classDeclaration()) as TypeDeclaration; + if (nestedType != null) result.NestedTypes.Add(nestedType); + } + else if (classMemberContext.interfaceDeclaration() != null) + { + var nestedType = Visit(classMemberContext.interfaceDeclaration()) as TypeDeclaration; + if (nestedType != null) result.NestedTypes.Add(nestedType); + } + else + { + // It's a regular member (field or method) + var member = BuildClassMember(classMemberContext); + if (member != null) result.Members.Add(member); + } + } + else if (declaration.instanceInitializer() != null) + { + var initializer = BuildInstanceInitializer(declaration.instanceInitializer()); + if (initializer != null) result.Members.Add(initializer); + } + else if (declaration.staticInitializer() != null) + { + var initializer = BuildStaticInitializer(declaration.staticInitializer()); + if (initializer != null) result.Members.Add(initializer); + } + else if (declaration.constructorDeclaration() != null) + { + var constructor = BuildConstructor(declaration.constructorDeclaration()); + if (constructor != null) result.Members.Add(constructor); + } + } + + return result; + } + private List BuildAnnotationMembers(Java9Parser.AnnotationTypeBodyContext context) { var members = new List(); @@ -3464,5 +3590,12 @@ namespace MarketAlly.IronJava.Core.AST.Builders return new JavaDoc(range, content, tags); } + + // Helper classes for building class bodies with both members and nested types + private class ClassBodyResult + { + public List Members { get; set; } = new List(); + public List NestedTypes { get; set; } = new List(); + } } } \ No newline at end of file diff --git a/IronJava.Core/IronJava.Core.csproj b/IronJava.Core/IronJava.Core.csproj index 8a01d81..acb634d 100644 --- a/IronJava.Core/IronJava.Core.csproj +++ b/IronJava.Core/IronJava.Core.csproj @@ -8,7 +8,7 @@ IronJava - 2.1.0 + 2.1.1 David H Friedel Jr MarketAlly IronJava diff --git a/TestNestedTypes.cs b/TestNestedTypes.cs new file mode 100644 index 0000000..1963f60 --- /dev/null +++ b/TestNestedTypes.cs @@ -0,0 +1,58 @@ +using System; +using MarketAlly.IronJava.Core; +using MarketAlly.IronJava.Core.AST.Nodes; + +class TestNestedTypes +{ + static void Main() + { + var javaCode = @" + public class OuterClass { + private int outerField; + + public class InnerClass { + private String innerField; + + public void innerMethod() { + System.out.println(innerField); + } + } + + public static class StaticNestedClass { + private static int staticField; + } + + public interface NestedInterface { + void doSomething(); + } + } + "; + + var result = JavaParser.Parse(javaCode); + + if (result.Success) + { + Console.WriteLine("Parse successful!"); + var outerClass = result.Ast.Types[0] as ClassDeclaration; + if (outerClass != null) + { + Console.WriteLine($"Outer class: {outerClass.Name}"); + Console.WriteLine($"Number of members: {outerClass.Members.Count}"); + Console.WriteLine($"Number of nested types: {outerClass.NestedTypes.Count}"); + + foreach (var nestedType in outerClass.NestedTypes) + { + Console.WriteLine($" - Nested type: {nestedType.Name} ({nestedType.GetType().Name})"); + } + } + } + else + { + Console.WriteLine("Parse failed!"); + foreach (var error in result.Errors) + { + Console.WriteLine($"Error: {error}"); + } + } + } +} \ No newline at end of file diff --git a/samples/IronJava.Sample/Program.cs b/samples/IronJava.Sample/Program.cs index 4441ffb..93d6c92 100644 --- a/samples/IronJava.Sample/Program.cs +++ b/samples/IronJava.Sample/Program.cs @@ -15,6 +15,10 @@ namespace MarketAlly.IronJava.Sample Console.WriteLine("IronJava Sample Application"); Console.WriteLine("===========================\n"); + // Test nested types + TestNestedTypes(); + Console.WriteLine("\n===========================\n"); + // Sample Java code string javaCode = @" package com.example; @@ -219,6 +223,79 @@ class User { Console.WriteLine($"\nMethods that throw exceptions: {throwingMethods.Count}"); Console.WriteLine(); } + + static void TestNestedTypes() + { + Console.WriteLine("Testing Nested Types Feature"); + Console.WriteLine("----------------------------"); + + var javaCode = @" +public class OuterClass { + private int outerField; + + public class InnerClass { + private String innerField; + + public void innerMethod() { + System.out.println(innerField); + } + } + + public static class StaticNestedClass { + private static int staticField; + } + + public interface NestedInterface { + void doSomething(); + } + + public enum NestedEnum { + VALUE1, VALUE2 + } +} +"; + + var result = JavaParser.Parse(javaCode); + + if (result.Success) + { + Console.WriteLine("✓ Parse successful!"); + var outerClass = result.Ast!.Types[0] as ClassDeclaration; + if (outerClass != null) + { + Console.WriteLine($"\nOuter class: {outerClass.Name}"); + Console.WriteLine($" Members: {outerClass.Members.Count}"); + Console.WriteLine($" Nested types: {outerClass.NestedTypes.Count}"); + + foreach (var member in outerClass.Members) + { + if (member is FieldDeclaration field) + { + Console.WriteLine($" - Field: {field.Variables[0].Name}"); + } + } + + foreach (var nestedType in outerClass.NestedTypes) + { + Console.WriteLine($" - Nested: {nestedType.Name} ({nestedType.GetType().Name})"); + + if (nestedType is ClassDeclaration nestedClass) + { + Console.WriteLine($" Static: {nestedClass.Modifiers.HasFlag(Modifiers.Static)}"); + Console.WriteLine($" Members: {nestedClass.Members.Count}"); + } + else if (nestedType is EnumDeclaration nestedEnum) + { + Console.WriteLine($" Constants: {nestedEnum.Constants.Count}"); + } + } + } + } + else + { + Console.WriteLine("✗ Parse failed!"); + } + } } // Custom visitor for code analysis