Browse Source

Rework class fields generation in the C# backend to be simpler and behave correctly under more situations.

pull/28/head
triton 12 years ago
parent
commit
ee3641338c
  1. 87
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs

87
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -73,6 +73,7 @@ namespace CppSharp.Generators.CSharp
public const int Class = FIRST + 5; public const int Class = FIRST + 5;
public const int InternalsClass = FIRST + 6; public const int InternalsClass = FIRST + 6;
public const int InternalsClassMethod = FIRST + 7; public const int InternalsClassMethod = FIRST + 7;
public const int InternalsClassField = FIRST + 15;
public const int Functions = FIRST + 8; public const int Functions = FIRST + 8;
public const int Function = FIRST + 9; public const int Function = FIRST + 9;
public const int Method = FIRST + 10; public const int Method = FIRST + 10;
@ -335,7 +336,10 @@ namespace CppSharp.Generators.CSharp
} }
GenerateClassConstructors(@class); GenerateClassConstructors(@class);
GenerateClassFields(@class);
if (@class.IsValueType)
GenerateValueClassFields(@class);
GenerateClassMethods(@class); GenerateClassMethods(@class);
GenerateClassVariables(@class); GenerateClassVariables(@class);
GenerateClassProperties(@class); GenerateClassProperties(@class);
@ -348,6 +352,30 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
private void GenerateValueClassFields(Class @class)
{
GenerateClassFields(@class, field =>
{
var fieldClass = (Class) field.Namespace;
if (!fieldClass.IsValueType)
return;
GenerateClassField(field);
});
}
public void GenerateClassInternalsFields(Class @class)
{
GenerateClassFields(@class, GenerateClassInternalsField);
foreach (var prop in @class.Properties)
{
if (prop.Ignore || prop.Field == null)
continue;
GenerateClassInternalsField(prop.Field);
}
}
public void GenerateClassInternals(Class @class) public void GenerateClassInternals(Class @class)
{ {
PushBlock(CSharpBlockKind.InternalsClass); PushBlock(CSharpBlockKind.InternalsClass);
@ -360,7 +388,7 @@ namespace CppSharp.Generators.CSharp
var typePrinter = TypePrinter as CSharpTypePrinter; var typePrinter = TypePrinter as CSharpTypePrinter;
typePrinter.PushContext(CSharpTypePrinterContextKind.Native); typePrinter.PushContext(CSharpTypePrinterContextKind.Native);
GenerateClassFields(@class, isInternal: true); GenerateClassInternalsFields(@class);
GenerateVTablePointers(@class); GenerateVTablePointers(@class);
var functions = GatherClassInternalFunctions(@class); var functions = GatherClassInternalFunctions(@class);
@ -576,85 +604,60 @@ namespace CppSharp.Generators.CSharp
Write("IDisposable"); Write("IDisposable");
} }
public void GenerateClassFields(Class @class, bool isInternal = false) public void GenerateClassFields(Class @class, Action<Field> action)
{
// Handle value-type inheritance
if (@class.IsValueType)
{ {
foreach (var @base in @class.Bases) foreach (var @base in @class.Bases)
{ {
if (!@base.IsClass) if (!@base.IsClass) continue;
continue;
var baseClass = @base.Class; var baseClass = @base.Class;
if (!baseClass.IsValueType || baseClass.Ignore) if (baseClass.Ignore)
continue; continue;
GenerateClassFields(baseClass, isInternal); GenerateClassFields(baseClass, action);
}
} }
foreach (var field in @class.Fields) foreach (var field in @class.Fields)
{ {
if (ASTUtils.CheckIgnoreField(field)) continue; if (ASTUtils.CheckIgnoreField(field)) continue;
GenerateClassField(@class, isInternal, field); action(field);
} }
} }
private void GenerateClassField(Class @class, bool isInternal, Field field) private void GenerateClassInternalsField(Field field)
{ {
if (ASTUtils.CheckIgnoreField(field)) return;
PushBlock(CSharpBlockKind.Field); PushBlock(CSharpBlockKind.Field);
if (isInternal)
{
WriteLine("[FieldOffset({0})]", field.OffsetInBytes); WriteLine("[FieldOffset({0})]", field.OffsetInBytes);
var result = field.Type.Visit(TypePrinter, field.QualifiedType.Qualifiers); var result = field.QualifiedType.CSharpType(TypePrinter);
Write("public {0} {1}", result.Type, SafeIdentifier(field.OriginalName)); Write("public {0} {1}", result.Type, SafeIdentifier(field.OriginalName));
if (!string.IsNullOrWhiteSpace(result.NameSuffix)) if (!string.IsNullOrWhiteSpace(result.NameSuffix))
Write(result.NameSuffix); Write(result.NameSuffix);
WriteLine(";"); WriteLine(";");
}
else if (@class.IsRefType)
{
GenerateFieldProperty(field);
}
else
{
GenerateDeclarationCommon(field);
if (@class.IsUnion)
WriteLine("[FieldOffset({0})]", field.Offset);
WriteLine("public {0} {1};", field.Type, SafeIdentifier(field.Name));
}
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
#endregion private void GenerateClassField(Field field)
private void GenerateFieldProperty(Field field)
{ {
var @class = field.Class; PushBlock(CSharpBlockKind.Field);
PushBlock(CSharpBlockKind.Property);
GenerateDeclarationCommon(field); GenerateDeclarationCommon(field);
WriteLine("public {0} {1}", field.Type, SafeIdentifier(field.Name));
WriteStartBraceIndent();
GeneratePropertyGetter(field, @class); var @class = (Class) field.Namespace;
if (@class.IsUnion)
WriteLine("[FieldOffset({0})]", field.Offset);
GeneratePropertySetter(field, @class); WriteLine("public {0} {1};", field.Type, SafeIdentifier(field.Name));
WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }
#endregion
private Tuple<string, string> GetDeclarationLibrarySymbol(IMangledDecl decl) private Tuple<string, string> GetDeclarationLibrarySymbol(IMangledDecl decl)
{ {
var library = Options.SharedLibraryName; var library = Options.SharedLibraryName;

Loading…
Cancel
Save