From cf7813d8d6dbb5855c8b643bdc569f2c906805e6 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Tue, 14 Feb 2017 03:00:39 +0200 Subject: [PATCH] Moved the C# generation of internal names of template specialisations to the C# type printer. Signed-off-by: Dimitar Dobrev --- src/AST/ASTVisitor.cs | 5 + .../Generators/CSharp/CSharpMarshal.cs | 57 ++++-- .../Generators/CSharp/CSharpSources.cs | 177 +++++++++--------- .../Generators/CSharp/CSharpTypePrinter.cs | 18 +- 4 files changed, 144 insertions(+), 113 deletions(-) diff --git a/src/AST/ASTVisitor.cs b/src/AST/ASTVisitor.cs index c6082653..9a38ac21 100644 --- a/src/AST/ASTVisitor.cs +++ b/src/AST/ASTVisitor.cs @@ -22,6 +22,7 @@ namespace CppSharp.AST public bool VisitClassFields = true; public bool VisitClassProperties = true; public bool VisitClassMethods = true; + public bool VisitClassTemplateSpecializations { get; set; } = true; public bool VisitNamespaceEnums = true; public bool VisitNamespaceTemplates = true; @@ -325,6 +326,10 @@ namespace CppSharp.AST VisitMethodDecl(method); } + if (@class.IsDependent && VisitOptions.VisitClassTemplateSpecializations) + foreach (var specialization in @class.Specializations) + VisitClassTemplateSpecializationDecl(specialization); + return true; } diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 4b1a1438..9477380a 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -331,6 +331,12 @@ namespace CppSharp.Generators.CSharp return true; } + public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals) + { + Context.Return.Write("({0}) (object) ", param.ReplacedParameter.Parameter.Name); + return base.VisitTemplateParameterSubstitutionType(param, quals); + } + private string HandleReturnedPointer(Class @class, string qualifiedClass) { var originalClass = @class.OriginalClass ?? @class; @@ -495,22 +501,34 @@ namespace CppSharp.Generators.CSharp if (!VisitType(pointer, quals)) return false; + var pointee = pointer.Pointee.Desugar(); if (Context.Function != null && pointer.IsPrimitiveTypeConvertibleToRef() && Context.Kind != CSharpMarshalKind.VTableReturnValue) { var refParamPtr = string.Format("__refParamPtr{0}", Context.ParameterIndex); - Context.SupportBefore.WriteLine("fixed ({0} {1} = &{2})", - pointer, refParamPtr, Context.Parameter.Name); - Context.HasCodeBlock = true; - Context.SupportBefore.WriteStartBraceIndent(); - Context.Return.Write(refParamPtr); + var templateSubstitution = pointer.Pointee as TemplateParameterSubstitutionType; + if (templateSubstitution != null) + { + var castParam = $"__{Context.Parameter.Name}{Context.ParameterIndex}"; + Context.SupportBefore.WriteLine( + $"var {castParam} = ({templateSubstitution}) (object) {Context.Parameter.Name};"); + Context.SupportBefore.WriteLine($"{pointer} {refParamPtr} = &{castParam};"); + Context.Return.Write(refParamPtr); + } + else + { + Context.SupportBefore.WriteLine( + $"fixed ({pointer} {refParamPtr} = &{Context.Parameter.Name})"); + Context.HasCodeBlock = true; + Context.SupportBefore.WriteStartBraceIndent(); + Context.Return.Write(refParamPtr); + } return true; } var param = Context.Parameter; var isRefParam = param != null && (param.IsInOut || param.IsOut); - var pointee = pointer.Pointee.Desugar(); if (CSharpTypePrinter.IsConstCharString(pointee) && isRefParam) { if (param.IsOut) @@ -668,6 +686,15 @@ namespace CppSharp.Generators.CSharp return decl.Type.Visit(this); } + public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals) + { + var replacement = param.Replacement.Type.Desugar(); + Class @class; + Context.Return.Write($@"{(replacement.TryGetClass(out @class) ? + string.Empty : $"({replacement}) (object) ")}"); + return base.VisitTemplateParameterSubstitutionType(param, quals); + } + public override bool VisitTemplateParameterType(TemplateParameterType param, TypeQualifiers quals) { Context.Return.Write(param.Parameter.Name); @@ -706,12 +733,17 @@ namespace CppSharp.Generators.CSharp Type type = Context.Parameter.Type.Desugar(); string paramInstance; Class @interface; - if ((type.GetFinalPointee() ?? type).TryGetClass(out @interface) && + var finalType = type.GetFinalPointee() ?? type; + var templateType = finalType as TemplateParameterSubstitutionType; + if (finalType.TryGetClass(out @interface) && @interface.IsInterface) paramInstance = string.Format("{0}.__PointerTo{1}", param, @interface.OriginalClass.Name); else - paramInstance = string.Format("{0}.{1}", param, Helpers.InstanceIdentifier); + paramInstance = $@"{ + (templateType != null ? $"(({@class.Visit(typePrinter)}) (object) " : string.Empty)}{ + param}{(templateType != null ? ")" : string.Empty) + }.{Helpers.InstanceIdentifier}"; if (type.IsAddress()) { Class decl; @@ -747,11 +779,12 @@ namespace CppSharp.Generators.CSharp } var realClass = @class.OriginalClass ?? @class; - var qualifiedIdentifier = realClass.Visit(this.typePrinter); + typePrinter.PushContext(CSharpTypePrinterContextKind.Native); + var qualifiedIdentifier = realClass.Visit(typePrinter); + typePrinter.PopContext(); Context.Return.Write( - "ReferenceEquals({0}, null) ? new {1}.{2}{3}() : *({1}.{2}{3}*) {4}", - param, qualifiedIdentifier, Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class), paramInstance); + "ReferenceEquals({0}, null) ? new {1}() : *({1}*) {2}", + param, qualifiedIdentifier, paramInstance); } private void MarshalValueClass() diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index 0225ecd7..ae9415b8 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -448,7 +448,8 @@ namespace CppSharp.Generators.CSharp System.Type typeMap = null; string key = string.Empty; - foreach (var name in new[] { @class.OriginalName, @class.QualifiedOriginalName }) + var cppTypePrinter = new CppTypePrinter { PrintScopeKind = CppTypePrintScopeKind.Qualified }; + foreach (var name in new[] { @class.OriginalName, @class.Visit(cppTypePrinter) }) { if (Context.TypeMaps.TypeMaps.ContainsKey(name)) { @@ -502,7 +503,7 @@ namespace CppSharp.Generators.CSharp // use interfaces if any - derived types with a secondary base this class must be compatible with the map var @interface = @class.Namespace.Classes.Find(c => c.OriginalClass == @class); var dict = string.Format("global::System.Collections.Concurrent.ConcurrentDictionary", - @interface != null ? @interface.Name : @class.Name); + (@interface ?? @class).Visit(TypePrinter)); WriteLine("internal static readonly {0} NativeToManagedMap = new {0}();", dict); WriteLine("protected void*[] __OriginalVTables;"); } @@ -695,9 +696,8 @@ namespace CppSharp.Generators.CSharp if (@class != null && @class.NeedsBase && !@class.BaseClass.IsInterface & !isSpecialization) Write("new "); - var suffix = Helpers.GetSuffixForInternal(@class); - WriteLine("{0}partial struct {1}{2}", - isSpecialization ? "unsafe " : string.Empty, Helpers.InternalStruct, suffix); + WriteLine($@"{(isSpecialization ? "unsafe " : string.Empty)}partial struct { + Helpers.InternalStruct}{Helpers.GetSuffixForInternal(@class)}"); } public static bool ShouldGenerateClassNativeField(Class @class) @@ -884,18 +884,12 @@ namespace CppSharp.Generators.CSharp if (method != null && method.OperatorKind == CXXOperatorKind.Subscript) { if (method.OperatorKind == CXXOperatorKind.Subscript) - { GenerateIndexerSetter(method); - } else - { GenerateInternalFunctionCall(function, new List { param }); - } } else - { GenerateInternalFunctionCall(function, new List { param }); - } } } else if (decl is Field) @@ -920,13 +914,11 @@ namespace CppSharp.Generators.CSharp else { var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; - ctx.ReturnVarName = string.Format("{0}{1}{2}", - @class.IsValueType - ? Helpers.InstanceField - : string.Format("(({0}{1}*) {2})", Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class), Helpers.InstanceIdentifier), - @class.IsValueType ? "." : "->", - Helpers.SafeIdentifier(name)); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + ctx.ReturnVarName = $@"{(@class.IsValueType ? Helpers.InstanceField : + $"(({@class.Visit(TypePrinter)}*) {Helpers.InstanceIdentifier})")}{ + (@class.IsValueType ? "." : "->")}{Helpers.SafeIdentifier(name)}"; + TypePrinter.PopContext(); } param.Visit(marshal); @@ -1047,11 +1039,12 @@ namespace CppSharp.Generators.CSharp function.Type.IsPointerTo(out type); PrimitiveType primitiveType; var internalFunction = GetFunctionNativeIdentifier(function); + var @internal = $@"{Helpers.InternalStruct}{ + Helpers.GetSuffixForInternal(function.Namespace)}"; if (type.IsPrimitiveType(out primitiveType)) { - WriteLine("*{0}{1}.{2}({3}, {4}) = value;", - Helpers.InternalStruct, Helpers.GetSuffixForInternal(function.Namespace), - internalFunction, GetInstanceParam(function), function.Parameters[0].Name); + WriteLine($@"*{@internal}.{internalFunction}({ + GetInstanceParam(function)}, {function.Parameters[0].Name}) = value;"); } else { @@ -1059,14 +1052,13 @@ namespace CppSharp.Generators.CSharp Class @class; var isValueType = (type.GetFinalPointee() ?? type).TryGetClass(out @class) && @class.IsValueType; - var paramMarshal = GenerateFunctionParamMarshal(function.Parameters[0], 0, function); - var suffix = Helpers.GetSuffixForInternal(function.Namespace); - WriteLine("*({0}.{1}{2}*) {1}{2}.{3}({4}, {5}) = {6}value.{7};", - typeString, Helpers.InternalStruct, suffix, internalFunction, GetInstanceParam(function), - paramMarshal.Context == null ? paramMarshal.Name : paramMarshal.Context.Return, - isValueType ? string.Empty : - string.Format("*({0}.{1}{2}*) ", typeString, Helpers.InternalStruct, suffix), - Helpers.InstanceIdentifier); + var paramMarshal = GenerateFunctionParamMarshal( + function.Parameters[0], 0, function); + WriteLine($@"*({typeString}.{@internal}*) {@internal}.{internalFunction}({ + GetInstanceParam(function)}, {(paramMarshal.Context == null ? + paramMarshal.Name : paramMarshal.Context.Return)}) = { + (isValueType ? string.Empty : $@"*({typeString}.{@internal}*) ")}value.{ + Helpers.InstanceIdentifier};"); } } @@ -1121,20 +1113,18 @@ namespace CppSharp.Generators.CSharp WriteStartBraceIndent(); var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); var ctx = new CSharpMarshalContext(Context) { Kind = CSharpMarshalKind.NativeField, ArgName = decl.Name, Declaration = decl, - ReturnVarName = string.Format("{0}{1}{2}", - @class.IsValueType - ? Helpers.InstanceField - : string.Format("(({0}{1}*) {2})", Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class), Helpers.InstanceIdentifier), - @class.IsValueType ? "." : "->", - Helpers.SafeIdentifier(name)), + ReturnVarName = $@"{(@class.IsValueType ? Helpers.InstanceField : + $"(({@class.Visit(TypePrinter)}*) {Helpers.InstanceIdentifier})")}{ + (@class.IsValueType ? "." : "->")}{Helpers.SafeIdentifier(name)}", ReturnType = decl.QualifiedType }; + TypePrinter.PopContext(); var arrayType = field.Type as ArrayType; @@ -1459,8 +1449,9 @@ namespace CppSharp.Generators.CSharp WriteLine("if (__OriginalVTables != null)"); WriteLineIndent("return;"); - WriteLine("var native = ({0}{1}*) {2}.ToPointer();", Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class), Helpers.InstanceIdentifier); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + WriteLine($"var native = ({@class.Visit(TypePrinter)}*) {Helpers.InstanceIdentifier}.ToPointer();"); + TypePrinter.PopContext(); NewLine(); SaveOriginalVTablePointers(@class); @@ -1532,8 +1523,8 @@ namespace CppSharp.Generators.CSharp private void SaveOriginalVTablePointers(Class @class, bool cast = false) { - var pointer = cast ? $@"(({Helpers.InternalStruct}{ - Helpers.GetSuffixForInternal(@class)}*) native)" : "native"; + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + var pointer = cast ? $@"(({@class.Visit(TypePrinter)}*) native)" : "native"; if (Context.ParserOptions.IsMicrosoftAbi) WriteLine("__OriginalVTables = new void*[] {{ {0} }};", string.Join(", ", @@ -1543,6 +1534,7 @@ namespace CppSharp.Generators.CSharp WriteLine( $@"__OriginalVTables = new void*[] {{ {pointer}->{ @class.Layout.VTablePointers[0].Name}.ToPointer() }};"); + TypePrinter.PopContext(); } private void AllocateNewVTablesMS(Class @class, IList wrappedEntries, @@ -1770,7 +1762,7 @@ namespace CppSharp.Generators.CSharp WriteLineIndent("throw new global::System.Exception(\"No managed instance was found\");"); NewLine(); - WriteLine("var {0} = ({1}) NativeToManagedMap[instance];", Helpers.TargetIdentifier, @class.Name); + WriteLine("var {0} = ({1}) NativeToManagedMap[instance];", Helpers.TargetIdentifier, @class.Visit(TypePrinter)); WriteLine("if ({0}.{1})", Helpers.TargetIdentifier, Helpers.OwnsNativeInstanceIdentifier); WriteLineIndent("{0}.SetupVTables();", Helpers.TargetIdentifier); GenerateVTableManagedCall(method); @@ -1988,18 +1980,18 @@ namespace CppSharp.Generators.CSharp Helpers.DummyIdentifier); WriteLine("NativeToManagedMap.TryRemove({0}, out {1});", Helpers.InstanceIdentifier, Helpers.DummyIdentifier); - var suffix = Helpers.GetSuffixForInternal(@class); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + var classInternal = @class.Visit(TypePrinter); + TypePrinter.PopContext(); if (@class.IsDynamic && GetUniqueVTableMethodEntries(@class).Count != 0) { if (Context.ParserOptions.IsMicrosoftAbi) for (var i = 0; i < @class.Layout.VTablePointers.Count; i++) - WriteLine("(({0}{1}*) {2})->{3} = new global::System.IntPtr(__OriginalVTables[{4}]);", - Helpers.InternalStruct, suffix, Helpers.InstanceIdentifier, - @class.Layout.VTablePointers[i].Name, i); + WriteLine($@"(({classInternal}*) {Helpers.InstanceIdentifier})->{ + @class.Layout.VTablePointers[i].Name} = new global::System.IntPtr(__OriginalVTables[{i}]);"); else - WriteLine("(({0}{1}*) {2})->{3} = new global::System.IntPtr(__OriginalVTables[0]);", - Helpers.InternalStruct, suffix, Helpers.InstanceIdentifier, - @class.Layout.VTablePointers[0].Name); + WriteLine($@"(({classInternal}*) {Helpers.InstanceIdentifier})->{ + @class.Layout.VTablePointers[0].Name} = new global::System.IntPtr(__OriginalVTables[0]);"); } } @@ -2060,14 +2052,14 @@ namespace CppSharp.Generators.CSharp PushBlock(CSharpBlockKind.Method); WriteLine("internal static {0}{1} {2}(global::System.IntPtr native, bool skipVTables = false)", @class.NeedsBase && !@class.BaseClass.IsInterface ? "new " : string.Empty, - @class.Name, Helpers.CreateInstanceIdentifier); + @class.Visit(TypePrinter), Helpers.CreateInstanceIdentifier); WriteStartBraceIndent(); WriteLine("return new {0}(native.ToPointer(), skipVTables);", ctorCall); WriteCloseBraceIndent(); PopBlock(NewLineKind.BeforeNextBlock); } - GenerateNativeConstructorByValue(@class, className, ctorCall); + GenerateNativeConstructorByValue(@class, ctorCall); PushBlock(CSharpBlockKind.Method); WriteLine("{0} {1}(void* native, bool skipVTables = false){2}", @@ -2115,35 +2107,36 @@ namespace CppSharp.Generators.CSharp } else { - WriteLine("{0} = *({1}{2}*) native;", Helpers.InstanceField, - Helpers.InternalStruct, Helpers.GetSuffixForInternal(@class)); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + WriteLine($"{Helpers.InstanceField} = *({@class.Visit(TypePrinter)}*) native;"); + TypePrinter.PopContext(); } WriteCloseBraceIndent(); PopBlock(NewLineKind.BeforeNextBlock); } - private void GenerateNativeConstructorByValue(Class @class, string className, string ctorCall) + private void GenerateNativeConstructorByValue(Class @class, string ctorCall) { - var internalSuffix = Helpers.GetSuffixForInternal(@class); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + var @internal = (@class.IsAbstractImpl ? @class.BaseClass : @class).Visit(TypePrinter); + TypePrinter.PopContext(); if (!@class.IsAbstractImpl) { PushBlock(CSharpBlockKind.Method); - WriteLine("internal static {0} {1}({0}.{2}{3} native, bool skipVTables = false)", - className, Helpers.CreateInstanceIdentifier, - Helpers.InternalStruct, internalSuffix); + WriteLine("internal static {0} {1}({2} native, bool skipVTables = false)", + @class.Visit(TypePrinter), Helpers.CreateInstanceIdentifier, @internal); WriteStartBraceIndent(); WriteLine("return new {0}(native, skipVTables);", ctorCall); WriteCloseBraceIndent(); - PopBlock(NewLineKind.BeforeNextBlock); + PopBlock(NewLineKind.BeforeNextBlock); } if (@class.IsRefType && !@class.IsAbstract) { PushBlock(CSharpBlockKind.Method); - WriteLine("private static void* __CopyValue({0}.{1}{2} native)", - className, Helpers.InternalStruct, internalSuffix); + WriteLine("private static void* __CopyValue({0} native)", @internal); WriteStartBraceIndent(); var copyCtorMethod = @class.Methods.FirstOrDefault(method => method.IsCopyConstructor); @@ -2152,18 +2145,17 @@ namespace CppSharp.Generators.CSharp { // Allocate memory for a new native object and call the ctor. WriteLine("var ret = Marshal.AllocHGlobal({0});", @class.Layout.Size); - WriteLine("{0}.{1}{2}.{3}(ret, new global::System.IntPtr(&native));", - @class.Visit(TypePrinter), Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class), + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + WriteLine($"{@class.Visit(TypePrinter)}.{GetFunctionNativeIdentifier(copyCtorMethod)}(ret, new global::System.IntPtr(&native));", + @class.Visit(TypePrinter), GetFunctionNativeIdentifier(copyCtorMethod)); - WriteLine("return ret.ToPointer();", className); + TypePrinter.PopContext(); + WriteLine("return ret.ToPointer();"); } else { - WriteLine("var ret = Marshal.AllocHGlobal({1});", - className, @class.Layout.Size); - WriteLine("*({0}.{1}{2}*) ret = native;", className, - Helpers.InternalStruct, Helpers.GetSuffixForInternal(@class)); + WriteLine("var ret = Marshal.AllocHGlobal({0});", @class.Layout.Size); + WriteLine("*({0}*) ret = native;", @internal); WriteLine("return ret.ToPointer();"); } WriteCloseBraceIndent(); @@ -2172,9 +2164,8 @@ namespace CppSharp.Generators.CSharp if (!@class.IsAbstract) { PushBlock(CSharpBlockKind.Method); - WriteLine("{0} {1}({2}.{3}{4} native, bool skipVTables = false)", - @class.IsAbstractImpl ? "internal" : "private", - @class.Name, className, Helpers.InternalStruct, internalSuffix); + WriteLine("{0} {1}({2} native, bool skipVTables = false)", + @class.IsAbstractImpl ? "internal" : "private", @class.Name, @internal); WriteLineIndent(@class.IsRefType ? ": this(__CopyValue(native), skipVTables)" : ": this()"); WriteStartBraceIndent(); if (@class.IsRefType) @@ -2455,8 +2446,10 @@ namespace CppSharp.Generators.CSharp { WriteLine("if ({0} == global::System.IntPtr.Zero)", Helpers.InstanceIdentifier); WriteLineIndent("return global::System.IntPtr.Zero.GetHashCode();"); - WriteLine("return (*({0}{1}*) {2}).GetHashCode();", Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class), Helpers.InstanceIdentifier); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + WriteLine($@"return (*({@class.Visit(TypePrinter)}*) { + Helpers.InstanceIdentifier}).GetHashCode();"); + TypePrinter.PopContext(); } else { @@ -2623,10 +2616,13 @@ namespace CppSharp.Generators.CSharp if (@class.HasNonTrivialCopyConstructor) GenerateInternalFunctionCall(method); else - WriteLine("*(({0}.{1}{2}*) {3}) = *(({0}.{1}{2}*) {4}.{3});", - @class.Name, Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class), Helpers.InstanceIdentifier, - method.Parameters[0].Name); + { + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + var classInternal = @class.Visit(TypePrinter); + TypePrinter.PopContext(); + WriteLine($@"*(({classInternal}*) {Helpers.InstanceIdentifier}) = *(({ + classInternal}*) {method.Parameters[0].Name}.{Helpers.InstanceIdentifier});"); + } } else { @@ -2643,14 +2639,17 @@ namespace CppSharp.Generators.CSharp if (parameters == null) parameters = function.Parameters; - var templateSpecialization = function.Namespace as ClassTemplateSpecialization; + var @class = function.Namespace as Class; - string @namespace = templateSpecialization != null && - templateSpecialization.Ignore ? - (templateSpecialization.Namespace.OriginalName + '.') : string.Empty; + string @internal = Helpers.InternalStruct; + if (@class != null && @class is ClassTemplateSpecialization) + { + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + @internal = @class.Visit(TypePrinter).Type; + TypePrinter.PopContext(); + } - var functionName = string.Format("{0}{1}{2}.{3}", @namespace, - Helpers.InternalStruct, Helpers.GetSuffixForInternal(function.Namespace), + var functionName = string.Format("{0}.{1}", @internal, GetFunctionNativeIdentifier(function.OriginalFunction ?? function)); GenerateFunctionCall(functionName, parameters, function, returnType); } @@ -2706,9 +2705,9 @@ namespace CppSharp.Generators.CSharp if (construct == null) { var @class = retClass.OriginalClass ?? retClass; - WriteLine("var {0} = new {1}.{2}{3}();", Helpers.ReturnIdentifier, - @class.Visit(TypePrinter), Helpers.InternalStruct, - Helpers.GetSuffixForInternal(@class)); + TypePrinter.PushContext(CSharpTypePrinterContextKind.Native); + WriteLine($"var {Helpers.ReturnIdentifier} = new {@class.Visit(TypePrinter)}();"); + TypePrinter.PopContext(); } else { @@ -2766,9 +2765,9 @@ namespace CppSharp.Generators.CSharp { if (operatorParam == null) { - WriteLine("fixed ({0}{1}* __instancePtr = &{2})", - Helpers.InternalStruct, Helpers.GetSuffixForInternal(originalFunction.Namespace), - Helpers.InstanceField); + WriteLine($@"fixed ({Helpers.InternalStruct}{ + Helpers.GetSuffixForInternal(originalFunction.Namespace)}* __instancePtr = &{ + Helpers.InstanceField})"); WriteStartBraceIndent(); } else diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 0a47e97f..2747b5db 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -400,18 +400,12 @@ namespace CppSharp.Generators.CSharp public CSharpTypePrinterResult VisitTemplateSpecializationType( TemplateSpecializationType template, TypeQualifiers quals) { - var decl = template.Template.TemplatedDecl; + var decl = template.GetClassTemplateSpecialization() ?? + template.Template.TemplatedDecl; TypeMap typeMap; if (!TypeMapDatabase.FindTypeMap(template, out typeMap)) - { - if (ContextKind != CSharpTypePrinterContextKind.Native) - return GetNestedQualifiedName(decl); - if (template.Desugared.Type.IsAddress()) - return template.Desugared.Type.ToString(); - var specialization = template.GetClassTemplateSpecialization(); - return specialization.Visit(this); - } + return decl.Visit(this); typeMap.Declaration = decl; typeMap.Type = template; @@ -612,8 +606,8 @@ namespace CppSharp.Generators.CSharp public CSharpTypePrinterResult VisitClassTemplateSpecializationDecl(ClassTemplateSpecialization specialization) { if (ContextKind == CSharpTypePrinterContextKind.Native) - return string.Format("{0}{1}", VisitClassDecl(specialization), - Helpers.GetSuffixForInternal(specialization)); + return $@"{VisitClassDecl(specialization)}{ + Helpers.GetSuffixForInternal(specialization)}"; return VisitClassDecl(specialization); } @@ -672,7 +666,7 @@ namespace CppSharp.Generators.CSharp Declaration ctx; var specialization = decl as ClassTemplateSpecialization; - if (specialization != null) + if (specialization != null && ContextKind == CSharpTypePrinterContextKind.Native) { ctx = specialization.TemplatedDecl.TemplatedClass.Namespace; if (specialization.OriginalNamespace is Class &&