From 86c029c29d878ec2ef407a54b3cf9c82e70a294e Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 11:52:31 -0500 Subject: [PATCH 01/11] [generator] `FixupMethodOverrides()` checks properties Context: https://github.com/dotnet/java-interop/pull/1313 Fixes: https://github.com/dotnet/android/issues/10509 In .NET 10 RC 1, `View.Foreground` is defined in C# as: [SupportedOSPlatform("android23.0")] public virtual Drawable? Foreground { get; set; } But `FrameLayout.Foreground` is defined as: [UnsupportedOSPlatform("android23.0")] public override Drawable? Foreground { get; set; } I think this is the exact same bug that was addressed in #1313 for methods, but we still have the issue for properties. I was able to duplicate the test and make a `getThing()` and `setThing()` methods in Java to see the issue. I updated the `FixupMethodOverrides()` to iterate over properties and do the same fixup for property getters and setters. --- .../Unit-Tests/CodeGeneratorTests.cs | 40 +++++++++++++++++++ .../GenBase.cs | 34 ++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs index c02b7def7..ae1327c7e 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs @@ -1469,6 +1469,46 @@ public void UnsupportedOSPlatformIgnoresMethodOverrides () StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", actual, "Should contain UnsupportedOSPlatform!"); } + [Test] + public void UnsupportedOSPlatformIgnoresPropertyOverrides () + { + // Given: + // public class TextView { + // public Object getThing () { ... } + // public void setThing (Object value) { ... } + // } + // public class TextView2 : TextView { + // public Object getThing () { ... } // removed-since = 30 + // public void setThing (Object value) { ... } // removed-since = 30 + // } + // We should not write [UnsupportedOSPlatform] on TextView2.Thing property, because the base methods aren't "removed". + var xml = @$" + + + + + + + + + + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + var klass = gens.Single (g => g.Name == "TextView2"); + var actual = GetGeneratedTypeOutput (klass); + + StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", actual, "Should not contain UnsupportedOSPlatform!"); + } + [Test] public void StringPropertyOverride ([Values ("true", "false")] string final) { diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 317835581..b61f5576d 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -307,6 +307,7 @@ public virtual void FixupExplicitImplementation () public void FixupMethodOverrides (CodeGenerationOptions opt) { + // Process regular methods (non-static, non-interface default methods) foreach (var m in Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod)) { for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { var bm = bt.Methods.FirstOrDefault (mm => mm.Name == m.Name && mm.Visibility == m.Visibility && ParameterList.Equals (mm.Parameters, m.Parameters)); @@ -333,6 +334,39 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) } } + // Process property getter/setter methods for ApiRemovedSince fixup + foreach (var prop in Properties) { + if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0) { + for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { + var baseProp = bt.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Getter != null); + if (baseProp != null && baseProp.Getter.ApiRemovedSince == 0) { + if (baseProp.Getter.Visibility == prop.Getter.Visibility && + ParameterList.Equals (baseProp.Getter.Parameters, prop.Getter.Parameters) && + baseProp.Getter.RetVal.FullName == prop.Getter.RetVal.FullName) { + // If a "removed" property getter overrides a "not removed" getter, the method was + // likely moved to a base class, so don't mark it as removed. + prop.Getter.ApiRemovedSince = default; + break; + } + } + } + } + if (prop.Setter != null && prop.Setter.ApiRemovedSince > 0) { + for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { + var baseProp = bt.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Setter != null); + if (baseProp != null && baseProp.Setter.ApiRemovedSince == 0) { + if (baseProp.Setter.Visibility == prop.Setter.Visibility && + ParameterList.Equals (baseProp.Setter.Parameters, prop.Setter.Parameters)) { + // If a "removed" property setter overrides a "not removed" setter, the method was + // likely moved to a base class, so don't mark it as removed. + prop.Setter.ApiRemovedSince = default; + break; + } + } + } + } + } + // Interface default methods can be overriden. We want to process them differently. var checkDimOverrideTargets = opt.SupportDefaultInterfaceMethods ? Methods : Methods.Where (m => m.IsInterfaceDefaultMethod); From e4a4269ce3b3a0fefa94e96e86b5c625b39e1c5c Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 13:23:08 -0500 Subject: [PATCH 02/11] Iterate over base properties once --- .../GenBase.cs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index b61f5576d..325a43c44 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -336,34 +336,34 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) // Process property getter/setter methods for ApiRemovedSince fixup foreach (var prop in Properties) { - if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0) { - for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { - var baseProp = bt.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Getter != null); - if (baseProp != null && baseProp.Getter.ApiRemovedSince == 0) { - if (baseProp.Getter.Visibility == prop.Getter.Visibility && - ParameterList.Equals (baseProp.Getter.Parameters, prop.Getter.Parameters) && - baseProp.Getter.RetVal.FullName == prop.Getter.RetVal.FullName) { - // If a "removed" property getter overrides a "not removed" getter, the method was - // likely moved to a base class, so don't mark it as removed. - prop.Getter.ApiRemovedSince = default; - break; - } + for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { + var baseProp = bt.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Type == prop.Type); + if (baseProp == null) + continue; + + bool shouldBreak = false; + if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0 && baseProp.Getter != null && baseProp.Getter.ApiRemovedSince == 0) { + if (baseProp.Getter.Visibility == prop.Getter.Visibility && + ParameterList.Equals (baseProp.Getter.Parameters, prop.Getter.Parameters) && + baseProp.Getter.RetVal.FullName == prop.Getter.RetVal.FullName) { + // If a "removed" property getter overrides a "not removed" getter, the method was + // likely moved to a base class, so don't mark it as removed. + prop.Getter.ApiRemovedSince = default; + shouldBreak = true; } } - } - if (prop.Setter != null && prop.Setter.ApiRemovedSince > 0) { - for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { - var baseProp = bt.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Setter != null); - if (baseProp != null && baseProp.Setter.ApiRemovedSince == 0) { - if (baseProp.Setter.Visibility == prop.Setter.Visibility && - ParameterList.Equals (baseProp.Setter.Parameters, prop.Setter.Parameters)) { - // If a "removed" property setter overrides a "not removed" setter, the method was - // likely moved to a base class, so don't mark it as removed. - prop.Setter.ApiRemovedSince = default; - break; - } + if (prop.Setter != null && prop.Setter.ApiRemovedSince > 0 && baseProp.Setter != null && baseProp.Setter.ApiRemovedSince == 0) { + if (baseProp.Setter.Visibility == prop.Setter.Visibility && + ParameterList.Equals (baseProp.Setter.Parameters, prop.Setter.Parameters)) { + // If a "removed" property setter overrides a "not removed" setter, the method was + // likely moved to a base class, so don't mark it as removed. + prop.Setter.ApiRemovedSince = default; + shouldBreak = true; } } + + if (shouldBreak) + break; } } From 2c0a8e889f7bc6e722290ccd9444a000619e1d48 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 13:27:37 -0500 Subject: [PATCH 03/11] New interface test --- .../Unit-Tests/CodeGeneratorTests.cs | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs index ae1327c7e..a1189a5b6 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs @@ -1441,13 +1441,21 @@ public void UnsupportedOSPlatformConstFields () public void UnsupportedOSPlatformIgnoresMethodOverrides () { // Given: + // Class inheritance scenario: // public class TextView { // public Object doThing () { ... } // } // public class TextView2 : TextView { // public Object doThing () { ... } // removed-since = 30 // } - // We should not write [UnsupportedOSPlatform] on TextView2.doThing (), because the base method isn't "removed". + // Interface inheritance scenario: + // public interface IFoo { + // public Object doSomething () { ... } + // } + // public interface IBar : IFoo { + // public Object doSomething () { ... } // removed-since = 30 + // } + // We should not write [UnsupportedOSPlatform] on overriding methods, because the base methods aren't "removed". var xml = @$" @@ -1460,13 +1468,28 @@ public void UnsupportedOSPlatformIgnoresMethodOverrides () + + + + + + + + + "; var gens = ParseApiDefinition (xml); + + // Test class inheritance scenario var klass = gens.Single (g => g.Name == "TextView2"); var actual = GetGeneratedTypeOutput (klass); + StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", actual, "Should not contain UnsupportedOSPlatform on class override!"); - StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", actual, "Should contain UnsupportedOSPlatform!"); + // Test interface inheritance scenario + var iface = gens.OfType ().Single (g => g.Name == "IBar"); + var ifaceActual = GetGeneratedTypeOutput (iface); + StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", ifaceActual, "Should not contain UnsupportedOSPlatform on interface override!"); } [Test] From e96c813c2f2aaec664170156d49b82e0919c04cc Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 13:57:27 -0500 Subject: [PATCH 04/11] New property interface test --- .../Unit-Tests/CodeGeneratorTests.cs | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs index a1189a5b6..6422b856f 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs @@ -1496,6 +1496,7 @@ public void UnsupportedOSPlatformIgnoresMethodOverrides () public void UnsupportedOSPlatformIgnoresPropertyOverrides () { // Given: + // Class inheritance scenario: // public class TextView { // public Object getThing () { ... } // public void setThing (Object value) { ... } @@ -1504,7 +1505,14 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides () // public Object getThing () { ... } // removed-since = 30 // public void setThing (Object value) { ... } // removed-since = 30 // } - // We should not write [UnsupportedOSPlatform] on TextView2.Thing property, because the base methods aren't "removed". + // Interface inheritance scenario: + // public interface IPropertyProvider { + // public Object getSomething () { ... } + // } + // public interface IExtendedProvider : IPropertyProvider { + // public Object getSomething () { ... } // removed-since = 30 + // } + // We should not write [UnsupportedOSPlatform] on overriding properties, because the base methods aren't "removed". var xml = @$" @@ -1523,13 +1531,28 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides () + + + + + + + + + "; var gens = ParseApiDefinition (xml); + + // Test class inheritance scenario var klass = gens.Single (g => g.Name == "TextView2"); var actual = GetGeneratedTypeOutput (klass); + StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", actual, "Should not contain UnsupportedOSPlatform on class property override!"); - StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", actual, "Should not contain UnsupportedOSPlatform!"); + // Test interface inheritance scenario + var iface = gens.OfType ().Single (g => g.Name == "IExtendedProvider"); + var ifaceActual = GetGeneratedTypeOutput (iface); + StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.UnsupportedOSPlatformAttribute (\"android30.0\")]", ifaceActual, "Should not contain UnsupportedOSPlatform on interface property override!"); } [Test] From 4682436e94b5accf228da981e7cb79e7a30a3e1f Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 13:58:08 -0500 Subject: [PATCH 05/11] Fixes for interfaces --- .../GenBase.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 325a43c44..c46f3e0c5 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -367,6 +367,54 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) } } + // Process interface inheritance for both regular and default interface methods + if (this is InterfaceGen currentInterface) { + // For interfaces, check all base interfaces (interfaces that this interface implements/extends) + var baseInterfaces = currentInterface.GetAllDerivedInterfaces (); + + foreach (var m in Methods.Where (m => !m.IsStatic)) { + foreach (var baseIface in baseInterfaces) { + var bm = baseIface.Methods.FirstOrDefault (mm => mm.Name == m.Name && mm.Visibility == m.Visibility && ParameterList.Equals (mm.Parameters, m.Parameters)); + if (bm != null && bm.RetVal.FullName == m.RetVal.FullName) { + // If a "removed" interface method overrides a "not removed" method, the method was + // likely moved to a base interface, so don't mark it as removed. + if (m.ApiRemovedSince > 0 && bm.ApiRemovedSince == 0) + m.ApiRemovedSince = default; + break; + } + } + } + + // Process interface property getter/setter methods for ApiRemovedSince fixup + foreach (var prop in Properties) { + foreach (var baseIface in baseInterfaces) { + var baseProp = baseIface.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Type == prop.Type); + if (baseProp == null) + continue; + + bool shouldBreak = false; + if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0 && baseProp.Getter != null && baseProp.Getter.ApiRemovedSince == 0) { + if (baseProp.Getter.Visibility == prop.Getter.Visibility && + ParameterList.Equals (baseProp.Getter.Parameters, prop.Getter.Parameters) && + baseProp.Getter.RetVal.FullName == prop.Getter.RetVal.FullName) { + prop.Getter.ApiRemovedSince = default; + shouldBreak = true; + } + } + if (prop.Setter != null && prop.Setter.ApiRemovedSince > 0 && baseProp.Setter != null && baseProp.Setter.ApiRemovedSince == 0) { + if (baseProp.Setter.Visibility == prop.Setter.Visibility && + ParameterList.Equals (baseProp.Setter.Parameters, prop.Setter.Parameters)) { + prop.Setter.ApiRemovedSince = default; + shouldBreak = true; + } + } + + if (shouldBreak) + break; + } + } + } + // Interface default methods can be overriden. We want to process them differently. var checkDimOverrideTargets = opt.SupportDefaultInterfaceMethods ? Methods : Methods.Where (m => m.IsInterfaceDefaultMethod); From 130429b25fddd54cc1cef00428ff15c9f7897ff8 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 16:21:11 -0500 Subject: [PATCH 06/11] `public static final String DATE_TAKEN = "datetaken"` --- .../generator-Tests/Unit-Tests/CodeGeneratorTests.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs index 6422b856f..271647ec9 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs @@ -1451,11 +1451,13 @@ public void UnsupportedOSPlatformIgnoresMethodOverrides () // Interface inheritance scenario: // public interface IFoo { // public Object doSomething () { ... } + // public static final String DATE_TAKEN = "datetaken"; // } // public interface IBar : IFoo { // public Object doSomething () { ... } // removed-since = 30 + // public static final String DATE_TAKEN = "datetaken"; // removed-since = 29 // } - // We should not write [UnsupportedOSPlatform] on overriding methods, because the base methods aren't "removed". + // We should not write [UnsupportedOSPlatform] on overriding methods or fields, because the base methods/fields aren't "removed". var xml = @$" @@ -1471,10 +1473,12 @@ public void UnsupportedOSPlatformIgnoresMethodOverrides () + + "; @@ -1508,11 +1512,13 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides () // Interface inheritance scenario: // public interface IPropertyProvider { // public Object getSomething () { ... } + // public static final String DATE_TAKEN = "datetaken"; // } // public interface IExtendedProvider : IPropertyProvider { // public Object getSomething () { ... } // removed-since = 30 + // public static final String DATE_TAKEN = "datetaken"; // removed-since = 29 // } - // We should not write [UnsupportedOSPlatform] on overriding properties, because the base methods aren't "removed". + // We should not write [UnsupportedOSPlatform] on overriding properties or fields, because the base methods/fields aren't "removed". var xml = @$" @@ -1534,10 +1540,12 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides () + + "; From bdce347b539cc2b07e4a1da8d274592c8b88d367 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 16:32:42 -0500 Subject: [PATCH 07/11] `removed-since = 30` --- tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs index 271647ec9..bc7adf68e 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs @@ -1455,7 +1455,7 @@ public void UnsupportedOSPlatformIgnoresMethodOverrides () // } // public interface IBar : IFoo { // public Object doSomething () { ... } // removed-since = 30 - // public static final String DATE_TAKEN = "datetaken"; // removed-since = 29 + // public static final String DATE_TAKEN = "datetaken"; // removed-since = 30 // } // We should not write [UnsupportedOSPlatform] on overriding methods or fields, because the base methods/fields aren't "removed". var xml = @$" @@ -1478,7 +1478,7 @@ public void UnsupportedOSPlatformIgnoresMethodOverrides () - + "; @@ -1516,7 +1516,7 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides () // } // public interface IExtendedProvider : IPropertyProvider { // public Object getSomething () { ... } // removed-since = 30 - // public static final String DATE_TAKEN = "datetaken"; // removed-since = 29 + // public static final String DATE_TAKEN = "datetaken"; // removed-since = 30 // } // We should not write [UnsupportedOSPlatform] on overriding properties or fields, because the base methods/fields aren't "removed". var xml = @$" @@ -1545,7 +1545,7 @@ public void UnsupportedOSPlatformIgnoresPropertyOverrides () - + "; From 9778ba2876283ad51638d5de97181fbf130dd18a Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 16:40:28 -0500 Subject: [PATCH 08/11] Fields! --- .../GenBase.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index c46f3e0c5..a7fb7f8f7 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -413,6 +413,21 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) break; } } + + // Process interface field inheritance for ApiRemovedSince fixup + foreach (var field in Fields) { + foreach (var baseIface in baseInterfaces) { + var baseField = baseIface.Fields.FirstOrDefault (f => f.Name == field.Name && f.TypeName == field.TypeName); + if (baseField != null) { + // If a "removed" interface field overrides a "not removed" field, the field was + // likely moved to a base interface, so don't mark it as removed. + if (field.ApiRemovedSince > 0 && baseField.ApiRemovedSince == 0) { + field.ApiRemovedSince = default; + break; + } + } + } + } } // Interface default methods can be overriden. We want to process them differently. From 77b5bfa2c75d9f266ba30aa58219c872953ae9df Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 22 Sep 2025 16:45:01 -0500 Subject: [PATCH 09/11] Check Visibility on fields --- .../Java.Interop.Tools.Generator.ObjectModel/GenBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index a7fb7f8f7..b9f621fe2 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -417,7 +417,7 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) // Process interface field inheritance for ApiRemovedSince fixup foreach (var field in Fields) { foreach (var baseIface in baseInterfaces) { - var baseField = baseIface.Fields.FirstOrDefault (f => f.Name == field.Name && f.TypeName == field.TypeName); + var baseField = baseIface.Fields.FirstOrDefault (f => f.Name == field.Name && f.TypeName == field.TypeName && f.Visibility == field.Visibility); if (baseField != null) { // If a "removed" interface field overrides a "not removed" field, the field was // likely moved to a base interface, so don't mark it as removed. From 448b00ac357af36e3e78a48bac15c230eb75535a Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 23 Sep 2025 09:32:29 -0500 Subject: [PATCH 10/11] Formatting --- .../GenBase.cs | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index b9f621fe2..3b65f3ea9 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -338,8 +338,9 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) foreach (var prop in Properties) { for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { var baseProp = bt.Properties.FirstOrDefault (p => p.Name == prop.Name && p.Type == prop.Type); - if (baseProp == null) + if (baseProp == null) { continue; + } bool shouldBreak = false; if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0 && baseProp.Getter != null && baseProp.Getter.ApiRemovedSince == 0) { @@ -361,9 +362,9 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) shouldBreak = true; } } - - if (shouldBreak) + if (shouldBreak) { break; + } } } @@ -374,12 +375,18 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) foreach (var m in Methods.Where (m => !m.IsStatic)) { foreach (var baseIface in baseInterfaces) { - var bm = baseIface.Methods.FirstOrDefault (mm => mm.Name == m.Name && mm.Visibility == m.Visibility && ParameterList.Equals (mm.Parameters, m.Parameters)); - if (bm != null && bm.RetVal.FullName == m.RetVal.FullName) { - // If a "removed" interface method overrides a "not removed" method, the method was - // likely moved to a base interface, so don't mark it as removed. - if (m.ApiRemovedSince > 0 && bm.ApiRemovedSince == 0) - m.ApiRemovedSince = default; + var bm = baseIface.Methods.FirstOrDefault (mm => + mm.Name == m.Name && + mm.Visibility == m.Visibility && + mm.RetVal.FullName == m.RetVal.FullName && + ParameterList.Equals (mm.Parameters, m.Parameters)); + if (bm == null) { + continue; + } + // If a "removed" interface method overrides a "not removed" method, the method was + // likely moved to a base interface, so don't mark it as removed. + if (m.ApiRemovedSince > 0 && bm.ApiRemovedSince == 0) { + m.ApiRemovedSince = default; break; } } @@ -408,9 +415,9 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) shouldBreak = true; } } - - if (shouldBreak) + if (shouldBreak) { break; + } } } @@ -418,13 +425,14 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) foreach (var field in Fields) { foreach (var baseIface in baseInterfaces) { var baseField = baseIface.Fields.FirstOrDefault (f => f.Name == field.Name && f.TypeName == field.TypeName && f.Visibility == field.Visibility); - if (baseField != null) { - // If a "removed" interface field overrides a "not removed" field, the field was - // likely moved to a base interface, so don't mark it as removed. - if (field.ApiRemovedSince > 0 && baseField.ApiRemovedSince == 0) { - field.ApiRemovedSince = default; - break; - } + if (baseField == null) { + continue; + } + // If a "removed" interface field overrides a "not removed" field, the field was + // likely moved to a base interface, so don't mark it as removed. + if (field.ApiRemovedSince > 0 && baseField.ApiRemovedSince == 0) { + field.ApiRemovedSince = default; + break; } } } From 1138738857e5d6cd330fe3634f62a6a1211d8f92 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 23 Sep 2025 09:39:04 -0500 Subject: [PATCH 11/11] Formatting existing code --- .../GenBase.cs | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs index 3b65f3ea9..4f0ca0b8e 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs @@ -310,27 +310,32 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) // Process regular methods (non-static, non-interface default methods) foreach (var m in Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod)) { for (var bt = GetBaseGen (opt); bt != null; bt = bt.GetBaseGen (opt)) { - var bm = bt.Methods.FirstOrDefault (mm => mm.Name == m.Name && mm.Visibility == m.Visibility && ParameterList.Equals (mm.Parameters, m.Parameters)); - if (bm != null && bm.RetVal.FullName == m.RetVal.FullName) { // if return type is different, it could be still "new", not "override". - m.IsOverride = true; - - if (opt.FixObsoleteOverrides) { - // If method overrides a deprecated method, it also needs to be marked as deprecated - if (bm.Deprecated.HasValue () && !m.Deprecated.HasValue ()) - m.Deprecated = bm.Deprecated; - - // Fix issue when base method was deprecated before the overriding method, set both both to base method value - if (bm.DeprecatedSince.GetValueOrDefault (default) < m.DeprecatedSince.GetValueOrDefault (default)) - m.DeprecatedSince = bm.DeprecatedSince; - } + var bm = bt.Methods.FirstOrDefault (mm => + mm.Name == m.Name && + mm.Visibility == m.Visibility && + mm.RetVal.FullName == m.RetVal.FullName && // if return type is different, it could be still "new", not "override". + ParameterList.Equals (mm.Parameters, m.Parameters)); + if (bm == null) { + continue; + } - // If a "removed" method overrides a "not removed" method, the method was - // likely moved to a base class, so don't mark it as removed. - if (m.ApiRemovedSince > 0 && bm.ApiRemovedSince == 0) - m.ApiRemovedSince = default; + m.IsOverride = true; + if (opt.FixObsoleteOverrides) { + // If method overrides a deprecated method, it also needs to be marked as deprecated + if (bm.Deprecated.HasValue () && !m.Deprecated.HasValue ()) + m.Deprecated = bm.Deprecated; + + // Fix issue when base method was deprecated before the overriding method, set both both to base method value + if (bm.DeprecatedSince.GetValueOrDefault (default) < m.DeprecatedSince.GetValueOrDefault (default)) + m.DeprecatedSince = bm.DeprecatedSince; + } - break; + // If a "removed" method overrides a "not removed" method, the method was + // likely moved to a base class, so don't mark it as removed. + if (m.ApiRemovedSince > 0 && bm.ApiRemovedSince == 0) { + m.ApiRemovedSince = default; } + break; } } @@ -344,7 +349,7 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) bool shouldBreak = false; if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0 && baseProp.Getter != null && baseProp.Getter.ApiRemovedSince == 0) { - if (baseProp.Getter.Visibility == prop.Getter.Visibility && + if (baseProp.Getter.Visibility == prop.Getter.Visibility && ParameterList.Equals (baseProp.Getter.Parameters, prop.Getter.Parameters) && baseProp.Getter.RetVal.FullName == prop.Getter.RetVal.FullName) { // If a "removed" property getter overrides a "not removed" getter, the method was @@ -354,7 +359,7 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) } } if (prop.Setter != null && prop.Setter.ApiRemovedSince > 0 && baseProp.Setter != null && baseProp.Setter.ApiRemovedSince == 0) { - if (baseProp.Setter.Visibility == prop.Setter.Visibility && + if (baseProp.Setter.Visibility == prop.Setter.Visibility && ParameterList.Equals (baseProp.Setter.Parameters, prop.Setter.Parameters)) { // If a "removed" property setter overrides a "not removed" setter, the method was // likely moved to a base class, so don't mark it as removed. @@ -387,8 +392,8 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) // likely moved to a base interface, so don't mark it as removed. if (m.ApiRemovedSince > 0 && bm.ApiRemovedSince == 0) { m.ApiRemovedSince = default; - break; } + break; } } @@ -401,7 +406,7 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) bool shouldBreak = false; if (prop.Getter != null && prop.Getter.ApiRemovedSince > 0 && baseProp.Getter != null && baseProp.Getter.ApiRemovedSince == 0) { - if (baseProp.Getter.Visibility == prop.Getter.Visibility && + if (baseProp.Getter.Visibility == prop.Getter.Visibility && ParameterList.Equals (baseProp.Getter.Parameters, prop.Getter.Parameters) && baseProp.Getter.RetVal.FullName == prop.Getter.RetVal.FullName) { prop.Getter.ApiRemovedSince = default; @@ -409,7 +414,7 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) } } if (prop.Setter != null && prop.Setter.ApiRemovedSince > 0 && baseProp.Setter != null && baseProp.Setter.ApiRemovedSince == 0) { - if (baseProp.Setter.Visibility == prop.Setter.Visibility && + if (baseProp.Setter.Visibility == prop.Setter.Visibility && ParameterList.Equals (baseProp.Setter.Parameters, prop.Setter.Parameters)) { prop.Setter.ApiRemovedSince = default; shouldBreak = true; @@ -432,8 +437,8 @@ public void FixupMethodOverrides (CodeGenerationOptions opt) // likely moved to a base interface, so don't mark it as removed. if (field.ApiRemovedSince > 0 && baseField.ApiRemovedSince == 0) { field.ApiRemovedSince = default; - break; } + break; } } }