Skip to content

Commit 5868599

Browse files
authored
Fix nested type inheritance conversion (#171)
## Summary - Fixes #137 — when a Java class extends/implements a nested type (e.g. `GeneratorFactory.AbstractXmlFeatureGeneratorFactory`), the declaring type qualifier was silently dropped, producing invalid/incorrect C# (`AbstractXmlFeatureGeneratorFactory` instead of `GeneratorFactory.AbstractXmlFeatureGeneratorFactory`). - Root cause: `TypeHelper.GetSyntaxFromType` only read `ClassOrInterfaceType.getNameAsString()`, which returns just the simple name. JavaParser exposes the declaring type separately via `getScope()`, which was never consulted. - Fix: after resolving the leaf type syntax, check `getScope()` and, if present, recursively resolve it and wrap the result in a `QualifiedName`, preserving `Outer.Inner` qualification (valid in both Java and C#). ## Test plan - [x] Added `ConvertNestedTypeInheritanceTests` reproducing the exact scenario from #137 (class extending/implementing nested types keeps the `GeneratorFactory.` qualifier). - [x] Added a sanity test confirming plain (non-nested) `extends` is unaffected. - [x] Full test suite passes: `dotnet test` — 337/337 passed. Co-authored-by: Munishwar kalra <kalramunishwar.com>
1 parent 1ea0262 commit 5868599

2 files changed

Lines changed: 54 additions & 0 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
namespace JavaToCSharp.Tests;
2+
3+
public class ConvertNestedTypeInheritanceTests
4+
{
5+
[Fact]
6+
public void Extending_Nested_Type_Keeps_Declaring_Type_Qualifier()
7+
{
8+
const string javaCode = """
9+
package com.example;
10+
public class GeneratorFactory {
11+
public abstract static class AbstractXmlFeatureGeneratorFactory {
12+
}
13+
public interface XmlFeatureGeneratorFactory {
14+
}
15+
public class CachedFeatureGeneratorFactory
16+
extends GeneratorFactory.AbstractXmlFeatureGeneratorFactory
17+
implements GeneratorFactory.XmlFeatureGeneratorFactory {
18+
}
19+
}
20+
""";
21+
22+
var parsed = Convert(javaCode);
23+
24+
Assert.Contains(
25+
"public class CachedFeatureGeneratorFactory : GeneratorFactory.AbstractXmlFeatureGeneratorFactory, GeneratorFactory.XmlFeatureGeneratorFactory",
26+
parsed);
27+
}
28+
29+
[Fact]
30+
public void Extending_Simple_Type_Is_Unaffected()
31+
{
32+
const string javaCode = """
33+
package com.example;
34+
public class Square extends Shape {
35+
}
36+
""";
37+
38+
var parsed = Convert(javaCode);
39+
40+
Assert.Contains("public class Square : Shape", parsed);
41+
}
42+
43+
private static string Convert(string javaCode)
44+
=> JavaToCSharpConverter.ConvertText(javaCode, new JavaConversionOptions { IncludeComments = false }) ?? "";
45+
}

‎JavaToCSharp/TypeHelper.cs‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,15 @@ public static TypeSyntax GetSyntaxFromType(ClassOrInterfaceType type)
171171
typeSyntax = SyntaxFactory.ParseTypeName(typeName);
172172
}
173173

174+
// Nested types (e.g. `Outer.Inner`) carry their declaring type as a scope, which
175+
// getNameAsString() above does not include. Prepend it so the declaring type isn't lost.
176+
if (type.getScope().FromOptional<ClassOrInterfaceType>() is { } scope
177+
&& typeSyntax is SimpleNameSyntax simpleName
178+
&& GetSyntaxFromType(scope) is NameSyntax scopeName)
179+
{
180+
return SyntaxFactory.QualifiedName(scopeName, simpleName);
181+
}
182+
174183
return typeSyntax;
175184
}
176185

0 commit comments

Comments
 (0)