Browse Source

Changed the C#-printing of template specialisation types to use their arguments.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/859/head
Dimitar Dobrev 9 years ago
parent
commit
762d3803d7
  1. 7
      src/Generator.Tests/AST/TestAST.cs
  2. 55
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 43
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs

7
src/Generator.Tests/AST/TestAST.cs

@ -516,8 +516,11 @@ namespace CppSharp.Generator.Tests.AST
[Test] [Test]
public void TestDependentNameType() public void TestDependentNameType()
{ {
var template = AstContext.FindDecl<ClassTemplate>("TestSpecializationArguments").First(); var template = AstContext.FindDecl<ClassTemplate>(
Assert.That(template.TemplatedClass.Fields[0].Type.ToString(), "TestSpecializationArguments").First();
var type = template.TemplatedClass.Fields[0].Type.Visit(
new CSharpTypePrinter(Driver.Context));
Assert.That($"{type}",
Is.EqualTo("global::Test.TestTemplateClass<T>.NestedInTemplate")); Is.EqualTo("global::Test.TestTemplateClass<T>.NestedInTemplate"));
} }
} }

55
src/Generator/Generators/CSharp/CSharpSources.cs

@ -344,9 +344,11 @@ namespace CppSharp.Generators.CSharp
WriteLine("protected int {0};", Helpers.PointerAdjustmentIdentifier); WriteLine("protected int {0};", Helpers.PointerAdjustmentIdentifier);
// use interfaces if any - derived types with a secondary base this class must be compatible with the map // 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 @interface = @class.Namespace.Classes.FirstOrDefault(
var dict = string.Format("global::System.Collections.Concurrent.ConcurrentDictionary<IntPtr, {0}>", c => c.IsInterface && c.OriginalClass == @class);
(@interface ?? @class).Visit(TypePrinter)); var printedClass = (@interface ?? @class).Visit(TypePrinter);
var dict = $@"global::System.Collections.Concurrent.ConcurrentDictionary<IntPtr, {
printedClass}{printedClass.NameSuffix}>";
WriteLine("internal static readonly {0} NativeToManagedMap = new {0}();", dict); WriteLine("internal static readonly {0} NativeToManagedMap = new {0}();", dict);
WriteLine("protected void*[] __OriginalVTables;"); WriteLine("protected void*[] __OriginalVTables;");
} }
@ -1169,6 +1171,7 @@ namespace CppSharp.Generators.CSharp
} }
GenerateDeclarationCommon(prop); GenerateDeclarationCommon(prop);
var printedType = prop.Type.Visit(TypePrinter);
if (prop.ExplicitInterfaceImpl == null) if (prop.ExplicitInterfaceImpl == null)
{ {
Write(Helpers.GetAccess(GetValidPropertyAccess(prop))); Write(Helpers.GetAccess(GetValidPropertyAccess(prop)));
@ -1190,12 +1193,12 @@ namespace CppSharp.Generators.CSharp
if (prop.IsVirtual && !isOverride && !prop.IsPure) if (prop.IsVirtual && !isOverride && !prop.IsPure)
Write("virtual "); Write("virtual ");
WriteLine("{0} {1}", prop.Type, GetPropertyName(prop)); WriteLine($"{printedType}{printedType.NameSuffix} {GetPropertyName(prop)}");
} }
else else
{ {
WriteLine("{0} {1}.{2}", prop.Type, prop.ExplicitInterfaceImpl.Name, WriteLine($@"{printedType}{printedType.NameSuffix} {
GetPropertyName(prop)); prop.ExplicitInterfaceImpl.Name}.{GetPropertyName(prop)}");
} }
WriteStartBraceIndent(); WriteStartBraceIndent();
@ -1613,7 +1616,9 @@ namespace CppSharp.Generators.CSharp
WriteLineIndent("throw new global::System.Exception(\"No managed instance was found\");"); WriteLineIndent("throw new global::System.Exception(\"No managed instance was found\");");
NewLine(); NewLine();
WriteLine("var {0} = ({1}) NativeToManagedMap[instance];", Helpers.TargetIdentifier, @class.Visit(TypePrinter)); var printedClass = @class.Visit(TypePrinter);
WriteLine($@"var {Helpers.TargetIdentifier} = ({printedClass}{
printedClass.NameSuffix}) NativeToManagedMap[instance];");
WriteLine("if ({0}.{1})", Helpers.TargetIdentifier, Helpers.OwnsNativeInstanceIdentifier); WriteLine("if ({0}.{1})", Helpers.TargetIdentifier, Helpers.OwnsNativeInstanceIdentifier);
WriteLineIndent("{0}.SetupVTables();", Helpers.TargetIdentifier); WriteLineIndent("{0}.SetupVTables();", Helpers.TargetIdentifier);
GenerateVTableManagedCall(method); GenerateVTableManagedCall(method);
@ -1828,15 +1833,16 @@ namespace CppSharp.Generators.CSharp
var @base = @class.GetNonIgnoredRootBase(); var @base = @class.GetNonIgnoredRootBase();
// Use interfaces if any - derived types with a this class as a seconary base, must be compatible with the map // Use interfaces if any - derived types with a this class as a seconary base, must be compatible with the map
var @interface = @base.Namespace.Classes.Find(c => c.OriginalClass == @base); var @interface = @base.Namespace.Classes.FirstOrDefault(
c => c.IsInterface && c.OriginalClass == @base);
WriteLine("if ({0} == IntPtr.Zero)", Helpers.InstanceIdentifier); WriteLine("if ({0} == IntPtr.Zero)", Helpers.InstanceIdentifier);
WriteLineIndent("return;"); WriteLineIndent("return;");
// The local var must be of the exact type in the object map because of TryRemove // The local var must be of the exact type in the object map because of TryRemove
WriteLine("{0} {1};", var printedClass = (@interface ?? (
(@interface ?? (@base.IsAbstractImpl ? @base.BaseClass : @base)).Visit(TypePrinter), @base.IsAbstractImpl ? @base.BaseClass : @base)).Visit(TypePrinter);
Helpers.DummyIdentifier); WriteLine($"{printedClass}{printedClass.NameSuffix} {Helpers.DummyIdentifier};");
WriteLine("NativeToManagedMap.TryRemove({0}, out {1});", WriteLine("NativeToManagedMap.TryRemove({0}, out {1});",
Helpers.InstanceIdentifier, Helpers.DummyIdentifier); Helpers.InstanceIdentifier, Helpers.DummyIdentifier);
TypePrinter.PushContext(TypePrinterContextKind.Native); TypePrinter.PushContext(TypePrinterContextKind.Native);
@ -1911,13 +1917,15 @@ namespace CppSharp.Generators.CSharp
} }
var suffix = @class.IsAbstract ? "Internal" : string.Empty; var suffix = @class.IsAbstract ? "Internal" : string.Empty;
var ctorCall = $"{@class.Visit(TypePrinter)}{suffix}"; var printedClass = @class.Visit(TypePrinter);
var ctorCall = $"{printedClass}{printedClass.NameSuffix}{suffix}";
if (!@class.IsAbstractImpl) if (!@class.IsAbstractImpl)
{ {
PushBlock(BlockKind.Method); PushBlock(BlockKind.Method);
WriteLine("internal static {0}{1} {2}(global::System.IntPtr native, bool skipVTables = false)", WriteLine("internal static {0}{1}{2} {3}(global::System.IntPtr native, bool skipVTables = false)",
@class.NeedsBase && !@class.BaseClass.IsInterface ? "new " : string.Empty, @class.NeedsBase && !@class.BaseClass.IsInterface ? "new " : string.Empty,
@class.Visit(TypePrinter), Helpers.CreateInstanceIdentifier); printedClass, printedClass.NameSuffix, Helpers.CreateInstanceIdentifier);
WriteStartBraceIndent(); WriteStartBraceIndent();
WriteLine("return new {0}(native.ToPointer(), skipVTables);", ctorCall); WriteLine("return new {0}(native.ToPointer(), skipVTables);", ctorCall);
WriteCloseBraceIndent(); WriteCloseBraceIndent();
@ -2118,7 +2126,10 @@ namespace CppSharp.Generators.CSharp
method.ExplicitInterfaceImpl.Name, functionName); method.ExplicitInterfaceImpl.Name, functionName);
else if (method.OperatorKind == CXXOperatorKind.Conversion || else if (method.OperatorKind == CXXOperatorKind.Conversion ||
method.OperatorKind == CXXOperatorKind.ExplicitConversion) method.OperatorKind == CXXOperatorKind.ExplicitConversion)
Write("{0} {1}(", functionName, method.OriginalReturnType); {
var printedType = method.OriginalReturnType.Visit(TypePrinter);
Write($"{functionName} {printedType}{printedType.NameSuffix}(");
}
else else
Write("{0} {1}(", method.OriginalReturnType, functionName); Write("{0} {1}(", method.OriginalReturnType, functionName);
@ -2427,11 +2438,15 @@ namespace CppSharp.Generators.CSharp
method.Parameters[0].Type.IsPrimitiveTypeConvertibleToRef() ? method.Parameters[0].Type.IsPrimitiveTypeConvertibleToRef() ?
"ref *" : string.Empty, "ref *" : string.Empty,
method.Parameters[0].Name); method.Parameters[0].Name);
var printedType = method.ConversionType.Visit(TypePrinter);
if (@interface != null) if (@interface != null)
WriteLine("return new {0}(({2}) {1});", {
method.ConversionType, paramName, @interface.Name); var printedInterface = @interface.Visit(TypePrinter);
WriteLine($@"return new {printedType}{printedType.NameSuffix}(({
printedInterface}{printedInterface.NameSuffix}) {paramName});");
}
else else
WriteLine("return new {0}({1});", method.ConversionType, paramName); WriteLine($"return new {printedType}{printedType.NameSuffix}({paramName});");
} }
else else
{ {
@ -2508,8 +2523,8 @@ namespace CppSharp.Generators.CSharp
TypePrinter.PopContext(); TypePrinter.PopContext();
} }
var functionName = string.Format("{0}.{1}", @internal, var nativeFunction = GetFunctionNativeIdentifier(function);
GetFunctionNativeIdentifier(function.OriginalFunction ?? function)); var functionName = $"{@internal}.{nativeFunction}";
GenerateFunctionCall(functionName, parameters, function, returnType); GenerateFunctionCall(functionName, parameters, function, returnType);
} }

