From 54c93f4d91234b3522c69db1b8489f493d3fe25d Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Fri, 13 Sep 2013 19:22:11 +0300 Subject: [PATCH] Added support for read-only [] operators. Signed-off-by: Dimitar Dobrev --- src/AST/Property.cs | 12 ++++ .../Generators/CSharp/CSharpTextTemplate.cs | 37 +++++------- .../Passes/CheckOperatorsOverloads.cs | 60 +++++++++++++------ 3 files changed, 71 insertions(+), 38 deletions(-) diff --git a/src/AST/Property.cs b/src/AST/Property.cs index 0514d111..b3394aa8 100644 --- a/src/AST/Property.cs +++ b/src/AST/Property.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace CppSharp.AST { /// @@ -36,6 +38,16 @@ namespace CppSharp.AST // The field that should be get and set by this property public Field Field { get; set; } + private readonly List parameters = new List(); + + /// + /// Only applicable to index ([]) properties. + /// + public List Parameters + { + get { return parameters; } + } + public override T Visit(IDeclVisitor visitor) { return visitor.VisitProperty(this); diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 7a2588e0..e40f902e 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -893,14 +893,12 @@ namespace CppSharp.Generators.CSharp 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); WriteLine("{0} {1} {2}", prop.Access == AccessSpecifier.Public ? "public" : "protected", - prop.Type, SafeIdentifier(prop.Name)); + prop.Type, GetPropertyName(prop)); WriteStartBraceIndent(); 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) { PushBlock(CSharpBlockKind.Variable); @@ -1469,7 +1473,7 @@ namespace CppSharp.Generators.CSharp var functionName = GetFunctionIdentifier(function); Write("public static {0} {1}(", function.OriginalReturnType, functionName); - GenerateMethodParameters(function); + Write(FormatMethodParameters(function.Parameters)); WriteLine(")"); WriteStartBraceIndent(); @@ -1517,7 +1521,7 @@ namespace CppSharp.Generators.CSharp else Write("{0} {1}(", method.OriginalReturnType, functionName); - GenerateMethodParameters(method); + Write(FormatMethodParameters(method.Parameters)); Write(")"); @@ -1938,23 +1942,14 @@ namespace CppSharp.Generators.CSharp } } - private void GenerateMethodParameters(Function function) + private string FormatMethodParameters(IEnumerable @params) { - var @params = new List(); - - for (var i = 0; i < function.Parameters.Count; ++i) - { - var param = function.Parameters[i]; - - if (param.Kind == ParameterKind.IndirectReturnType) - continue; - - var typeName = param.CSharpType(TypePrinter); - @params.Add(string.Format("{0}{1} {2}", GetParameterUsage(param.Usage), + return string.Join(", ", + from param in @params + where param.Kind != ParameterKind.IndirectReturnType + let typeName = param.CSharpType(this.TypePrinter) + select string.Format("{0}{1} {2}", GetParameterUsage(param.Usage), typeName, SafeIdentifier(param.Name))); - } - - Write(string.Join(", ", @params)); } #endregion diff --git a/src/Generator/Passes/CheckOperatorsOverloads.cs b/src/Generator/Passes/CheckOperatorsOverloads.cs index 0e75f235..96769a05 100644 --- a/src/Generator/Passes/CheckOperatorsOverloads.cs +++ b/src/Generator/Passes/CheckOperatorsOverloads.cs @@ -57,22 +57,48 @@ namespace CppSharp.Passes if (@operator.SynthKind == FunctionSynthKind.NonMemberOperator) continue; - // Handle missing operator parameters - if (@operator.IsStatic) - @operator.Parameters = @operator.Parameters.Skip(1).ToList(); - - var type = new PointerType() + if (@operator.OperatorKind == CXXOperatorKind.Subscript) { - QualifiedPointee = new QualifiedType(new TagType(@class)), - Modifier = PointerType.TypeModifier.LVReference - }; - - @operator.Parameters.Insert(0, new Parameter + CreateIndexer(@class, @operator); + } + else { - Name = Generator.GeneratedIdentifier("op"), - QualifiedType = new QualifiedType(type), - Kind = ParameterKind.OperatorParameter - }); + // Handle missing operator parameters + if (@operator.IsStatic) + @operator.Parameters = @operator.Parameters.Skip(1).ToList(); + + var type = new PointerType() + { + QualifiedPointee = new QualifiedType(new TagType(@class)), + Modifier = PointerType.TypeModifier.LVReference + }; + + @operator.Parameters.Insert(0, new Parameter + { + Name = Generator.GeneratedIdentifier("op"), + QualifiedType = new QualifiedType(type), + Kind = ParameterKind.OperatorParameter + }); + } + } + } + + private static void CreateIndexer(Class @class, Method @operator) + { + if (@class.Properties.All(p => p.Parameters.Count == 0 || + p.Parameters[0].QualifiedType != @operator.Parameters[0].QualifiedType)) + { + Property property = new Property + { + Name = "Item", + QualifiedType = @operator.ReturnType, + Access = @operator.Access, + Namespace = @class + }; + property.GetMethod = @operator; + property.Parameters.AddRange(@operator.Parameters); + @class.Properties.Add(property); + @operator.IsGenerated = false; } } @@ -153,6 +179,9 @@ namespace CppSharp.Passes case CXXOperatorKind.Pipe: case CXXOperatorKind.Caret: + // The array indexing operator can be overloaded + case CXXOperatorKind.Subscript: + // The comparison operators can be overloaded case CXXOperatorKind.EqualEqual: case CXXOperatorKind.ExclaimEqual: @@ -180,9 +209,6 @@ namespace CppSharp.Passes case CXXOperatorKind.LessLessEqual: case CXXOperatorKind.GreaterGreaterEqual: - // The array indexing operator cannot be overloaded - case CXXOperatorKind.Subscript: - // The conditional logical operators cannot be overloaded case CXXOperatorKind.AmpAmp: case CXXOperatorKind.PipePipe: