Browse Source

Merge pull request #61 from ddobrev/master

Read-only support for operator []
pull/62/merge
João Matos 12 years ago
parent
commit
c242c5d807
  1. 12
      src/AST/Property.cs
  2. 3
      src/Generator/Driver.cs
  3. 37
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  4. 8
      src/Generator/Passes/CheckAmbiguousFunctions.cs
  5. 30
      src/Generator/Passes/CheckOperatorsOverloads.cs
  6. 7
      tests/Basic/Basic.Tests.cs
  7. 4
      tests/Basic/Basic.h
  8. 21
      tests/CSharpTemp/CSharpTemp.Tests.cs
  9. 12
      tests/CSharpTemp/CSharpTemp.cpp
  10. 22
      tests/CSharpTemp/CSharpTemp.cs
  11. 15
      tests/CSharpTemp/CSharpTemp.h
  12. 2
      tests/CSharpTemp/premake4.lua
  13. 8
      tests/UTF16/UTF16.Tests.cs
  14. 11
      tests/UTF16/UTF16.cpp
  15. 4
      tests/UTF16/UTF16.h

12
src/AST/Property.cs

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace CppSharp.AST namespace CppSharp.AST
{ {
/// <summary> /// <summary>
@ -36,6 +38,16 @@ namespace CppSharp.AST
// The field that should be get and set by this property // The field that should be get and set by this property
public Field Field { get; set; } public Field Field { get; set; }
private readonly List<Parameter> parameters = new List<Parameter>();
/// <summary>
/// Only applicable to index ([]) properties.
/// </summary>
public List<Parameter> Parameters
{
get { return parameters; }
}
public override T Visit<T>(IDeclVisitor<T> visitor) public override T Visit<T>(IDeclVisitor<T> visitor)
{ {
return visitor.VisitProperty(this); return visitor.VisitProperty(this);

3
src/Generator/Driver.cs

@ -134,15 +134,16 @@ namespace CppSharp
TranslationUnitPasses.AddPass(new ResolveIncompleteDeclsPass()); TranslationUnitPasses.AddPass(new ResolveIncompleteDeclsPass());
TranslationUnitPasses.AddPass(new CleanInvalidDeclNamesPass()); TranslationUnitPasses.AddPass(new CleanInvalidDeclNamesPass());
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass()); TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
if (Options.IsCSharpGenerator)
TranslationUnitPasses.AddPass(new GenerateInlinesCodePass()); TranslationUnitPasses.AddPass(new GenerateInlinesCodePass());
library.SetupPasses(this); library.SetupPasses(this);
TranslationUnitPasses.AddPass(new FindSymbolsPass()); TranslationUnitPasses.AddPass(new FindSymbolsPass());
TranslationUnitPasses.AddPass(new MoveOperatorToClassPass()); TranslationUnitPasses.AddPass(new MoveOperatorToClassPass());
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass()); TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass());
TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance()); TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance());
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
Generator.SetupPasses(); Generator.SetupPasses();
TranslationUnitPasses.AddPass(new FieldToPropertyPass()); TranslationUnitPasses.AddPass(new FieldToPropertyPass());

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

@ -893,14 +893,12 @@ namespace CppSharp.Generators.CSharp
private void GenerateClassProperties(Class @class) private void GenerateClassProperties(Class @class)
{ {
foreach (var prop in @class.Properties) foreach (var prop in @class.Properties.Where(p => !p.Ignore))
{ {
if (prop.Ignore) continue;
PushBlock(CSharpBlockKind.Property); PushBlock(CSharpBlockKind.Property);
WriteLine("{0} {1} {2}", WriteLine("{0} {1} {2}",
prop.Access == AccessSpecifier.Public ? "public" : "protected", prop.Access == AccessSpecifier.Public ? "public" : "protected",
prop.Type, SafeIdentifier(prop.Name)); prop.Type, GetPropertyName(prop));
WriteStartBraceIndent(); WriteStartBraceIndent();
if (prop.Field != null) if (prop.Field != null)
@ -925,6 +923,12 @@ namespace CppSharp.Generators.CSharp
} }
} }
private string GetPropertyName(Property prop)
{
return prop.Parameters.Count == 0 ? SafeIdentifier(prop.Name)
: string.Format("this[{0}]", FormatMethodParameters(prop.Parameters));
}
private void GenerateVariable(Class @class, Type type, Variable variable) private void GenerateVariable(Class @class, Type type, Variable variable)
{ {
PushBlock(CSharpBlockKind.Variable); PushBlock(CSharpBlockKind.Variable);
@ -1469,7 +1473,7 @@ namespace CppSharp.Generators.CSharp
var functionName = GetFunctionIdentifier(function); var functionName = GetFunctionIdentifier(function);
Write("public static {0} {1}(", function.OriginalReturnType, functionName); Write("public static {0} {1}(", function.OriginalReturnType, functionName);
GenerateMethodParameters(function); Write(FormatMethodParameters(function.Parameters));
WriteLine(")"); WriteLine(")");
WriteStartBraceIndent(); WriteStartBraceIndent();
@ -1517,7 +1521,7 @@ namespace CppSharp.Generators.CSharp
else else
Write("{0} {1}(", method.OriginalReturnType, functionName); Write("{0} {1}(", method.OriginalReturnType, functionName);
GenerateMethodParameters(method); Write(FormatMethodParameters(method.Parameters));
Write(")"); Write(")");
@ -1938,25 +1942,16 @@ namespace CppSharp.Generators.CSharp
} }
} }
private void GenerateMethodParameters(Function function) private string FormatMethodParameters(IEnumerable<Parameter> @params)
{
var @params = new List<string>();
for (var i = 0; i < function.Parameters.Count; ++i)
{ {
var param = function.Parameters[i]; return string.Join(", ",
from param in @params
if (param.Kind == ParameterKind.IndirectReturnType) where param.Kind != ParameterKind.IndirectReturnType
continue; let typeName = param.CSharpType(this.TypePrinter)
select string.Format("{0}{1} {2}", GetParameterUsage(param.Usage),
var typeName = param.CSharpType(TypePrinter);
@params.Add(string.Format("{0}{1} {2}", GetParameterUsage(param.Usage),
typeName, SafeIdentifier(param.Name))); typeName, SafeIdentifier(param.Name)));
} }
Write(string.Join(", ", @params));
}
#endregion #endregion
public bool GenerateTypedef(TypedefDecl typedef) public bool GenerateTypedef(TypedefDecl typedef)

8
src/Generator/Passes/CheckAmbiguousFunctions.cs

@ -23,14 +23,6 @@ namespace CppSharp.Passes
/// </summary> /// </summary>
public class CheckAmbiguousFunctions : TranslationUnitPass public class CheckAmbiguousFunctions : TranslationUnitPass
{ {
public override bool VisitMethodDecl(Method method)
{
if (method.Kind != CXXMethodKind.Normal)
return false;
return base.VisitMethodDecl(method);
}
public override bool VisitFunctionDecl(AST.Function function) public override bool VisitFunctionDecl(AST.Function function)
{ {
if (AlreadyVisited(function)) if (AlreadyVisited(function))

30
src/Generator/Passes/CheckOperatorsOverloads.cs

@ -44,7 +44,7 @@ namespace CppSharp.Passes
private void CheckInvalidOperators(Class @class) private void CheckInvalidOperators(Class @class)
{ {
foreach (var @operator in @class.Operators) foreach (var @operator in @class.Operators.Where(o => !o.Ignore))
{ {
if (!IsValidOperatorOverload(@operator)) if (!IsValidOperatorOverload(@operator))
{ {
@ -57,6 +57,12 @@ namespace CppSharp.Passes
if (@operator.SynthKind == FunctionSynthKind.NonMemberOperator) if (@operator.SynthKind == FunctionSynthKind.NonMemberOperator)
continue; continue;
if (@operator.OperatorKind == CXXOperatorKind.Subscript)
{
CreateIndexer(@class, @operator);
}
else
{
// Handle missing operator parameters // Handle missing operator parameters
if (@operator.IsStatic) if (@operator.IsStatic)
@operator.Parameters = @operator.Parameters.Skip(1).ToList(); @operator.Parameters = @operator.Parameters.Skip(1).ToList();
@ -75,6 +81,22 @@ namespace CppSharp.Passes
}); });
} }
} }
}
private static void CreateIndexer(Class @class, Method @operator)
{
Property property = new Property
{
Name = "Item",
QualifiedType = @operator.ReturnType,
Access = @operator.Access,
Namespace = @class,
GetMethod = @operator
};
property.Parameters.AddRange(@operator.Parameters);
@class.Properties.Add(property);
@operator.IsGenerated = false;
}
static void HandleMissingOperatorOverloadPair(Class @class, CXXOperatorKind op1, static void HandleMissingOperatorOverloadPair(Class @class, CXXOperatorKind op1,
CXXOperatorKind op2) CXXOperatorKind op2)
@ -153,6 +175,9 @@ namespace CppSharp.Passes
case CXXOperatorKind.Pipe: case CXXOperatorKind.Pipe:
case CXXOperatorKind.Caret: case CXXOperatorKind.Caret:
// The array indexing operator can be overloaded
case CXXOperatorKind.Subscript:
// The comparison operators can be overloaded // The comparison operators can be overloaded
case CXXOperatorKind.EqualEqual: case CXXOperatorKind.EqualEqual:
case CXXOperatorKind.ExclaimEqual: case CXXOperatorKind.ExclaimEqual:
@ -180,9 +205,6 @@ namespace CppSharp.Passes
case CXXOperatorKind.LessLessEqual: case CXXOperatorKind.LessLessEqual:
case CXXOperatorKind.GreaterGreaterEqual: case CXXOperatorKind.GreaterGreaterEqual:
// The array indexing operator cannot be overloaded
case CXXOperatorKind.Subscript:
// The conditional logical operators cannot be overloaded // The conditional logical operators cannot be overloaded
case CXXOperatorKind.AmpAmp: case CXXOperatorKind.AmpAmp:
case CXXOperatorKind.PipePipe: case CXXOperatorKind.PipePipe:

7
tests/Basic/Basic.Tests.cs

@ -117,13 +117,6 @@ public class BasicTests
Assert.AreEqual(abstractFoo.pureFunction2(), 15); Assert.AreEqual(abstractFoo.pureFunction2(), 15);
} }
[Test, Ignore]
public void TestPropertyAccessModifier()
{
Assert.That(typeof(Foo2).GetProperty("P",
BindingFlags.Instance | BindingFlags.NonPublic), Is.Not.Null);
}
[Test] [Test]
public void TestANSI() public void TestANSI()
{ {

4
tests/Basic/Basic.h

@ -29,10 +29,6 @@ public:
Foo2 operator<<(signed int i); Foo2 operator<<(signed int i);
Foo2 operator<<(signed long l); Foo2 operator<<(signed long l);
// TODO: uncomment when the C++/CLI back-end supports protected members
//protected:
// int P;
}; };
struct DLL_API Bar struct DLL_API Bar

