diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 9f14f7ad..041d4bb4 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -775,7 +775,7 @@ namespace CppSharp.Generators.CLI var fieldRef = string.Format("{0}.{1}", Context.Parameter.Name, property.Name); - var marshalCtx = new MarshalContext(Context.Context) + var marshalCtx = new MarshalContext(Context.Context, Context.Indent) { ArgName = fieldRef, ParameterIndex = Context.ParameterIndex++, diff --git a/src/Generator/Generators/CLI/CLISources.cs b/src/Generator/Generators/CLI/CLISources.cs index 76e7b098..bf1afa08 100644 --- a/src/Generator/Generators/CLI/CLISources.cs +++ b/src/Generator/Generators/CLI/CLISources.cs @@ -396,7 +396,7 @@ namespace CppSharp.Generators.CLI else variable = $"((::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}"; - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { Parameter = param, ArgName = param.Name, @@ -408,7 +408,7 @@ namespace CppSharp.Generators.CLI if (isIndexer) { - var ctx2 = new MarshalContext(Context) + var ctx2 = new MarshalContext(Context, CurrentIndent) { Parameter = indexParameter, ArgName = indexParameter.Name @@ -483,7 +483,7 @@ namespace CppSharp.Generators.CLI variable = string.Format("((::{0}*)NativePtr)->{1}", @class.QualifiedOriginalName, decl.OriginalName); - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { Declaration = decl, ArgName = decl.Name, @@ -592,7 +592,7 @@ namespace CppSharp.Generators.CLI var returns = new List(); foreach (var param in @event.Parameters) { - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { ReturnVarName = param.Name, ReturnType = param.QualifiedType @@ -686,7 +686,7 @@ namespace CppSharp.Generators.CLI var nativeField = string.Format("{0}{1}", nativeVar, property.Field.OriginalName); - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { ArgName = property.Name, ReturnVarName = nativeField, @@ -834,7 +834,7 @@ namespace CppSharp.Generators.CLI var paramIndex = 0; foreach (var param in method.Parameters) { - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { Function = method, Parameter = param, @@ -870,7 +870,7 @@ namespace CppSharp.Generators.CLI var varName = string.Format("_native.{0}", property.Field.OriginalName); - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { ReturnVarName = varName, ReturnType = property.QualifiedType @@ -946,7 +946,7 @@ namespace CppSharp.Generators.CLI WriteLine("auto {0} = ::{1}();", valueMarshalName, @class.QualifiedOriginalName); var param = new Parameter { Name = "(*this)" , Namespace = function.Namespace }; - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { MarshalVarPrefix = valueMarshalName, Parameter = param @@ -1021,7 +1021,7 @@ namespace CppSharp.Generators.CLI var nativeVarName = paramInfo.Name; - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { ArgName = nativeVarName, ReturnVarName = nativeVarName, @@ -1054,7 +1054,7 @@ namespace CppSharp.Generators.CLI isIntPtr ? "System::IntPtr()" : "nullptr"); } - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { ArgName = returnIdentifier, ReturnVarName = returnIdentifier, @@ -1167,7 +1167,7 @@ namespace CppSharp.Generators.CLI QualifiedType = new QualifiedType(paramType) }; - var ctx = new MarshalContext(Context) + var ctx = new MarshalContext(Context, CurrentIndent) { Parameter = effectiveParam, ParameterIndex = paramIndex, diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index ef759635..98714182 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Text; using CppSharp.AST; @@ -10,11 +11,13 @@ namespace CppSharp.Generators.CSharp { public class CSharpMarshalContext : MarshalContext { - public CSharpMarshalContext(BindingContext context) - : base(context) + public CSharpMarshalContext(BindingContext context, Stack indent) + : base(context, indent) { ArgumentPrefix = new TextGenerator(); + indent.PushTo(ArgumentPrefix.CurrentIndent); Cleanup = new TextGenerator(); + indent.PushTo(Cleanup.CurrentIndent); } public TextGenerator ArgumentPrefix { get; private set; } @@ -335,7 +338,7 @@ namespace CppSharp.Generators.CSharp if (parameter.Usage == ParameterUsage.Unknown || parameter.IsIn) return base.VisitParameterDecl(parameter); - var ctx = new CSharpMarshalContext(Context.Context) + var ctx = new CSharpMarshalContext(Context.Context, Context.Indent) { ReturnType = Context.ReturnType, ReturnVarName = Context.ReturnVarName diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index 49046628..ac60b9ef 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -820,7 +820,7 @@ namespace CppSharp.Generators.CSharp QualifiedType = var.QualifiedType }; - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { Parameter = param, ArgName = param.Name, @@ -880,38 +880,40 @@ namespace CppSharp.Generators.CSharp private void GenerateFieldSetter(Field field, Class @class, QualifiedType fieldType) { + string returnVar; + Type type = field.Type.Desugar(); + var arrayType = type as ArrayType; + if (arrayType != null && @class.IsValueType) + { + returnVar = HandleValueArray(arrayType, field); + } + else + { + var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; + var identifier = SafeIdentifier(name); + if (@class.IsValueType) + returnVar = $"{Helpers.InstanceField}.{identifier}"; + else + returnVar = $"(({TypePrinter.PrintNative(@class)}*){Helpers.InstanceIdentifier})->{identifier}"; + } + var param = new Parameter { Name = "value", QualifiedType = field.QualifiedType }; - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { Parameter = param, ArgName = param.Name, + ReturnVarName = returnVar }; ctx.PushMarshalKind(MarshalKind.NativeField); var marshal = new CSharpMarshalManagedToNativePrinter(ctx); ctx.Declaration = field; - Type type = field.Type.Desugar(); - var arrayType = type as ArrayType; - - if (arrayType != null && @class.IsValueType) - { - ctx.ReturnVarName = HandleValueArray(arrayType, field); - } - else - { - var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; - var identifier = SafeIdentifier(name); - if (@class.IsValueType) - ctx.ReturnVarName = $"{Helpers.InstanceField}.{identifier}"; - else - ctx.ReturnVarName = $"(({TypePrinter.PrintNative(@class)}*){Helpers.InstanceIdentifier})->{identifier}"; - } param.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) @@ -987,7 +989,7 @@ namespace CppSharp.Generators.CSharp function.OriginalReturnType.Type.IsPointerTo(out type); var @internal = TypePrinter.PrintNative(function.Namespace); - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { Parameter = new Parameter { @@ -1108,7 +1110,7 @@ namespace CppSharp.Generators.CSharp TypePrinter.PopContext(); - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { ArgName = var.Name, ReturnType = new QualifiedType(var.Type) @@ -1171,12 +1173,18 @@ namespace CppSharp.Generators.CSharp private void GenerateFieldGetter(Field field, Class @class, QualifiedType returnType) { var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; - String returnVar; + string returnVar; + var arrayType = field.Type.Desugar() as ArrayType; if (@class.IsValueType) - returnVar = $@"{Helpers.InstanceField}.{SafeIdentifier(name)}"; + { + if (arrayType != null) + returnVar = HandleValueArray(arrayType, field); + else + returnVar = $"{Helpers.InstanceField}.{SafeIdentifier(name)}"; + } else { - returnVar = $@"(({TypePrinter.PrintNative(@class)}*) {Helpers.InstanceIdentifier})->{SafeIdentifier(name)}"; + returnVar = $"(({TypePrinter.PrintNative(@class)}*) {Helpers.InstanceIdentifier})->{SafeIdentifier(name)}"; // Class field getter should return a reference object instead of a copy. Wrapping `returnVar` in // IntPtr ensures that non-copying object constructor is invoked. Class typeClass; @@ -1185,7 +1193,7 @@ namespace CppSharp.Generators.CSharp returnVar = $"new {CSharpTypePrinter.IntPtrType}(&{returnVar})"; } - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { ArgName = field.Name, Declaration = field, @@ -1194,11 +1202,6 @@ namespace CppSharp.Generators.CSharp }; ctx.PushMarshalKind(MarshalKind.NativeField); - var arrayType = field.Type.Desugar() as ArrayType; - - if (arrayType != null && @class.IsValueType) - ctx.ReturnVarName = HandleValueArray(arrayType, field); - var marshal = new CSharpMarshalNativeToManagedPrinter(ctx); field.QualifiedType.Visit(marshal); @@ -1666,7 +1669,7 @@ namespace CppSharp.Generators.CSharp if (param.Kind == ParameterKind.IndirectReturnType) continue; - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { ReturnType = param.QualifiedType, ReturnVarName = param.Name, @@ -1723,7 +1726,7 @@ namespace CppSharp.Generators.CSharp }; // Marshal the managed result to native - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { ArgName = Helpers.ReturnIdentifier, Parameter = param, @@ -1901,7 +1904,7 @@ namespace CppSharp.Generators.CSharp var returns = new List(); foreach (var param in @event.Parameters) { - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { ReturnVarName = param.Name, ReturnType = param.QualifiedType @@ -2853,7 +2856,7 @@ namespace CppSharp.Generators.CSharp if (needsReturn) { - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { ArgName = Helpers.ReturnIdentifier, ReturnVarName = Helpers.ReturnIdentifier, @@ -2944,7 +2947,7 @@ namespace CppSharp.Generators.CSharp var nativeVarName = paramInfo.Name; - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { Parameter = param, ArgName = nativeVarName, @@ -3012,7 +3015,7 @@ namespace CppSharp.Generators.CSharp } } - var ctx = new CSharpMarshalContext(Context) + var ctx = new CSharpMarshalContext(Context, CurrentIndent) { Parameter = param, ParameterIndex = paramIndex, diff --git a/src/Generator/Generators/Marshal.cs b/src/Generator/Generators/Marshal.cs index 7eda5902..649fe4cf 100644 --- a/src/Generator/Generators/Marshal.cs +++ b/src/Generator/Generators/Marshal.cs @@ -1,23 +1,27 @@ using CppSharp.AST; +using System.Collections.Generic; namespace CppSharp.Generators { public class MarshalContext : TypePrinter { - public MarshalContext(BindingContext context) + public MarshalContext(BindingContext context, Stack indent) { Context = context; Before = new TextGenerator(); + indent.PushTo(Before.CurrentIndent); Return = new TextGenerator(); + indent.PushTo(Return.CurrentIndent); MarshalVarPrefix = string.Empty; + this.Indent = indent; } - public BindingContext Context { get; private set; } + public BindingContext Context { get; } public MarshalPrinter MarshalToNative; - public TextGenerator Before { get; private set; } - public TextGenerator Return { get; private set; } + public TextGenerator Before { get; } + public TextGenerator Return { get; } public string ReturnVarName { get; set; } public QualifiedType ReturnType { get; set; } @@ -27,11 +31,12 @@ namespace CppSharp.Generators public Function Function { get; set; } public string MarshalVarPrefix { get; set; } + public Stack Indent { get; } } public abstract class MarshalPrinter : AstVisitor where T : MarshalContext { - public T Context { get; private set; } + public T Context { get; } protected MarshalPrinter(T ctx) { diff --git a/src/Generator/Types/Std/Stdlib.cs b/src/Generator/Types/Std/Stdlib.cs index 5f82d1b3..a241c9a1 100644 --- a/src/Generator/Types/Std/Stdlib.cs +++ b/src/Generator/Types/Std/Stdlib.cs @@ -235,7 +235,7 @@ namespace CppSharp.Types.Std QualifiedType = type }; - var elementCtx = new MarshalContext(ctx.Context) + var elementCtx = new MarshalContext(ctx.Context, ctx.Indent) { Parameter = param, ArgName = param.Name, @@ -280,7 +280,7 @@ namespace CppSharp.Types.Std ctx.ReturnVarName); ctx.Before.WriteStartBraceIndent(); { - var elementCtx = new MarshalContext(ctx.Context) + var elementCtx = new MarshalContext(ctx.Context, ctx.Indent) { ReturnVarName = "_element", ReturnType = type diff --git a/src/Generator/Utils/BlockGenerator.cs b/src/Generator/Utils/BlockGenerator.cs index 041c7499..511b66a9 100644 --- a/src/Generator/Utils/BlockGenerator.cs +++ b/src/Generator/Utils/BlockGenerator.cs @@ -176,8 +176,6 @@ namespace CppSharp #region ITextGenerator implementation - public uint Indent { get { return Text.Indent; } } - public void Write(string msg, params object[] args) { Text.Write(msg, args); @@ -240,8 +238,9 @@ namespace CppSharp public abstract class BlockGenerator : ITextGenerator { - public Block RootBlock { get; private set; } + public Block RootBlock { get; } public Block ActiveBlock { get; private set; } + public Stack CurrentIndent => ActiveBlock.Text.CurrentIndent; protected BlockGenerator() { @@ -264,12 +263,7 @@ namespace CppSharp public void PushBlock(BlockKind kind = BlockKind.Unknown, object obj = null) { var block = new Block { Kind = kind, Object = obj }; - var array = new uint[ActiveBlock.Text.CurrentIndent.Count]; - ActiveBlock.Text.CurrentIndent.CopyTo(array, 0); - foreach (var indent in array.Reverse()) - { - block.Text.CurrentIndent.Push(indent); - } + CurrentIndent.PushTo(block.Text.CurrentIndent); block.Text.IsStartOfLine = ActiveBlock.Text.IsStartOfLine; block.Text.NeedsNewLine = ActiveBlock.Text.NeedsNewLine; PushBlock(block); @@ -306,8 +300,6 @@ namespace CppSharp #region ITextGenerator implementation - public uint Indent { get { return ActiveBlock.Indent; } } - public void Write(string msg, params object[] args) { ActiveBlock.Write(msg, args); diff --git a/src/Generator/Utils/TextGenerator.cs b/src/Generator/Utils/TextGenerator.cs index 308849a7..faf3c6da 100644 --- a/src/Generator/Utils/TextGenerator.cs +++ b/src/Generator/Utils/TextGenerator.cs @@ -7,7 +7,6 @@ namespace CppSharp { public interface ITextGenerator { - uint Indent { get; } void Write(string msg, params object[] args); void WriteLine(string msg, params object[] args); void WriteLineIndent(string msg, params object[] args); @@ -30,11 +29,6 @@ namespace CppSharp public bool NeedsNewLine { get; set; } public Stack CurrentIndent { get; } = new Stack(); - public uint Indent - { - get { return (uint)CurrentIndent.Sum(u => (int)u); } - } - public TextGenerator() { } @@ -60,16 +54,13 @@ namespace CppSharp if (args.Length > 0) msg = string.Format(msg, args); - foreach(var line in msg.SplitAndKeep(Environment.NewLine)) - { - if (IsStartOfLine && !string.IsNullOrWhiteSpace(line)) - StringBuilder.Append(new string(' ', (int) CurrentIndent.Sum(u => u))); + if (IsStartOfLine && !string.IsNullOrWhiteSpace(msg)) + StringBuilder.Append(new string(' ', (int) CurrentIndent.Sum(u => u))); - if (line.Length > 0) - IsStartOfLine = line.EndsWith(Environment.NewLine); + if (msg.Length > 0) + IsStartOfLine = msg.EndsWith(Environment.NewLine); - StringBuilder.Append(line); - } + StringBuilder.Append(msg); } public void WriteLine(string msg, params object[] args) diff --git a/src/Generator/Utils/Utils.cs b/src/Generator/Utils/Utils.cs index b8f8ed17..a651a58a 100644 --- a/src/Generator/Utils/Utils.cs +++ b/src/Generator/Utils/Utils.cs @@ -49,13 +49,6 @@ namespace CppSharp return str.Trim().Split(); } - public static IEnumerable SplitAndKeep(this string s, string seperator) - { - string[] obj = s.Split(new[] { seperator }, StringSplitOptions.None); - - return obj.Select((t, i) => i == obj.Length - 1 ? t : t + seperator); - } - public static string Capitalize(string s) { // Check for empty string. @@ -134,6 +127,18 @@ namespace CppSharp return uri1.MakeRelativeUri(uri2).ToString(); } - + } + + public static class CollectionExtensions + { + public static void PushTo(this Stack source, Stack destination) + { + var array = new T[source.Count]; + source.CopyTo(array, 0); + foreach (var indent in array.Reverse()) + { + destination.Push(indent); + } + } } }