Browse Source

Merge pull request #77 from ddobrev/master

Properties
pull/78/head
João Matos 12 years ago
parent
commit
5d436f1b48
  1. 2
      src/AST/Class.cs
  2. 36
      src/AST/Property.cs
  3. 3
      src/Generator/Driver.cs
  4. 5
      src/Generator/Generator.lua
  5. 111
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  6. 2
      src/Generator/Passes/FindSymbolsPass.cs
  7. 5
      src/Generator/Passes/GenerateAbstractImplementationsPass.cs
  8. 245
      src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs
  9. 12
      src/Generator/Passes/MultipleInheritancePass.cs
  10. 12
      src/Generator/Passes/RenamePass.cs
  11. 8828
      src/Generator/Passes/verbs.txt
  12. 23
      tests/CSharpTemp/CSharpTemp.Tests.cs
  13. 30
      tests/CSharpTemp/CSharpTemp.cpp
  14. 1
      tests/CSharpTemp/CSharpTemp.cs
  15. 29
      tests/CSharpTemp/CSharpTemp.h

2
src/AST/Class.cs

@ -231,7 +231,7 @@ namespace CppSharp.AST
public Property GetRootBaseProperty(Property @override, bool onlyFirstBase = false) public Property GetRootBaseProperty(Property @override, bool onlyFirstBase = false)
{ {
return (from @base in Bases return (from @base in Bases
where !onlyFirstBase || !@base.Class.IsInterface where (!onlyFirstBase || !@base.Class.IsInterface) && @base.IsClass
let baseProperty = ( let baseProperty = (
from property in @base.Class.Properties from property in @base.Class.Properties
where where

36
src/AST/Property.cs

@ -28,6 +28,42 @@ namespace CppSharp.AST
public QualifiedType QualifiedType { get; set; } public QualifiedType QualifiedType { get; set; }
public bool IsStatic
{
get
{
return (GetMethod != null && GetMethod.IsStatic) ||
(SetMethod != null && SetMethod.IsStatic);
}
}
public bool IsPure
{
get
{
return (GetMethod != null && GetMethod.IsPure) ||
(SetMethod != null && SetMethod.IsPure);
}
}
public bool IsVirtual
{
get
{
return (GetMethod != null && GetMethod.IsVirtual) ||
(SetMethod != null && SetMethod.IsVirtual);
}
}
public bool IsOverride
{
get
{
return (GetMethod != null && GetMethod.IsOverride) ||
(SetMethod != null && SetMethod.IsOverride);
}
}
public Method GetMethod { get; set; } public Method GetMethod { get; set; }
public Method SetMethod { get; set; } public Method SetMethod { get; set; }

3
src/Generator/Driver.cs

@ -158,6 +158,8 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new MultipleInheritancePass()); TranslationUnitPasses.AddPass(new MultipleInheritancePass());
TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass()); TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass());
} }
if (Options.GenerateProperties)
TranslationUnitPasses.AddPass(new GetterSetterToPropertyAdvancedPass());
} }
public void ProcessCode() public void ProcessCode()
@ -288,6 +290,7 @@ namespace CppSharp
public bool GenerateVirtualTables; public bool GenerateVirtualTables;
public bool GenerateAbstractImpls; public bool GenerateAbstractImpls;
public bool GenerateInterfacesForMultipleInheritance; public bool GenerateInterfacesForMultipleInheritance;
public bool GenerateProperties;
public bool GenerateInternalImports; public bool GenerateInternalImports;
public string IncludePrefix; public string IncludePrefix;
public bool WriteOnlyWhenChanged; public bool WriteOnlyWhenChanged;

5
src/Generator/Generator.lua

@ -4,7 +4,10 @@ project "CppSharp.Generator"
language "C#" language "C#"
location "." location "."
files { "**.cs", "**.bmp", "**.resx", "**.config" } files { "**.cs", "**.bmp", "**.resx", "**.config", "**verbs.txt" }
excludes { "Filter.cs" } excludes { "Filter.cs" }
links { "System", "System.Core", "CppSharp.AST", "CppSharp.Parser" } links { "System", "System.Core", "CppSharp.AST", "CppSharp.Parser" }
configuration '**verbs.txt'
buildaction "Embed"

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