21
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -0,0 +1,21 @@
using System.Reflection;
using NUnit.Framework;
using Foo = CSharpTemp.Foo;
[TestFixture]
public class CSharpTempTests
{
[Test]
public void TestIndexer()
{
var foo = new Foo();
Assert.That(foo[0], Is.EqualTo(5));
}
[Test]
public void TestPropertyAccessModifier()
{
Assert.That(typeof(Foo).GetProperty("P",
BindingFlags.Instance | BindingFlags.NonPublic), Is.Not.Null);
}
}

12
tests/CSharpTemp/CSharpTemp.cpp

@ -0,0 +1,12 @@
#include "CSharpTemp.h"
// TODO: move this, it has nothing to do with Unicode, it's here only not to break the CLI branch
int Foo::operator[](int i) const
{
return 5;
}
int Foo::operator[](int i)
{
return 5;
}

22
tests/CSharpTemp/CSharpTemp.cs

@ -0,0 +1,22 @@
using CppSharp.Generators;
using CppSharp.Utils;
namespace CppSharp.Tests
{
public class CSharpTempTests : LibraryTest
{
public CSharpTempTests(LanguageGeneratorKind kind)
: base("CSharpTemp", kind)
{
}
static class Program
{
public static void Main(string[] args)
{
ConsoleDriver.Run(new CSharpTempTests(LanguageGeneratorKind.CSharp));
}
}
}
}

15
tests/CSharpTemp/CSharpTemp.h

@ -0,0 +1,15 @@
#if defined(_MSC_VER)
#define DLL_API __declspec(dllexport)
#else
#define DLL_API
#endif
class DLL_API Foo
{
public:
int operator[](int i) const;
int operator[](int i);
protected:
int P;
};

2
tests/CSharpTemp/premake4.lua

@ -0,0 +1,2 @@
group "Tests/CSharpTemp"
SetupTestCSharp("CSharpTemp")

8
tests/UTF16/UTF16.Tests.cs

@ -1,5 +1,6 @@
using NUnit.Framework; using System;
using UTF16; using NUnit.Framework;
using Foo = UTF16.Foo;
[TestFixture] [TestFixture]
public class UTF16Tests public class UTF16Tests
@ -11,5 +12,8 @@ public class UTF16Tests
const string georgia = "საქართველო"; const string georgia = "საქართველო";
foo.Unicode = georgia; foo.Unicode = georgia;
Assert.That(foo.Unicode, Is.EqualTo(georgia)); Assert.That(foo.Unicode, Is.EqualTo(georgia));
// TODO: move this, it has nothing to do with Unicode, it's here only not to break the CLI branch
Assert.That(foo[0], Is.EqualTo(5));
} }
} }

11
tests/UTF16/UTF16.cpp

@ -1 +1,12 @@
#include "UTF16.h" #include "UTF16.h"
// TODO: move this, it has nothing to do with Unicode, it's here only not to break the CLI branch
int Foo::operator[](int i) const
{
return 5;
}
int Foo::operator[](int i)
{
return 5;
}

4
tests/UTF16/UTF16.h

@ -8,6 +8,10 @@ class DLL_API Foo
{ {
public: public:
const char* Unicode; const char* Unicode;
// TODO: move this, it has nothing to do with Unicode, it's here only not to break the CLI branch
int operator[](int i) const;
int operator[](int i);
}; };
DLL_API int FooCallFoo(Foo* foo); DLL_API int FooCallFoo(Foo* foo);

Loading…
Cancel
Save