Browse Source

Completed the parallel hierarchy of interfaces so that a derived class can access the members of all of its bases.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/68/head
Dimitar Dobrev 12 years ago
parent
commit
c9e5c0d505
  1. 10
      src/AST/Class.cs
  2. 21
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  3. 62
      src/Generator/Passes/MultipleInheritancePass.cs
  4. 5
      tests/CSharpTemp/CSharpTemp.cpp
  5. 8
      tests/CSharpTemp/CSharpTemp.h

10
src/AST/Class.cs

@ -203,9 +203,10 @@ namespace CppSharp.AST
} }
} }
public Method GetRootBaseMethod(Method @override) public Method GetRootBaseMethod(Method @override, bool onlyFirstBase = false)
{ {
return (from @base in Bases return (from @base in Bases
where !@base.Class.IsInterface
let baseMethod = ( let baseMethod = (
from method in @base.Class.Methods from method in @base.Class.Methods
where where
@ -216,13 +217,14 @@ namespace CppSharp.AST
new ParameterTypeComparer()) new ParameterTypeComparer())
select method).FirstOrDefault() select method).FirstOrDefault()
let rootBaseMethod = @base.Class.GetRootBaseMethod(@override) ?? baseMethod let rootBaseMethod = @base.Class.GetRootBaseMethod(@override) ?? baseMethod
where rootBaseMethod != null where rootBaseMethod != null || onlyFirstBase
select rootBaseMethod).FirstOrDefault(); select rootBaseMethod).FirstOrDefault();
} }
public Property GetRootBaseProperty(Property @override) public Property GetRootBaseProperty(Property @override, bool onlyFirstBase = false)
{ {
return (from @base in Bases return (from @base in Bases
where !@base.Class.IsInterface
let baseProperty = ( let baseProperty = (
from property in @base.Class.Properties from property in @base.Class.Properties
where where
@ -232,7 +234,7 @@ namespace CppSharp.AST
new ParameterTypeComparer()) new ParameterTypeComparer())
select property).FirstOrDefault() select property).FirstOrDefault()
let rootBaseProperty = @base.Class.GetRootBaseProperty(@override) ?? baseProperty let rootBaseProperty = @base.Class.GetRootBaseProperty(@override) ?? baseProperty
where rootBaseProperty != null where rootBaseProperty != null || onlyFirstBase
select rootBaseProperty).FirstOrDefault(); select rootBaseProperty).FirstOrDefault();
} }

21
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -375,21 +375,12 @@ namespace CppSharp.Generators.CSharp
Write("interface "); Write("interface ");
Write("{0}", SafeIdentifier(@class.Name)); Write("{0}", SafeIdentifier(@class.Name));
//var needsBase = @class.HasBaseClass && !@class.IsValueType if (@class.HasBase)
// && !@class.Bases[0].Class.IsValueType {
// && !@class.Bases[0].Class.Ignore; Write(" : {0}", string.Join(", ",
from @base in @class.Bases
//if (needsBase || @class.IsRefType) select QualifiedIdentifier(@base.Class)));
// Write(" : "); }
//if (needsBase)
//{
// var qualifiedBase = QualifiedIdentifier(@class.Bases[0].Class);
// Write("{0}", qualifiedBase);
// if (@class.IsRefType)
// Write(", ");
//}
NewLine(); NewLine();
WriteStartBraceIndent(); WriteStartBraceIndent();

62
src/Generator/Passes/MultipleInheritancePass.cs

