diff --git a/src/AST/ClassExtensions.cs b/src/AST/ClassExtensions.cs index 25e30299..39431c00 100644 --- a/src/AST/ClassExtensions.cs +++ b/src/AST/ClassExtensions.cs @@ -80,7 +80,7 @@ namespace CppSharp.AST if (getTopmost) { - baseMethod = (@base.Class.GetBaseMethod(@override, onlyPrimaryBase)); + baseMethod = (@base.Class.GetBaseMethod(@override, onlyPrimaryBase, true)); if (baseMethod != null) return baseMethod; } @@ -88,20 +88,37 @@ namespace CppSharp.AST return null; } - public static Property GetRootBaseProperty(this Class c, Property @override, bool onlyFirstBase = false) + public static Property GetBaseProperty(this Class c, Property @override, bool onlyFirstBase = false, bool getTopmost = false) { - return (from @base in c.Bases - where @base.IsClass && @base.Class.OriginalClass != c && (!onlyFirstBase || !@base.Class.IsInterface) - let baseProperty = ( - from property in @base.Class.Properties + foreach (var @base in c.Bases) + { + if (!@base.IsClass || @base.Class.OriginalClass == c || (onlyFirstBase && @base.Class.IsInterface)) + continue; + + Property baseProperty; + if (!getTopmost) + { + baseProperty = @base.Class.GetBaseProperty(@override, onlyFirstBase); + if (baseProperty != null) + return baseProperty; + } + + baseProperty = (from property in @base.Class.Properties where property.OriginalName == @override.OriginalName && - property.Parameters.SequenceEqual(@override.Parameters, - new ParameterTypeComparer()) - select property).FirstOrDefault() - let rootBaseProperty = @base.Class.GetRootBaseProperty(@override, onlyFirstBase) ?? baseProperty - where rootBaseProperty != null || onlyFirstBase - select rootBaseProperty).FirstOrDefault(); + property.Parameters.SequenceEqual(@override.Parameters, new ParameterTypeComparer()) + select property).FirstOrDefault(); + if (baseProperty != null) + return baseProperty; + + if (getTopmost) + { + baseProperty = @base.Class.GetBaseProperty(@override, onlyFirstBase, true); + if (baseProperty != null) + return baseProperty; + } + } + return null; } public static Property GetPropertyByName(this Class c, string propertyName) diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index f9625a0e..4a9e71a6 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1211,7 +1211,7 @@ namespace CppSharp.Generators.CSharp // check if overriding a property from a secondary base Property rootBaseProperty; var isOverride = prop.IsOverride && - (rootBaseProperty = @class.GetRootBaseProperty(prop, true)) != null && + (rootBaseProperty = @class.GetBaseProperty(prop, true)) != null && (rootBaseProperty.IsVirtual || rootBaseProperty.IsPure); if (isOverride) @@ -2317,7 +2317,7 @@ namespace CppSharp.Generators.CSharp return AccessSpecifier.Public; default: return property.IsOverride ? - ((Class) property.Namespace).GetRootBaseProperty(property).Access : property.Access; + ((Class) property.Namespace).GetBaseProperty(property).Access : property.Access; } } diff --git a/src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs b/src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs index 5da811ef..12302140 100644 --- a/src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs +++ b/src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs @@ -84,7 +84,7 @@ namespace CppSharp.Passes goto next; } } - Property baseProperty = type.GetRootBaseProperty(new Property { Name = afterSet }); + Property baseProperty = type.GetBaseProperty(new Property { Name = afterSet }, getTopmost: true); if (!type.IsInterface && baseProperty != null && baseProperty.IsVirtual && setter.IsVirtual) { bool isReadOnly = baseProperty.SetMethod == null; @@ -98,7 +98,7 @@ namespace CppSharp.Passes { Class type = (Class) nonSetter.Namespace; string name = GetPropertyName(nonSetter.Name); - Property baseProperty = type.GetRootBaseProperty(new Property { Name = name }); + Property baseProperty = type.GetBaseProperty(new Property { Name = name }, getTopmost: true); if (!type.IsInterface && baseProperty != null && baseProperty.IsVirtual) { bool isReadOnly = baseProperty.SetMethod == null; @@ -151,7 +151,7 @@ namespace CppSharp.Passes }; if (getter.IsOverride || (setter != null && setter.IsOverride)) { - var baseVirtualProperty = type.GetRootBaseProperty(property); + var baseVirtualProperty = type.GetBaseProperty(property, getTopmost: true); if (baseVirtualProperty.SetMethod == null) setter = null; } diff --git a/src/Generator/Passes/MultipleInheritancePass.cs b/src/Generator/Passes/MultipleInheritancePass.cs index 01d87704..f1c3daa2 100644 --- a/src/Generator/Passes/MultipleInheritancePass.cs +++ b/src/Generator/Passes/MultipleInheritancePass.cs @@ -214,7 +214,7 @@ namespace CppSharp.Passes foreach (var property in @interface.Properties.Where(p => p.Name != Helpers.InstanceIdentifier)) { var impl = new Property(property) { Namespace = @class }; - var rootBaseProperty = @class.GetRootBaseProperty(property, true); + var rootBaseProperty = @class.GetBaseProperty(property, true); if (rootBaseProperty != null && rootBaseProperty.IsDeclared) impl.ExplicitInterfaceImpl = @interface; @class.Properties.Add(impl); diff --git a/src/Generator/Passes/RenamePass.cs b/src/Generator/Passes/RenamePass.cs index 9901d539..9464d5e7 100644 --- a/src/Generator/Passes/RenamePass.cs +++ b/src/Generator/Passes/RenamePass.cs @@ -57,7 +57,7 @@ namespace CppSharp.Passes var property = decl as Property; if (property != null && !property.IsStatic) { - var rootBaseProperty = ((Class) property.Namespace).GetRootBaseProperty(property); + var rootBaseProperty = ((Class) property.Namespace).GetBaseProperty(property); if (rootBaseProperty != null && rootBaseProperty != property) { newName = rootBaseProperty.Name; diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index 4beaabc5..df22ce30 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -461,4 +461,13 @@ public class CSharpTests : GeneratorTestFixture testHashes[testComparison2] = 2; Assert.That(testHashes[testComparison1], Is.EqualTo(2)); } + + [Test] + public void TestOverriddenPropertyFromIndirectBase() + { + using (var overridePropertyFromIndirectPrimaryBase = new OverridePropertyFromIndirectPrimaryBase()) + { + Assert.That(overridePropertyFromIndirectPrimaryBase.Property, Is.EqualTo(5)); + } + } } diff --git a/tests/CSharp/CSharp.cpp b/tests/CSharp/CSharp.cpp index 52326678..a65771b7 100644 --- a/tests/CSharp/CSharp.cpp +++ b/tests/CSharp/CSharp.cpp @@ -812,3 +812,24 @@ bool TestComparison::operator ==(const TestComparison& other) const { return A == other.A && B == other.B; } + +OverridePropertyFromIndirectPrimaryBaseBase::OverridePropertyFromIndirectPrimaryBaseBase() +{ +} + +OverridePropertyFromDirectPrimaryBase::OverridePropertyFromDirectPrimaryBase() +{ +} + +void OverridePropertyFromDirectPrimaryBase::setProperty(int value) +{ +} + +OverridePropertyFromIndirectPrimaryBase::OverridePropertyFromIndirectPrimaryBase() +{ +} + +int OverridePropertyFromIndirectPrimaryBase::property() +{ + return 5; +} diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index 51c00768..9ba1fea0 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -698,7 +698,7 @@ public: OverrideFromDirectSecondaryBase(); }; -class OverrideFromIndirectSecondaryBase : public OverrideFromDirectSecondaryBase +class DLL_API OverrideFromIndirectSecondaryBase : public OverrideFromDirectSecondaryBase { public: OverrideFromIndirectSecondaryBase(); @@ -742,3 +742,25 @@ public: float B; bool operator ==(const TestComparison& other) const; }; + +class DLL_API OverridePropertyFromIndirectPrimaryBaseBase +{ +public: + OverridePropertyFromIndirectPrimaryBaseBase(); + virtual int property() = 0; + virtual void setProperty(int value) = 0; +}; + +class DLL_API OverridePropertyFromDirectPrimaryBase : public OverridePropertyFromIndirectPrimaryBaseBase +{ +public: + OverridePropertyFromDirectPrimaryBase(); + void setProperty(int value); +}; + +class DLL_API OverridePropertyFromIndirectPrimaryBase : public OverridePropertyFromDirectPrimaryBase +{ +public: + OverridePropertyFromIndirectPrimaryBase(); + int property(); +};