@ -784,7 +784,6 @@ namespace CppSharp.Generators.CSharp
{ {
PushBlock(CSharpBlockKind.Method); PushBlock(CSharpBlockKind.Method);
WriteLine("set"); WriteLine("set");
WriteStartBraceIndent();
var param = new Parameter var param = new Parameter
{ {
@ -801,7 +800,14 @@ namespace CppSharp.Generators.CSharp
if (decl is Function) if (decl is Function)
{ {
var function = decl as Function; var function = decl as Function;
if (function.IsPure && Driver.Options.GenerateAbstractImpls)
{
Write("; ");
PopBlock(NewLineKind.BeforeNextBlock);
return;
}
WriteStartBraceIndent();
if (function.Parameters.Count == 0) if (function.Parameters.Count == 0)
throw new NotSupportedException("Expected at least one parameter in setter"); throw new NotSupportedException("Expected at least one parameter in setter");
@ -810,16 +816,32 @@ namespace CppSharp.Generators.CSharp
var method = function as Method; var method = function as Method;
if (method != null && method.OperatorKind == CXXOperatorKind.Subscript) if (method != null && method.OperatorKind == CXXOperatorKind.Subscript)
{ {
GenerateIndexerSetter(returnType, method); if (method.IsOverride && method.IsSynthetized)
{
GenerateVirtualTableFunctionCall(function, @class);
}
else
{
if (method.OperatorKind == CXXOperatorKind.Subscript)
{
GenerateIndexerSetter(returnType, method);
}
else
{
var parameters = new List<Parameter> { param };
GenerateInternalFunctionCall(function, parameters);
}
}
} }
else else
{ {
var parameters = new List<Parameter> { param }; var parameters = new List<Parameter> { param };
GenerateInternalFunctionCall(function, parameters); GenerateInternalFunctionCall(function, parameters);
} }
} }
else if (decl is Field) else if (decl is Field)
{ {
WriteStartBraceIndent();
var field = decl as Field; var field = decl as Field;
WriteLine("var {0} = (Internal*){1}.ToPointer();", WriteLine("var {0} = (Internal*){1}.ToPointer();",
@ -865,22 +887,39 @@ namespace CppSharp.Generators.CSharp
where T : Declaration, ITypedDecl where T : Declaration, ITypedDecl
{ {
PushBlock(CSharpBlockKind.Method); PushBlock(CSharpBlockKind.Method);
WriteLine("get"); Write("get");
WriteStartBraceIndent();
if (decl is Function) if (decl is Function)
{ {
var function = decl as Function; var function = decl as Function;
bool isPrimitiveIndexer = function.OperatorKind == CXXOperatorKind.Subscript && if (function.IsPure && Driver.Options.GenerateAbstractImpls)
function.ReturnType.Type.IsPointerToPrimitiveType(); {
if (isPrimitiveIndexer) Write("; ");
TypePrinter.PushContext(CSharpTypePrinterContextKind.PrimitiveIndexer); PopBlock(NewLineKind.BeforeNextBlock);
GenerateInternalFunctionCall(function); return;
if (isPrimitiveIndexer) }
TypePrinter.PopContext(); NewLine();
WriteStartBraceIndent();
Method method = function as Method;
if (method != null && method.IsOverride && method.IsSynthetized)
{
GenerateVirtualTableFunctionCall(function, @class);
}
else
{
bool isPrimitiveIndexer = function.OperatorKind == CXXOperatorKind.Subscript &&
function.ReturnType.Type.IsPointerToPrimitiveType();
if (isPrimitiveIndexer)
TypePrinter.PushContext(CSharpTypePrinterContextKind.PrimitiveIndexer);
GenerateInternalFunctionCall(function);
if (isPrimitiveIndexer)
TypePrinter.PopContext();
}
} }
else if (decl is Field) else if (decl is Field)
{ {
NewLine();
WriteStartBraceIndent();
var field = decl as Field; var field = decl as Field;
WriteLine("var {0} = (Internal*){1}.ToPointer();", WriteLine("var {0} = (Internal*){1}.ToPointer();",
@ -905,6 +944,8 @@ namespace CppSharp.Generators.CSharp
} }
else if (decl is Variable) else if (decl is Variable)
{ {
NewLine();
WriteStartBraceIndent();
var @var = decl as Variable; var @var = decl as Variable;
var libSymbol = GetDeclarationLibrarySymbol(@var); var libSymbol = GetDeclarationLibrarySymbol(@var);
@ -990,10 +1031,22 @@ namespace CppSharp.Generators.CSharp
type = ((PointerType) prop.Type).Pointee; type = ((PointerType) prop.Type).Pointee;
if (prop.ExplicitInterfaceImpl == null) if (prop.ExplicitInterfaceImpl == null)
WriteLine("{0}{1} {2}", Helpers.GetAccess(prop.Access), {
type, GetPropertyName(prop)); Write(Helpers.GetAccess(prop.Access));
if (prop.IsStatic)
Write("static ");
if (prop.IsOverride)
Write("override ");
else if (prop.IsPure && Driver.Options.GenerateAbstractImpls)
Write("abstract ");
else if (prop.IsVirtual)
Write("virtual ");
WriteLine("{0} {1}", type, GetPropertyName(prop));
}
else else
{
WriteLine("{0} {1}.{2}", type, prop.ExplicitInterfaceImpl.Name, GetPropertyName(prop)); WriteLine("{0} {1}.{2}", type, prop.ExplicitInterfaceImpl.Name, GetPropertyName(prop));
}
WriteStartBraceIndent(); WriteStartBraceIndent();
if (prop.Field != null) if (prop.Field != null)
@ -1044,7 +1097,9 @@ namespace CppSharp.Generators.CSharp
public void GenerateVTable(Class @class) public void GenerateVTable(Class @class)
{ {
var entries = VTables.GatherVTableMethodEntries(@class); var entries = VTables.GatherVTableMethodEntries(@class);
entries = entries.Where(entry => !entry.Method.Ignore).ToList(); entries = entries.Where(e => !e.Method.Ignore ||
@class.Properties.Any(p => !p.Ignore &&
(p.GetMethod == e.Method || p.SetMethod == e.Method))).ToList();
if (entries.Count == 0) if (entries.Count == 0)
return; return;
@ -1203,7 +1258,14 @@ namespace CppSharp.Generators.CSharp
if (hasReturn) if (hasReturn)
Write("var _ret = "); Write("var _ret = ");
WriteLine("target.{0}({1});", SafeIdentifier(method.Name), string.Join(", ", marshals)); if (method.IsGenerated)
{
WriteLine("target.{0}({1});", SafeIdentifier(method.Name), string.Join(", ", marshals));
}
else
{
InvokeProperty(method, marshals);
}
// TODO: Handle hidden structure return types. // TODO: Handle hidden structure return types.
@ -1233,6 +1295,23 @@ namespace CppSharp.Generators.CSharp
} }
} }
private void InvokeProperty(Declaration method, IEnumerable<string> marshals)
{
var property = ((Class) method.Namespace).Properties.FirstOrDefault(
p => p.GetMethod == method);
if (property == null)
{
property = ((Class) method.Namespace).Properties.First(
p => p.SetMethod == method);
WriteLine("target.{0} = {1};", SafeIdentifier(property.Name),
string.Join(", ", marshals));
}
else
{
WriteLine("target.{0};", SafeIdentifier(property.Name));
}
}
private void GenerateVTableMethodDelegates(Class @class, Method method) private void GenerateVTableMethodDelegates(Class @class, Method method)
{ {
PushBlock(CSharpBlockKind.VTableDelegate); PushBlock(CSharpBlockKind.VTableDelegate);

2
src/Generator/Passes/FindSymbolsPass.cs

@ -12,7 +12,7 @@ namespace CppSharp.Passes
var mangledDecl = decl as IMangledDecl; var mangledDecl = decl as IMangledDecl;
var method = decl as Method; var method = decl as Method;
if (mangledDecl != null && !(method != null && method.IsPure) && if (mangledDecl != null && !(method != null && (method.IsPure || method.IsSynthetized)) &&
!VisitMangledDeclaration(mangledDecl)) !VisitMangledDeclaration(mangledDecl))
{ {
decl.ExplicityIgnored = true; decl.ExplicityIgnored = true;

5
src/Generator/Passes/GenerateAbstractImplementationsPass.cs

@ -57,7 +57,8 @@ namespace CppSharp.Passes
{ {
Name = abstractMethod.Name + "Delegate", Name = abstractMethod.Name + "Delegate",
QualifiedType = abstractMethod.GetFunctionType(), QualifiedType = abstractMethod.GetFunctionType(),
IgnoreFlags = abstractMethod.IgnoreFlags IgnoreFlags = abstractMethod.IgnoreFlags,
Namespace = internalImpl
}; };
internalImpl.Typedefs.Add(@delegate); internalImpl.Typedefs.Add(@delegate);
} }
@ -79,7 +80,7 @@ namespace CppSharp.Passes
var internalImpl = new Class var internalImpl = new Class
{ {
Name = @class.Name + "Internal", Name = @class.Name + "Internal",
Access = AccessSpecifier.Private, Access = @class.Access,
Namespace = @class.Namespace Namespace = @class.Namespace
}; };
var @base = new BaseClassSpecifier { Type = new TagType(@class) }; var @base = new BaseClassSpecifier { Type = new TagType(@class) };

245
src/Generator/Passes/GetterSetterToPropertyAdvancedPass.cs

@ -0,0 +1,245 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using CppSharp.AST;
namespace CppSharp.Passes
{
class GetterSetterToPropertyAdvancedPass : TranslationUnitPass
{
// collect all types of methods first to be able to match pairs and detect virtuals and overrides;
// (a property needs to) be virtual or an override if either of its constituent methods are such)
private readonly List<Method> setters = new List<Method>();
private readonly List<Method> setMethods = new List<Method>();
private readonly List<Method> nonSetters = new List<Method>();
private readonly HashSet<Method> getters = new HashSet<Method>();
private static readonly HashSet<string> verbs = new HashSet<string>();
static GetterSetterToPropertyAdvancedPass()
{
LoadVerbs();
}
private static void LoadVerbs()
{
using (var resourceStream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("CppSharp.Generator.Passes.verbs.txt"))
{
using (StreamReader streamReader = new StreamReader(resourceStream))
while (!streamReader.EndOfStream)
verbs.Add(streamReader.ReadLine());
}
}
public GetterSetterToPropertyAdvancedPass()
{
Options.VisitClassFields = false;
Options.VisitClassProperties = false;
Options.VisitNamespaceEnums = false;
Options.VisitNamespaceTemplates = false;
Options.VisitNamespaceTypedefs = false;
Options.VisitNamespaceEvents = false;
Options.VisitNamespaceVariables = false;
Options.VisitFunctionParameters = false;
Options.VisitTemplateArguments = false;
}
public override bool VisitTranslationUnit(TranslationUnit unit)
{
bool result = base.VisitTranslationUnit(unit);
GenerateProperties();
return result;
}
public override bool VisitMethodDecl(Method method)
{
if (!method.IsConstructor && !method.IsDestructor && !method.IsOperator &&
!method.Ignore)
DistributeMethod(method);
return base.VisitMethodDecl(method);
}
public void GenerateProperties()
{
GenerateProperties(setters, false);
GenerateProperties(setMethods, true);
foreach (Method getter in
from getter in getters
where getter.IsGenerated &&
((Class) getter.Namespace).Methods.All(m => m == getter || m.Name != getter.Name)
select getter)
{
// Make it a read-only property
GenerateProperty(getter.Namespace, getter);
}
}
private void GenerateProperties(IEnumerable<Method> settersToUse, bool readOnly)
{
foreach (var group in settersToUse.GroupBy(m => m.Namespace))
{
foreach (var setter in group)
{
Class type = (Class) setter.Namespace;
StringBuilder nameBuilder = new StringBuilder(setter.Name.Substring(3));
if (char.IsLower(setter.Name[0]))
nameBuilder[0] = char.ToLowerInvariant(nameBuilder[0]);
string afterSet = nameBuilder.ToString();
foreach (var getter in nonSetters.Where(m => m.Namespace == type))
{
string name = GetPropertyName(getter.Name);
if (string.Compare(name, afterSet, StringComparison.OrdinalIgnoreCase) == 0 &&
getter.ReturnType == setter.Parameters[0].QualifiedType &&
!type.Methods.Any(
m =>
m != getter &&
string.Compare(name, m.Name, StringComparison.OrdinalIgnoreCase) == 0))
{
GenerateProperty(getter.Namespace, getter, readOnly ? null : setter);
goto next;
}
}
Property baseVirtualProperty = type.GetRootBaseProperty(new Property { Name = afterSet });
if (!type.IsInterface && baseVirtualProperty != null)
{
bool isReadOnly = baseVirtualProperty.SetMethod == null;
GenerateProperty(setter.Namespace, baseVirtualProperty.GetMethod,
readOnly || isReadOnly ? null : setter);
}
next:
;
}
}
foreach (Method nonSetter in nonSetters)
{
Class type = (Class) nonSetter.Namespace;
string name = GetPropertyName(nonSetter.Name);
Property baseVirtualProperty = type.GetRootBaseProperty(new Property { Name = name });
if (!type.IsInterface && baseVirtualProperty != null)
{
bool isReadOnly = baseVirtualProperty.SetMethod == null;
if (readOnly == isReadOnly)
{
GenerateProperty(nonSetter.Namespace, nonSetter,
readOnly ? null : baseVirtualProperty.SetMethod);
}
}
}
}
private static void GenerateProperty(DeclarationContext context, Method getter, Method setter = null)
{
Class type = (Class) context;
if (type.Properties.All(
p => string.Compare(getter.Name, p.Name, StringComparison.OrdinalIgnoreCase) != 0 ||
p.ExplicitInterfaceImpl != getter.ExplicitInterfaceImpl))
{
Property property = new Property();
property.Name = GetPropertyName(getter.Name);
property.Namespace = type;
property.QualifiedType = getter.ReturnType;
if (getter.IsOverride || (setter != null && setter.IsOverride))
{
Property baseVirtualProperty = type.GetRootBaseProperty(property);
if (baseVirtualProperty.SetMethod == null)
setter = null;
foreach (Method method in type.Methods.Where(m => m.Name == property.Name && m.Parameters.Count > 0))
method.Name = "get" + method.Name;
}
property.GetMethod = getter;
property.SetMethod = setter;
property.ExplicitInterfaceImpl = getter.ExplicitInterfaceImpl;
if (property.ExplicitInterfaceImpl == null && setter != null)
{
property.ExplicitInterfaceImpl = setter.ExplicitInterfaceImpl;
}
if (getter.Comment != null)
{
var comment = new RawComment();
comment.Kind = getter.Comment.Kind;
comment.BriefText = getter.Comment.BriefText;
comment.Text = getter.Comment.Text;
comment.FullComment = new FullComment();
comment.FullComment.Blocks.AddRange(getter.Comment.FullComment.Blocks);
if (setter != null && setter.Comment != null)
{
comment.BriefText += Environment.NewLine + setter.Comment.BriefText;
comment.Text += Environment.NewLine + setter.Comment.Text;
comment.FullComment.Blocks.AddRange(setter.Comment.FullComment.Blocks);
}
property.Comment = comment;
}
type.Properties.Add(property);
getter.IsGenerated = false;
if (setter != null)
setter.IsGenerated = false;
}
}
private static string GetPropertyName(string name)
{
if (GetFirstWord(name) == "get")
{
if (char.IsLower(name[0]))
{
if (name.Length == 4)
{
return char.ToLowerInvariant(
name[3]).ToString(CultureInfo.InvariantCulture);
}
return char.ToLowerInvariant(
name[3]).ToString(CultureInfo.InvariantCulture) +
name.Substring(4);
}
return name.Substring(3);
}
return name;
}
private void DistributeMethod(Method method)
{
if (GetFirstWord(method.Name) == "set" && method.Name.Length > 3 &&
method.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void))
{
if (method.Parameters.Count == 1)
setters.Add(method);
else
setMethods.Add(method);
}
else
{
if (IsGetter(method))
getters.Add(method);
if (method.Parameters.Count == 0)
nonSetters.Add(method);
}
}
private bool IsGetter(Method method)
{
if (method.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void) ||
method.Parameters.Count > 0 || method.IsDestructor)
return false;
var result = GetFirstWord(method.Name);
return (result.Length < method.Name.Length &&
(result == "get" || result == "is" || result == "has")) ||
(result != "to" && result != "new" && !verbs.Contains(result));
}
private static string GetFirstWord(string name)
{
List<char> firstVerb = new List<char>
{
char.ToLowerInvariant(name[0])
};
firstVerb.AddRange(name.Skip(1).TakeWhile(
c => char.IsLower(c) || !char.IsLetterOrDigit(c)));
return new string(firstVerb.ToArray());
}
}
}

12
src/Generator/Passes/MultipleInheritancePass.cs

@ -66,9 +66,15 @@ namespace CppSharp.Passes
let i = GetInterface(@base, b.Class) let i = GetInterface(@base, b.Class)
select new BaseClassSpecifier { Type = new TagType(i) }); select new BaseClassSpecifier { Type = new TagType(i) });
@interface.Methods.AddRange(@base.Methods.Where( @interface.Methods.AddRange(
m => !m.IsConstructor && !m.IsDestructor && !m.IsStatic && !m.Ignore)); from m in @base.Methods
@interface.Properties.AddRange(@base.Properties.Where(p => !p.Ignore)); where !m.IsConstructor && !m.IsDestructor && !m.IsStatic && !m.Ignore
select new Method(m) { Namespace = @interface });
@interface.Properties.AddRange(
from property in @base.Properties
where !property.Ignore
select new Property(property) { Namespace = @interface });
if (@interface.Bases.Count == 0) if (@interface.Bases.Count == 0)
{ {

12
src/Generator/Passes/RenamePass.cs

@ -39,6 +39,7 @@ namespace CppSharp.Passes
if (decl is Enumeration) return true; if (decl is Enumeration) return true;
if (decl is Property) return true; if (decl is Property) return true;
if (decl is Event) return true; if (decl is Event) return true;
if (decl is TypedefDecl) return true;
return false; return false;
} }
@ -125,6 +126,14 @@ namespace CppSharp.Passes
return base.VisitProperty(property); return base.VisitProperty(property);
} }
public override bool VisitTypedefDecl(TypedefDecl typedef)
{
if (!Targets.HasFlag(RenameTargets.Delegate))
return false;
return base.VisitTypedefDecl(typedef);
}
public override bool VisitMethodDecl(Method method) public override bool VisitMethodDecl(Method method)
{ {
if (!Targets.HasFlag(RenameTargets.Method)) if (!Targets.HasFlag(RenameTargets.Method))
@ -173,7 +182,8 @@ namespace CppSharp.Passes
EnumItem = 1 << 6, EnumItem = 1 << 6,
Event = 1 << 7, Event = 1 << 7,
Property = 1 << 8, Property = 1 << 8,
Any = Function | Method | Parameter | Class | Field | Enum | EnumItem | Event | Property, Delegate = 1 << 9,
Any = Function | Method | Parameter | Class | Field | Enum | EnumItem | Event | Property | Delegate,
} }
/// <summary> /// <summary>

8828
src/Generator/Passes/verbs.txt

File diff suppressed because it is too large Load Diff

23
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -45,19 +45,34 @@ public class CSharpTempTests
public void TestMultipleInheritance() public void TestMultipleInheritance()
{ {
Baz baz = new Baz(); Baz baz = new Baz();
Assert.That(baz.method(), Is.EqualTo(1)); Assert.That(baz.method, Is.EqualTo(1));
var bar = (IBar) baz; var bar = (IBar) baz;
Assert.That(bar.method(), Is.EqualTo(2)); Assert.That(bar.method, Is.EqualTo(2));
Assert.That(baz[0], Is.EqualTo(50)); Assert.That(baz[0], Is.EqualTo(50));
bar[0] = new Foo { A = 1000 }; bar[0] = new Foo { A = 1000 };
Assert.That(bar[0].A, Is.EqualTo(1000)); Assert.That(bar[0].A, Is.EqualTo(1000));
Assert.That(baz.farAwayFunc(), Is.EqualTo(20)); Assert.That(baz.farAwayFunc, Is.EqualTo(20));
Assert.That(baz.takesQux(baz), Is.EqualTo(20)); Assert.That(baz.takesQux(baz), Is.EqualTo(20));
Assert.That(baz.returnQux().farAwayFunc(), Is.EqualTo(20)); Assert.That(baz.returnQux().farAwayFunc, Is.EqualTo(20));
int cast = baz; int cast = baz;
Assert.That(cast, Is.EqualTo(500)); Assert.That(cast, Is.EqualTo(500));
var nested = new Baz.Nested(); var nested = new Baz.Nested();
int nestedCast = nested; int nestedCast = nested;
Assert.That(nestedCast, Is.EqualTo(300)); Assert.That(nestedCast, Is.EqualTo(300));
} }
[Test]
public void TestProperties()
{
var proprietor = new Proprietor();
proprietor.value = 20;
Assert.That(proprietor.value, Is.EqualTo(20));
proprietor.prop = 50;
Assert.That(proprietor.prop, Is.EqualTo(50));
var p = new P();
p.value = 20;
Assert.That(p.value, Is.EqualTo(30));
p.prop = 50;
Assert.That(p.prop, Is.EqualTo(150));
}
} }

30
tests/CSharpTemp/CSharpTemp.cpp

@ -65,3 +65,33 @@ Baz::operator int() const
{ {
return 500; return 500;
} }
int AbstractProprietor::getValue()
{
return m_value;
}
void AbstractProprietor::setProp(long property)
{
m_property = property;
}
void Proprietor::setValue(int value)
{
m_value = value;
}
long Proprietor::prop()
{
return m_property;
}
void P::setValue(int value)
{
m_value = value + 10;
}
long P::prop()
{
return m_property + 100;
}

1
tests/CSharpTemp/CSharpTemp.cs

@ -13,6 +13,7 @@ namespace CppSharp.Tests
public override void SetupPasses(Driver driver) public override void SetupPasses(Driver driver)
{ {
driver.Options.GenerateInterfacesForMultipleInheritance = true; driver.Options.GenerateInterfacesForMultipleInheritance = true;
driver.Options.GenerateProperties = true;
} }
static class Program static class Program

29
tests/CSharpTemp/CSharpTemp.h

@ -63,3 +63,32 @@ struct QByteArrayDataPtr
{ {
QByteArrayData* ptr; QByteArrayData* ptr;
}; };
class DLL_API AbstractProprietor
{
public:
virtual int getValue();
virtual void setValue(int value) = 0;
virtual long prop() = 0;
virtual void setProp(long prop);
protected:
int m_value;
long m_property;
};
class DLL_API Proprietor : public AbstractProprietor
{
public:
virtual void setValue(int value);
virtual long prop();
};
class DLL_API P : Proprietor
{
public:
virtual void setValue(int value);
virtual long prop();
};

Loading…
Cancel
Save