@ -27,19 +27,25 @@ namespace CppSharp.Passes
var @base = @class.Bases[i].Class; var @base = @class.Bases[i].Class;
if (@base.IsInterface) continue; if (@base.IsInterface) continue;
var @interface = GetInterface(@class, @base, true);
@class.Bases[i] = new BaseClassSpecifier { Type = new TagType(@interface) };
}
return base.VisitClassDecl(@class);
}
private Class GetInterface(Class @class, Class @base, bool addMembers = false)
{
if (@base.CompleteDeclaration != null) if (@base.CompleteDeclaration != null)
@base = (Class) @base.CompleteDeclaration; @base = (Class) @base.CompleteDeclaration;
var name = "I" + @base.Name; var name = "I" + @base.Name;
var @interface = (interfaces.ContainsKey(@base) var @interface = (this.interfaces.ContainsKey(@base)
? interfaces[@base] ? this.interfaces[@base]
: @base.Namespace.Classes.FirstOrDefault(c => c.Name == name)) ?? : @base.Namespace.Classes.FirstOrDefault(c => c.Name == name)) ??
GetNewInterface(@class, name, @base); GetNewInterface(@class, name, @base, addMembers);
@class.Bases[i] = new BaseClassSpecifier { Type = new TagType(@interface) }; return @interface;
}
return base.VisitClassDecl(@class);
} }
private Class GetNewInterface(Class @class, string name, Class @base) private Class GetNewInterface(Class @class, string name, Class @base, bool addMembers = false)
{ {
var @interface = new Class var @interface = new Class
{ {
@ -48,8 +54,27 @@ namespace CppSharp.Passes
Access = @base.Access, Access = @base.Access,
IsInterface = true IsInterface = true
}; };
@interface.Bases.AddRange(
from b in @base.Bases
let i = GetInterface(@base, b.Class)
select new BaseClassSpecifier { Type = new TagType(i) });
@interface.Methods.AddRange(@base.Methods.Where( @interface.Methods.AddRange(@base.Methods.Where(
m => !m.IsConstructor && !m.IsDestructor && !m.IsStatic && !m.Ignore)); m => !m.IsConstructor && !m.IsDestructor && !m.IsStatic && !m.Ignore));
@interface.Properties.AddRange(@base.Properties.Where(p => !p.Ignore));
@interface.Events.AddRange(@base.Events);
if (addMembers)
{
ImplementInterfaceMethods(@class, @interface);
ImplementInterfaceProperties(@class, @interface);
if (@base.Bases.All(b => b.Class != @interface))
@base.Bases.Add(new BaseClassSpecifier { Type = new TagType(@interface) });
}
interfaces.Add(@base, @interface);
return @interface;
}
private static void ImplementInterfaceMethods(Class @class, Class @interface)
{
foreach (var method in @interface.Methods) foreach (var method in @interface.Methods)
{ {
var impl = new Method(method) var impl = new Method(method)
@ -58,28 +83,27 @@ namespace CppSharp.Passes
IsVirtual = false, IsVirtual = false,
IsOverride = false IsOverride = false
}; };
var rootBaseMethod = @class.GetRootBaseMethod(method); var rootBaseMethod = @class.GetRootBaseMethod(method, true);
if (rootBaseMethod != null && !rootBaseMethod.Ignore) if (rootBaseMethod != null && !rootBaseMethod.Ignore)
impl.Name = @interface.Name + "." + impl.Name; impl.Name = @interface.Name + "." + impl.Name;
@class.Methods.Add(impl); @class.Methods.Add(impl);
} }
@interface.Properties.AddRange(@base.Properties.Where(p => !p.Ignore)); foreach (var @base in @interface.Bases)
foreach (var property in @interface.Properties) ImplementInterfaceMethods(@class, @base.Class);
}
private static void ImplementInterfaceProperties(Class @class, Class @interface)
{ {
var impl = new Property(property) foreach (var property in @interface.Properties)
{ {
Namespace = @class var impl = new Property(property) { Namespace = @class };
}; var rootBaseProperty = @class.GetRootBaseProperty(property, true);
var rootBaseProperty = @class.GetRootBaseProperty(property);
if (rootBaseProperty != null && !rootBaseProperty.Ignore) if (rootBaseProperty != null && !rootBaseProperty.Ignore)
impl.Name = @interface.Name + "." + impl.Name; impl.Name = @interface.Name + "." + impl.Name;
@class.Properties.Add(impl); @class.Properties.Add(impl);
} }
@interface.Events.AddRange(@base.Events); foreach (var @base in @interface.Bases)
if (@base.Bases.All(b => b.Class != @interface)) ImplementInterfaceProperties(@class, @base.Class);
@base.Bases.Add(new BaseClassSpecifier { Type = new TagType(@interface) });
interfaces.Add(@base, @interface);
return @interface;
} }
} }
} }

5
tests/CSharpTemp/CSharpTemp.cpp

@ -31,6 +31,11 @@ const Foo& Bar::operator[](int i) const
return m_foo; return m_foo;
} }
int Qux::farAwayFunc()
{
return 20;
}
int Bar::method() int Bar::method()
{ {
return 2; return 2;

8
tests/CSharpTemp/CSharpTemp.h

@ -18,7 +18,13 @@ protected:
int P; int P;
}; };
class DLL_API Bar class DLL_API Qux
{
public:
int farAwayFunc();
};
class DLL_API Bar : public Qux
{ {
public: public:
int method(); int method();

Loading…
Cancel
Save