Browse Source

Moved the generation of C# bodies to their own methods.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/787/head
Dimitar Dobrev 10 years ago
parent
commit
254e51145f
  1. 485
      src/Generator/Generators/CSharp/CSharpSources.cs

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

@ -705,21 +705,8 @@ namespace CppSharp.Generators.CSharp
PushBlock(BlockKind.Method); PushBlock(BlockKind.Method);
Write("set"); Write("set");
var param = new Parameter
{
Name = "value",
QualifiedType = decl.QualifiedType
};
var ctx = new CSharpMarshalContext(Context)
{
Parameter = param,
ArgName = param.Name,
};
if (decl is Function) if (decl is Function)
{ {
var function = decl as Function;
if (isAbstract) if (isAbstract)
{ {
Write(";"); Write(";");
@ -729,32 +716,13 @@ namespace CppSharp.Generators.CSharp
NewLine(); NewLine();
WriteStartBraceIndent(); WriteStartBraceIndent();
if (function.Parameters.Count == 0) GenerateFunctionSetter(property);
throw new NotSupportedException("Expected at least one parameter in setter"); }
else if (decl is Variable)
param.QualifiedType = function.Parameters[0].QualifiedType; {
NewLine();
if (!property.Type.Equals(param.Type) && property.Type.IsEnumType()) WriteStartBraceIndent();
param.Name = ctx.ArgName = "&" + param.Name; GenerateVariableSetter(decl, @class);
var method = function as Method;
if (function.SynthKind == FunctionSynthKind.AbstractImplCall)
GenerateVirtualPropertyCall(method, @class.BaseClass, property,
new List<Parameter> { param });
else if (method != null && method.IsVirtual)
GenerateVirtualPropertyCall(method, @class, property, new List<Parameter> { param });
else
{
if (method != null && method.OperatorKind == CXXOperatorKind.Subscript)
{
if (method.OperatorKind == CXXOperatorKind.Subscript)
GenerateIndexerSetter(method);
else
GenerateInternalFunctionCall(function, new List<Parameter> { param });
}
else
GenerateInternalFunctionCall(function, new List<Parameter> { param });
}
} }
else if (decl is Field) else if (decl is Field)
{ {
@ -764,91 +732,151 @@ namespace CppSharp.Generators.CSharp
NewLine(); NewLine();
WriteStartBraceIndent(); WriteStartBraceIndent();
GenerateFieldSetter(field, @class);
}
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}
ctx.Kind = MarshalKind.NativeField; private void GenerateVariableSetter<T>(T decl, Class @class) where T : Declaration, ITypedDecl
var marshal = new CSharpMarshalManagedToNativePrinter(ctx); {
ctx.Declaration = field; var var = decl as Variable;
var arrayType = field.Type as ArrayType; TypePrinter.PushContext(TypePrinterContextKind.Native);
if (arrayType != null && @class.IsValueType) var location = $@"CppSharp.SymbolResolver.ResolveSymbol(""{
{ GetLibraryOf(decl)}"", ""{var.Mangled}"")";
ctx.ReturnVarName = HandleValueArray(arrayType, field);
} string ptr = Generator.GeneratedIdentifier("ptr");
else var arrayType = decl.Type as ArrayType;
{ var isRefTypeArray = arrayType != null && @class != null && @class.IsRefType;
var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; if (isRefTypeArray)
TypePrinter.PushContext(TypePrinterContextKind.Native); WriteLine($@"var {ptr} = {
ctx.ReturnVarName = $@"{(@class.IsValueType ? Helpers.InstanceField : (arrayType.Type.IsPrimitiveType(PrimitiveType.Char) &&
$"(({@class.Visit(TypePrinter)}*) {Helpers.InstanceIdentifier})")}{ arrayType.QualifiedType.Qualifiers.IsConst ?
(@class.IsValueType ? "." : "->")}{SafeIdentifier(name)}"; string.Empty : "(byte*)")}{location};");
TypePrinter.PopContext(); else
} WriteLine($"var {ptr} = ({var.Type}*){location};");
param.Visit(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) TypePrinter.PopContext();
Write(marshal.Context.SupportBefore);
if (ctx.HasCodeBlock) var param = new Parameter
PushIndent(); {
Name = "value",
QualifiedType = decl.QualifiedType
};
if (marshal.Context.Return.StringBuilder.Length > 0) var ctx = new CSharpMarshalContext(Context)
{ {
WriteLine("{0} = {1}{2};", ctx.ReturnVarName, Parameter = param,
field.Type.IsPointer() && field.Type.GetFinalPointee().IsPrimitiveType() && ArgName = param.Name,
!CSharpTypePrinter.IsConstCharString(field.Type) ? };
string.Format("({0}) ", CSharpTypePrinter.IntPtrType) :
string.Empty,
marshal.Context.Return);
}
if ((arrayType != null && @class.IsValueType) || ctx.HasCodeBlock) ctx.Kind = MarshalKind.Variable;
WriteCloseBraceIndent(); ctx.ReturnType = new QualifiedType(var.Type);
}
else if (decl is Variable) var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
decl.CSharpMarshalToNative(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);
if (ctx.HasCodeBlock)
PushIndent();
WriteLine($"*{ptr} = {marshal.Context.Return};", marshal.Context.Return);
if (ctx.HasCodeBlock)
WriteCloseBraceIndent();
}
private void GenerateFunctionSetter(Property property)
{
var param = new Parameter
{ {
NewLine(); Name = "value",
WriteStartBraceIndent(); QualifiedType = property.SetMethod.Parameters[0].QualifiedType
var var = decl as Variable; };
TypePrinter.PushContext(TypePrinterContextKind.Native); if (!property.Type.Equals(param.Type) && property.Type.IsEnumType())
param.Name = "&" + param.Name;
var location = $@"CppSharp.SymbolResolver.ResolveSymbol(""{ var @class = (Class) property.Namespace;
GetLibraryOf(decl)}"", ""{var.Mangled}"")"; var function = property.SetMethod;
var method = function as Method;
string ptr = Generator.GeneratedIdentifier("ptr"); if (function.SynthKind == FunctionSynthKind.AbstractImplCall)
var arrayType = decl.Type as ArrayType; GenerateVirtualPropertyCall(method, @class.BaseClass, property,
var isRefTypeArray = arrayType != null && @class != null && @class.IsRefType; new List<Parameter> { param });
if (isRefTypeArray) else if (method != null && method.IsVirtual)
WriteLine($@"var {ptr} = { GenerateVirtualPropertyCall(method, @class, property, new List<Parameter> { param });
(arrayType.Type.IsPrimitiveType(PrimitiveType.Char) && else if (method != null && method.OperatorKind == CXXOperatorKind.Subscript)
arrayType.QualifiedType.Qualifiers.IsConst ? {
string.Empty : "(byte*)")}{location};"); if (method.OperatorKind == CXXOperatorKind.Subscript)
GenerateIndexerSetter(method);
else else
WriteLine($"var {ptr} = ({var.Type}*){location};"); GenerateInternalFunctionCall(property.SetMethod, new List<Parameter> { param });
}
else
GenerateInternalFunctionCall(function, new List<Parameter> { param });
}
TypePrinter.PopContext(); private void GenerateFieldSetter(Field field, Class @class)
{
var param = new Parameter
{
Name = "value",
QualifiedType = field.QualifiedType
};
ctx.Kind = MarshalKind.Variable; var ctx = new CSharpMarshalContext(Context)
ctx.ReturnType = new QualifiedType(var.Type); {
Parameter = param,
ArgName = param.Name,
};
ctx.Kind = MarshalKind.NativeField;
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
ctx.Declaration = field;
var marshal = new CSharpMarshalManagedToNativePrinter(ctx); var arrayType = field.Type as ArrayType;
decl.CSharpMarshalToNative(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) if (arrayType != null && @class.IsValueType)
Write(marshal.Context.SupportBefore); {
ctx.ReturnVarName = HandleValueArray(arrayType, field);
}
else
{
var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name;
TypePrinter.PushContext(TypePrinterContextKind.Native);
ctx.ReturnVarName = string.Format("{0}{1}{2}",
@class.IsValueType
? Helpers.InstanceField
: string.Format("(({0}*) {1})", @class.Visit(TypePrinter),
Helpers.InstanceIdentifier),
@class.IsValueType ? "." : "->",
SafeIdentifier(name));
TypePrinter.PopContext();
}
param.Visit(marshal);
if (ctx.HasCodeBlock) if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
PushIndent(); Write(marshal.Context.SupportBefore);
if (ctx.HasCodeBlock)
PushIndent();
WriteLine($"*{ptr} = {marshal.Context.Return};", marshal.Context.Return); if (marshal.Context.Return.StringBuilder.Length > 0)
{
WriteLine("{0} = {1}{2};", ctx.ReturnVarName,
field.Type.IsPointer() && field.Type.GetFinalPointee().IsPrimitiveType() &&
!CSharpTypePrinter.IsConstCharString(field.Type) ?
string.Format("({0}) ", CSharpTypePrinter.IntPtrType) :
string.Empty,
marshal.Context.Return);
if (ctx.HasCodeBlock)
WriteCloseBraceIndent();
} }
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock); if ((arrayType != null && @class.IsValueType) || ctx.HasCodeBlock)
WriteCloseBraceIndent();
} }
private string HandleValueArray(ArrayType arrayType, Field field) private string HandleValueArray(ArrayType arrayType, Field field)
@ -926,8 +954,8 @@ namespace CppSharp.Generators.CSharp
} }
} }
private void GeneratePropertyGetter<T>(QualifiedType returnType, T decl, private void GeneratePropertyGetter<T>(T decl, Class @class,
Class @class, bool isAbstract = false, Property property = null) bool isAbstract = false, Property property = null)
where T : Declaration, ITypedDecl where T : Declaration, ITypedDecl
{ {
PushBlock(BlockKind.Method); PushBlock(BlockKind.Method);
@ -958,14 +986,7 @@ namespace CppSharp.Generators.CSharp
NewLine(); NewLine();
WriteStartBraceIndent(); WriteStartBraceIndent();
GenerateFunctionGetter(property);
var method = function as Method;
if (function.SynthKind == FunctionSynthKind.AbstractImplCall)
GenerateVirtualPropertyCall(method, @class.BaseClass, property);
else if (method != null && method.IsVirtual)
GenerateVirtualPropertyCall(method, @class, property);
else
GenerateInternalFunctionCall(function, function.Parameters, returnType.Type);
} }
else if (decl is Field) else if (decl is Field)
{ {
@ -975,105 +996,124 @@ namespace CppSharp.Generators.CSharp
NewLine(); NewLine();
WriteStartBraceIndent(); WriteStartBraceIndent();
GenerateFieldGetter(field, @class);
}
else if (decl is Variable)
{
NewLine();
WriteStartBraceIndent();
GenerateVariableGetter(decl, @class);
}
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock);
}
var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name; private void GenerateVariableGetter<T>(T decl, Class @class) where T : Declaration, ITypedDecl
TypePrinter.PushContext(TypePrinterContextKind.Native); {
var ctx = new CSharpMarshalContext(Context) var var = decl as Variable;
{
Kind = MarshalKind.NativeField,
ArgName = decl.Name,
Declaration = decl,
ReturnVarName = $@"{(@class.IsValueType ? Helpers.InstanceField :
$"(({@class.Visit(TypePrinter)}*) {Helpers.InstanceIdentifier})")}{
(@class.IsValueType ? "." : "->")}{SafeIdentifier(name)}",
ReturnType = decl.QualifiedType
};
TypePrinter.PopContext();
var arrayType = field.Type as ArrayType; TypePrinter.PushContext(TypePrinterContextKind.Native);
if (arrayType != null && @class.IsValueType) var location = string.Format("CppSharp.SymbolResolver.ResolveSymbol(\"{0}\", \"{1}\")",
ctx.ReturnVarName = HandleValueArray(arrayType, field); GetLibraryOf(decl), var.Mangled);
var arrayType = decl.Type as ArrayType;
var isRefTypeArray = arrayType != null && @class != null && @class.IsRefType;
if (isRefTypeArray)
WriteLine("var {0} = {1}{2};", Generator.GeneratedIdentifier("ptr"),
arrayType.Type.IsPrimitiveType(PrimitiveType.Char) &&
arrayType.QualifiedType.Qualifiers.IsConst
? string.Empty : "(byte*)",
location);
else
WriteLine("var {0} = ({1}*){2};", Generator.GeneratedIdentifier("ptr"),
@var.Type, location);
var marshal = new CSharpMarshalNativeToManagedPrinter(ctx); TypePrinter.PopContext();
decl.CSharpMarshalToManaged(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) var ctx = new CSharpMarshalContext(Context)
Write(marshal.Context.SupportBefore); {
ArgName = decl.Name,
ReturnVarName = (isRefTypeArray ||
(arrayType != null && arrayType.Type.Desugar().IsPrimitiveType()) ? string.Empty : "*")
+ Generator.GeneratedIdentifier("ptr"),
ReturnType = new QualifiedType(var.Type)
};
if (ctx.HasCodeBlock) var marshal = new CSharpMarshalNativeToManagedPrinter(ctx);
PushIndent(); decl.CSharpMarshalToManaged(marshal);
var @return = marshal.Context.Return.ToString(); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
if (field.Type.IsPointer()) Write(marshal.Context.SupportBefore);
{
var final = field.Type.GetFinalPointee().Desugar();
if (final.IsPrimitiveType() && !final.IsPrimitiveType(PrimitiveType.Void) &&
(!final.IsPrimitiveType(PrimitiveType.Char) &&
!final.IsPrimitiveType(PrimitiveType.WideChar) ||
(!Context.Options.MarshalCharAsManagedChar &&
!((PointerType) field.Type).QualifiedPointee.Qualifiers.IsConst)))
@return = string.Format("({0}*) {1}", field.Type.GetPointee().Desugar(), @return);
if (!((PointerType) field.Type).QualifiedPointee.Qualifiers.IsConst &&
final.IsPrimitiveType(PrimitiveType.WideChar))
@return = string.Format("({0}*) {1}", field.Type.GetPointee().Desugar(), @return);
}
WriteLine("return {0};", @return);
if ((arrayType != null && @class.IsValueType) || ctx.HasCodeBlock) if (ctx.HasCodeBlock)
WriteCloseBraceIndent(); PushIndent();
}
else if (decl is Variable)
{
NewLine();
WriteStartBraceIndent();
var var = decl as Variable;
TypePrinter.PushContext(TypePrinterContextKind.Native); WriteLine("return {0};", marshal.Context.Return);
var location = string.Format("CppSharp.SymbolResolver.ResolveSymbol(\"{0}\", \"{1}\")", if (ctx.HasCodeBlock)
GetLibraryOf(decl), var.Mangled); WriteCloseBraceIndent();
}
var arrayType = decl.Type as ArrayType;
var isRefTypeArray = arrayType != null && @class != null && @class.IsRefType;
if (isRefTypeArray)
WriteLine("var {0} = {1}{2};", Generator.GeneratedIdentifier("ptr"),
arrayType.Type.IsPrimitiveType(PrimitiveType.Char) &&
arrayType.QualifiedType.Qualifiers.IsConst
? string.Empty : "(byte*)",
location);
else
WriteLine("var {0} = ({1}*){2};", Generator.GeneratedIdentifier("ptr"),
@var.Type, location);
TypePrinter.PopContext(); private void GenerateFunctionGetter(Property property)
{
var @class = (Class) property.Namespace;
if (property.GetMethod.SynthKind == FunctionSynthKind.AbstractImplCall)
GenerateVirtualPropertyCall(property.GetMethod, @class.BaseClass, property);
else if (property.GetMethod.IsVirtual)
GenerateVirtualPropertyCall(property.GetMethod, @class, property);
else GenerateInternalFunctionCall(property.GetMethod,
property.GetMethod.Parameters, property.QualifiedType.Type);
}
var ctx = new CSharpMarshalContext(Context) private void GenerateFieldGetter(Field field, Class @class)
{ {
ArgName = decl.Name, var name = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr).Name;
ReturnVarName = (isRefTypeArray || TypePrinter.PushContext(TypePrinterContextKind.Native);
(arrayType != null && arrayType.Type.Desugar().IsPrimitiveType()) ? string.Empty : "*") var ctx = new CSharpMarshalContext(Context)
+ Generator.GeneratedIdentifier("ptr"), {
ReturnType = new QualifiedType(var.Type) Kind = MarshalKind.NativeField,
}; ArgName = field.Name,
Declaration = field,
ReturnVarName = $@"{(@class.IsValueType ? Helpers.InstanceField :
$"(({@class.Visit(TypePrinter)}*) {Helpers.InstanceIdentifier})")}{
(@class.IsValueType ? "." : "->")}{SafeIdentifier(name)}",
ReturnType = field.QualifiedType
};
TypePrinter.PopContext();
var marshal = new CSharpMarshalNativeToManagedPrinter(ctx); var arrayType = field.Type as ArrayType;
decl.CSharpMarshalToManaged(marshal);
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) if (arrayType != null && @class.IsValueType)
Write(marshal.Context.SupportBefore); ctx.ReturnVarName = HandleValueArray(arrayType, field);
if (ctx.HasCodeBlock) var marshal = new CSharpMarshalNativeToManagedPrinter(ctx);
PushIndent(); field.CSharpMarshalToManaged(marshal);
WriteLine("return {0};", marshal.Context.Return); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
Write(marshal.Context.SupportBefore);
if (ctx.HasCodeBlock) if (ctx.HasCodeBlock)
WriteCloseBraceIndent(); PushIndent();
var @return = marshal.Context.Return.ToString();
if (field.Type.IsPointer())
{
var final = field.Type.GetFinalPointee().Desugar();
if (final.IsPrimitiveType() && !final.IsPrimitiveType(PrimitiveType.Void) &&
(!final.IsPrimitiveType(PrimitiveType.Char) &&
!final.IsPrimitiveType(PrimitiveType.WideChar) ||
(!Context.Options.MarshalCharAsManagedChar &&
!((PointerType) field.Type).QualifiedPointee.Qualifiers.IsConst)))
@return = string.Format("({0}*) {1}", field.Type.GetPointee().Desugar(), @return);
if (!((PointerType) field.Type).QualifiedPointee.Qualifiers.IsConst &&
final.IsPrimitiveType(PrimitiveType.WideChar))
@return = string.Format("({0}*) {1}", field.Type.GetPointee().Desugar(), @return);
} }
WriteLine("return {0};", @return);
WriteCloseBraceIndent(); if ((arrayType != null && @class.IsValueType) || ctx.HasCodeBlock)
PopBlock(NewLineKind.BeforeNextBlock); WriteCloseBraceIndent();
} }
private bool WrapGetterArrayOfPointers(string name, Type fieldType) private bool WrapGetterArrayOfPointers(string name, Type fieldType)
@ -1212,7 +1252,7 @@ namespace CppSharp.Generators.CSharp
if (prop.Field != null) if (prop.Field != null)
{ {
if (prop.HasGetter) if (prop.HasGetter)
GeneratePropertyGetter(prop.QualifiedType, prop.Field, @class); GeneratePropertyGetter(prop.Field, @class);
if (prop.HasSetter) if (prop.HasSetter)
GeneratePropertySetter(prop.Field, @class); GeneratePropertySetter(prop.Field, @class);
@ -1220,7 +1260,7 @@ namespace CppSharp.Generators.CSharp
else else
{ {
if (prop.HasGetter) if (prop.HasGetter)
GeneratePropertyGetter(prop.QualifiedType, prop.GetMethod, @class, prop.IsPure, prop); GeneratePropertyGetter(prop.GetMethod, @class, prop.IsPure, prop);
if (prop.HasSetter) if (prop.HasSetter)
GeneratePropertySetter(prop.SetMethod, @class, prop.IsPure, prop); GeneratePropertySetter(prop.SetMethod, @class, prop.IsPure, prop);
@ -1254,7 +1294,7 @@ namespace CppSharp.Generators.CSharp
WriteLine("public static {0} {1}", variable.Type, variable.Name); WriteLine("public static {0} {1}", variable.Type, variable.Name);
WriteStartBraceIndent(); WriteStartBraceIndent();
GeneratePropertyGetter(variable.QualifiedType, variable, @class); GeneratePropertyGetter(variable, @class);
if (!variable.QualifiedType.Qualifiers.IsConst && if (!variable.QualifiedType.Qualifiers.IsConst &&
!(variable.Type.Desugar() is ArrayType)) !(variable.Type.Desugar() is ArrayType))
@ -1873,15 +1913,7 @@ namespace CppSharp.Generators.CSharp
if (dtor.IsVirtual) if (dtor.IsVirtual)
{ {
WriteStartBraceIndent(); WriteStartBraceIndent();
GenerateVirtualFunctionCall(dtor, @class, true); GenerateDestructorCall(dtor);
if (@class.IsAbstract)
{
WriteCloseBraceIndent();
WriteLine("else");
PushIndent();
GenerateInternalFunctionCall(dtor);
PopIndent();
}
WriteCloseBraceIndent(); WriteCloseBraceIndent();
} }
else else
@ -1900,6 +1932,20 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
private void GenerateDestructorCall(Method dtor)
{
var @class = (Class) dtor.Namespace;
GenerateVirtualFunctionCall(dtor, @class, true);
if (@class.IsAbstract)
{
WriteCloseBraceIndent();
WriteLine("else");
PushIndent();
GenerateInternalFunctionCall(dtor);
PopIndent();
}
}
private void GenerateNativeConstructor(Class @class) private void GenerateNativeConstructor(Class @class)
{ {
var shouldGenerateClassNativeField = ShouldGenerateClassNativeField(@class); var shouldGenerateClassNativeField = ShouldGenerateClassNativeField(@class);
@ -2174,6 +2220,22 @@ namespace CppSharp.Generators.CSharp
goto SkipImpl; goto SkipImpl;
} }
GenerateMethodBody(method, @class);
SkipImpl:
WriteCloseBraceIndent();
if (method.OperatorKind == CXXOperatorKind.EqualEqual)
{
GenerateEqualsAndGetHashCode(method, @class);
}
PopBlock(NewLineKind.BeforeNextBlock);
}
private void GenerateMethodBody(Method method, Class @class)
{
if (@class.IsRefType) if (@class.IsRefType)
{ {
if (method.IsConstructor) if (method.IsConstructor)
@ -2212,17 +2274,6 @@ namespace CppSharp.Generators.CSharp
GenerateInternalFunctionCall(method); GenerateInternalFunctionCall(method);
} }
} }
SkipImpl:
WriteCloseBraceIndent();
if (method.OperatorKind == CXXOperatorKind.EqualEqual)
{
GenerateEqualsAndGetHashCode(method, @class);
}
PopBlock(NewLineKind.BeforeNextBlock);
} }
private string OverloadParamNameWithDefValue(Parameter p, ref int index) private string OverloadParamNameWithDefValue(Parameter p, ref int index)

Loading…
Cancel
Save