43
src/Generator/Generators/CSharp/CSharpTypePrinter.cs

@ -7,6 +7,7 @@ using Type = CppSharp.AST.Type;
using ParserTargetInfo = CppSharp.Parser.ParserTargetInfo; using ParserTargetInfo = CppSharp.Parser.ParserTargetInfo;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Globalization;
namespace CppSharp.Generators.CSharp namespace CppSharp.Generators.CSharp
{ {
@ -339,7 +340,13 @@ namespace CppSharp.Generators.CSharp
TypeMap typeMap; TypeMap typeMap;
if (!TypeMapDatabase.FindTypeMap(template, out typeMap)) if (!TypeMapDatabase.FindTypeMap(template, out typeMap))
{
if (ContextKind == TypePrinterContextKind.Managed &&
decl == template.Template.TemplatedDecl)
return $@"{decl.Visit(this)}<{string.Join(", ",
template.Arguments.Select(VisitTemplateArgument))}>";
return decl.Visit(this); return decl.Visit(this);
}
typeMap.Declaration = decl; typeMap.Declaration = decl;
typeMap.Type = template; typeMap.Type = template;
@ -542,8 +549,12 @@ namespace CppSharp.Generators.CSharp
if (ContextKind == TypePrinterContextKind.Native) if (ContextKind == TypePrinterContextKind.Native)
return $"{VisitDeclaration(@class.OriginalClass ?? @class)}.{Helpers.InternalStruct}"; return $"{VisitDeclaration(@class.OriginalClass ?? @class)}.{Helpers.InternalStruct}";
return $@"{VisitDeclaration(@class)}{(@class.IsDependent ? $@"<{ var typePrinterResult = new TypePrinterResult();
string.Join(", ", @class.TemplateParameters.Select(p => p.Name))}>" : string.Empty)}"; typePrinterResult.Type = VisitDeclaration(@class).Type;
if (@class.IsDependent)
typePrinterResult.NameSuffix = $@"<{
string.Join(", ", @class.TemplateParameters.Select(p => p.Name))}>";
return typePrinterResult;
} }
public override TypePrinterResult VisitClassTemplateSpecializationDecl( public override TypePrinterResult VisitClassTemplateSpecializationDecl(
@ -552,7 +563,18 @@ namespace CppSharp.Generators.CSharp
if (ContextKind == TypePrinterContextKind.Native) if (ContextKind == TypePrinterContextKind.Native)
return $@"{VisitClassDecl(specialization)}{ return $@"{VisitClassDecl(specialization)}{
Helpers.GetSuffixForInternal(specialization)}"; Helpers.GetSuffixForInternal(specialization)}";
return VisitClassDecl(specialization); if (specialization.IsExplicitlyGenerated)
return $"{VisitClassDecl(specialization)}";
var args = string.Join(", ", specialization.Arguments.Select(VisitTemplateArgument));
return $"{VisitClassDecl(specialization)}<{args}>";
}
private TypePrinterResult VisitTemplateArgument(TemplateArgument a)
{
if (a.Type.Type == null)
return a.Integral.ToString(CultureInfo.InvariantCulture);
var type = a.Type.Type.Desugar();
return type.IsPointerToPrimitiveType() ? "global::System.IntPtr" : type.Visit(this);
} }
public override TypePrinterResult VisitParameterDecl(Parameter parameter) public override TypePrinterResult VisitParameterDecl(Parameter parameter)
@ -626,13 +648,20 @@ namespace CppSharp.Generators.CSharp
public override TypePrinterResult VisitParameter(Parameter param, bool hasName) public override TypePrinterResult VisitParameter(Parameter param, bool hasName)
{ {
var usage = ContextKind == TypePrinterContextKind.Native ? var printedType = param.Type.Visit(this, param.QualifiedType.Qualifiers);
string.Empty : GetParameterUsage(param.Usage); var type = $"{printedType}{printedType.NameSuffix}";
var type = param.QualifiedType.Visit(this);
var name = param.Name; var name = param.Name;
if (ContextKind == TypePrinterContextKind.Native)
return $"{type} {name}";
var usage = GetParameterUsage(param.Usage);
if (param.DefaultArgument == null || !Options.GenerateDefaultValuesForArguments) if (param.DefaultArgument == null || !Options.GenerateDefaultValuesForArguments)
return $"{usage}{type} {name}"; return $"{usage}{type} {name}";
return $"{usage}{type} {name} = {expressionPrinter.VisitParameter(param)}";
var defaultValue = expressionPrinter.VisitParameter(param);
return $"{usage}{type} {name} = {defaultValue}";
} }
public override TypePrinterResult VisitDelegate(FunctionType function) public override TypePrinterResult VisitDelegate(FunctionType function)

Loading…
Cancel
Save