mirror of https://github.com/mono/CppSharp.git
3 changed files with 591 additions and 0 deletions
@ -0,0 +1,39 @@ |
|||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using Cxxi.Types; |
||||||
|
|
||||||
|
namespace Cxxi.Generators.CSharp |
||||||
|
{ |
||||||
|
public class CSharpGenerator : Generator |
||||||
|
{ |
||||||
|
private readonly ITypePrinter typePrinter; |
||||||
|
|
||||||
|
public CSharpGenerator(Driver driver) : base(driver) |
||||||
|
{ |
||||||
|
typePrinter = new CSharpTypePrinter(driver.TypeDatabase, driver.Library); |
||||||
|
Type.TypePrinter = typePrinter; |
||||||
|
} |
||||||
|
|
||||||
|
void WriteTemplate(TextTemplate template) |
||||||
|
{ |
||||||
|
var file = Path.GetFileNameWithoutExtension(template.unit.FileName) |
||||||
|
+ Driver.Options.WrapperSuffix + "." |
||||||
|
+ template.FileExtension; |
||||||
|
|
||||||
|
var path = Path.Combine(Driver.Options.OutputDir, file); |
||||||
|
|
||||||
|
template.Generate(); |
||||||
|
|
||||||
|
Console.WriteLine(" Generated '" + file + "'."); |
||||||
|
File.WriteAllText(Path.GetFullPath(path), template.ToString()); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Generate(TranslationUnit unit) |
||||||
|
{ |
||||||
|
var template = new CSharpTextTemplate(Driver, unit); |
||||||
|
WriteTemplate(template); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,314 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using Cxxi.Types; |
||||||
|
|
||||||
|
namespace Cxxi.Generators.CSharp |
||||||
|
{ |
||||||
|
public class CSharpTextTemplate : TextTemplate |
||||||
|
{ |
||||||
|
public ITypePrinter TypePrinter { get; set; } |
||||||
|
|
||||||
|
public CSharpTextTemplate(Driver driver, TranslationUnit unit) |
||||||
|
: base(driver, unit) |
||||||
|
{ |
||||||
|
TypePrinter = new CSharpTypePrinter(driver.TypeDatabase, driver.Library); |
||||||
|
} |
||||||
|
|
||||||
|
// from https://github.com/mono/mono/blob/master/mcs/class/System/Microsoft.CSharp/CSharpCodeGenerator.cs
|
||||||
|
private static string[] keywords = new string[] |
||||||
|
{ |
||||||
|
"abstract", "event", "new", "struct", "as", "explicit", "null", "switch", "base", "extern", |
||||||
|
"this", "false", "operator", "throw", "break", "finally", "out", "true", |
||||||
|
"fixed", "override", "try", "case", "params", "typeof", "catch", "for", |
||||||
|
"private", "foreach", "protected", "checked", "goto", "public", |
||||||
|
"unchecked", "class", "if", "readonly", "unsafe", "const", "implicit", "ref", |
||||||
|
"continue", "in", "return", "using", "virtual", "default", |
||||||
|
"interface", "sealed", "volatile", "delegate", "internal", "do", "is", |
||||||
|
"sizeof", "while", "lock", "stackalloc", "else", "static", "enum", |
||||||
|
"namespace", |
||||||
|
"object", "bool", "byte", "float", "uint", "char", "ulong", "ushort", |
||||||
|
"decimal", "int", "sbyte", "short", "double", "long", "string", "void", |
||||||
|
"partial", "yield", "where" |
||||||
|
}; |
||||||
|
|
||||||
|
public static string SafeIdentifier(string proposedName) |
||||||
|
{ |
||||||
|
proposedName = |
||||||
|
new string(((IEnumerable<char>) proposedName).Select(c => char.IsLetterOrDigit(c) ? c : '_').ToArray()); |
||||||
|
return keywords.Contains(proposedName) ? "@" + proposedName : proposedName; |
||||||
|
} |
||||||
|
|
||||||
|
public override string FileExtension |
||||||
|
{ |
||||||
|
get { return "cs"; } |
||||||
|
} |
||||||
|
|
||||||
|
public override void Generate() |
||||||
|
{ |
||||||
|
GenerateStart(); |
||||||
|
|
||||||
|
WriteLine("using System;"); |
||||||
|
WriteLine("using System.Runtime.InteropServices;"); |
||||||
|
NewLine(); |
||||||
|
|
||||||
|
WriteLine("namespace {0}", SafeIdentifier(Driver.Options.LibraryName)); |
||||||
|
WriteStartBraceIndent(); |
||||||
|
|
||||||
|
GenerateDeclarations(); |
||||||
|
|
||||||
|
WriteCloseBraceIndent(); |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateStart() |
||||||
|
{ |
||||||
|
if (Transform != null) |
||||||
|
{ |
||||||
|
Transform.GenerateStart(this); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
WriteLine("//----------------------------------------------------------------------------"); |
||||||
|
WriteLine("// This is autogenerated code by Cxxi."); |
||||||
|
WriteLine("// Do not edit this file or all your changes will be lost after re-generation."); |
||||||
|
WriteLine("//----------------------------------------------------------------------------"); |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateDeclarations() |
||||||
|
{ |
||||||
|
// Generate all the enum declarations for the module.
|
||||||
|
foreach (var @enum in unit.Enums) |
||||||
|
{ |
||||||
|
if (@enum.Ignore || @enum.IsIncomplete) |
||||||
|
continue; |
||||||
|
|
||||||
|
GenerateEnum(@enum); |
||||||
|
NewLine(); |
||||||
|
} |
||||||
|
|
||||||
|
// Generate all the typedef declarations for the module.
|
||||||
|
foreach (var typedef in unit.Typedefs) |
||||||
|
{ |
||||||
|
if (typedef.Ignore) continue; |
||||||
|
|
||||||
|
if (!GenerateTypedef(typedef)) |
||||||
|
continue; |
||||||
|
|
||||||
|
NewLine(); |
||||||
|
} |
||||||
|
|
||||||
|
// Generate all the struct/class declarations for the module.
|
||||||
|
foreach (var @class in unit.Classes) |
||||||
|
{ |
||||||
|
if (@class.Ignore) continue; |
||||||
|
|
||||||
|
GenerateClass(@class); |
||||||
|
NewLine(); |
||||||
|
} |
||||||
|
|
||||||
|
if (unit.HasFunctions) |
||||||
|
{ |
||||||
|
WriteLine("public partial class " + SafeIdentifier(Options.LibraryName)); |
||||||
|
WriteStartBraceIndent(); |
||||||
|
|
||||||
|
// Generate all the function declarations for the module.
|
||||||
|
foreach (var function in unit.Functions) |
||||||
|
GenerateFunction(function); |
||||||
|
|
||||||
|
WriteCloseBraceIndent(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateDeclarationCommon(Declaration T) |
||||||
|
{ |
||||||
|
GenerateSummary(T.BriefComment); |
||||||
|
GenerateDebug(T); |
||||||
|
} |
||||||
|
|
||||||
|
#region Classes
|
||||||
|
|
||||||
|
public void GenerateClass(Class @class) |
||||||
|
{ |
||||||
|
if (@class.Ignore) return; |
||||||
|
GenerateDeclarationCommon(@class); |
||||||
|
|
||||||
|
GenerateClassProlog(@class); |
||||||
|
|
||||||
|
NewLine(); |
||||||
|
WriteStartBraceIndent(); |
||||||
|
|
||||||
|
if (!@class.IsOpaque) |
||||||
|
GenerateClassFields(@class); |
||||||
|
|
||||||
|
WriteCloseBraceIndent(); |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateClassProlog(Class @class) |
||||||
|
{ |
||||||
|
if (@class.IsUnion) |
||||||
|
WriteLine("[StructLayout(LayoutKind.Explicit)]"); |
||||||
|
|
||||||
|
Write("public unsafe "); |
||||||
|
|
||||||
|
if (@class.IsAbstract) |
||||||
|
Write("abstract "); |
||||||
|
|
||||||
|
Write("class {0}", SafeIdentifier(@class.Name)); |
||||||
|
|
||||||
|
if (@class.HasBase) |
||||||
|
Write(" : {0}", SafeIdentifier(@class.Bases[0].Class.Name)); |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateClassFields(Class @class) |
||||||
|
{ |
||||||
|
foreach (var field in @class.Fields) |
||||||
|
{ |
||||||
|
if (field.Ignore) continue; |
||||||
|
|
||||||
|
GenerateDeclarationCommon(field); |
||||||
|
if (@class.IsUnion) |
||||||
|
WriteLine("[FieldOffset({0})]", field.Offset); |
||||||
|
WriteLine("public {0} {1};", field.Type, SafeIdentifier(field.Name)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public bool GenerateTypedef(TypedefDecl typedef) |
||||||
|
{ |
||||||
|
if (typedef.Ignore) |
||||||
|
return false; |
||||||
|
|
||||||
|
GenerateDeclarationCommon(typedef); |
||||||
|
|
||||||
|
FunctionType func; |
||||||
|
TagType tag; |
||||||
|
|
||||||
|
if (typedef.Type.IsPointerToPrimitiveType(PrimitiveType.Void) |
||||||
|
|| typedef.Type.IsPointerTo<TagType>(out tag)) |
||||||
|
{ |
||||||
|
WriteLine("public class " + SafeIdentifier(typedef.Name) + @" { }"); |
||||||
|
} |
||||||
|
else if (typedef.Type.IsPointerTo<FunctionType>(out func)) |
||||||
|
{ |
||||||
|
//WriteLine("public {0};",
|
||||||
|
// string.Format(func.ToDelegateString(), SafeIdentifier(T.Name)));
|
||||||
|
} |
||||||
|
else if (typedef.Type.IsEnumType()) |
||||||
|
{ |
||||||
|
// Already handled in the parser.
|
||||||
|
return false; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
Console.WriteLine("Unhandled typedef type: {0}", typedef); |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateEnum(Enumeration @enum) |
||||||
|
{ |
||||||
|
if (@enum.Ignore) return; |
||||||
|
GenerateDeclarationCommon(@enum); |
||||||
|
|
||||||
|
if (@enum.IsFlags) |
||||||
|
WriteLine("[Flags]"); |
||||||
|
|
||||||
|
Write("public enum {0}", SafeIdentifier(@enum.Name)); |
||||||
|
|
||||||
|
var typeName = TypePrinter.VisitPrimitiveType(@enum.BuiltinType.Type, |
||||||
|
new TypeQualifiers()); |
||||||
|
|
||||||
|
if (@enum.BuiltinType.Type != PrimitiveType.Int32) |
||||||
|
Write(" : {0}", typeName); |
||||||
|
|
||||||
|
NewLine(); |
||||||
|
|
||||||
|
WriteStartBraceIndent(); |
||||||
|
for (var i = 0; i < @enum.Items.Count; ++i) |
||||||
|
{ |
||||||
|
var item = @enum.Items[i]; |
||||||
|
GenerateInlineSummary(item.Comment); |
||||||
|
|
||||||
|
Write(item.ExplicitValue |
||||||
|
? string.Format("{0} = {1}", SafeIdentifier(item.Name), item.Value) |
||||||
|
: string.Format("{0}", SafeIdentifier(item.Name))); |
||||||
|
|
||||||
|
if (i < @enum.Items.Count - 1) |
||||||
|
Write(","); |
||||||
|
|
||||||
|
NewLine(); |
||||||
|
} |
||||||
|
WriteCloseBraceIndent(); |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateFunction(Function function) |
||||||
|
{ |
||||||
|
if(function.Ignore) return; |
||||||
|
GenerateDeclarationCommon(function); |
||||||
|
|
||||||
|
Write("[DllImport(\"{0}.dll\", ", SafeIdentifier(Library.SharedLibrary)); |
||||||
|
Write("CallingConvention = CallingConvention.{0}, ", ToCSharpCallConv(function.CallingConvention)); |
||||||
|
WriteLine("EntryPoint=\"{0}\")]", function.Mangled); |
||||||
|
|
||||||
|
Write("public unsafe static extern {0} {1}(", function.ReturnType, |
||||||
|
SafeIdentifier(function.Name)); |
||||||
|
|
||||||
|
for(var i = 0; i < function.Parameters.Count; ++i) |
||||||
|
{ |
||||||
|
var param = function.Parameters[i]; |
||||||
|
Write("{0} {1}", param.Type, SafeIdentifier(param.Name)); |
||||||
|
|
||||||
|
if (i < function.Parameters.Count - 1) |
||||||
|
Write(", "); |
||||||
|
} |
||||||
|
|
||||||
|
WriteLine(");"); |
||||||
|
} |
||||||
|
|
||||||
|
public static string ToCSharpCallConv(CallingConvention convention) |
||||||
|
{ |
||||||
|
switch (convention) |
||||||
|
{ |
||||||
|
case CallingConvention.Default: |
||||||
|
return "Winapi"; |
||||||
|
case CallingConvention.C: |
||||||
|
return "Cdecl"; |
||||||
|
case CallingConvention.StdCall: |
||||||
|
return "StdCall"; |
||||||
|
case CallingConvention.ThisCall: |
||||||
|
return "ThisCall"; |
||||||
|
case CallingConvention.FastCall: |
||||||
|
return "FastCall"; |
||||||
|
} |
||||||
|
|
||||||
|
return "Winapi"; |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateDebug(Declaration decl) |
||||||
|
{ |
||||||
|
if(Options.OutputDebug && !String.IsNullOrWhiteSpace(decl.DebugText)) |
||||||
|
WriteLine("// DEBUG: " + decl.DebugText); |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateSummary(string comment) |
||||||
|
{ |
||||||
|
if(String.IsNullOrWhiteSpace(comment)) |
||||||
|
return; |
||||||
|
|
||||||
|
WriteLine("/// <summary>"); |
||||||
|
WriteLine("/// {0}", comment); |
||||||
|
WriteLine("/// </summary>"); |
||||||
|
} |
||||||
|
|
||||||
|
public void GenerateInlineSummary(string comment) |
||||||
|
{ |
||||||
|
if(String.IsNullOrWhiteSpace(comment)) |
||||||
|
return; |
||||||
|
|
||||||
|
WriteLine("/// <summary>{0}</summary>", comment); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,238 @@ |
|||||||
|
using System; |
||||||
|
using Cxxi.Types; |
||||||
|
|
||||||
|
namespace Cxxi.Generators.CSharp |
||||||
|
{ |
||||||
|
public class CSharpTypePrinter : ITypePrinter, IDeclVisitor<string> |
||||||
|
{ |
||||||
|
public Library Library { get; set; } |
||||||
|
private readonly ITypeMapDatabase TypeMapDatabase; |
||||||
|
|
||||||
|
public CSharpTypePrinter(ITypeMapDatabase database, Library library) |
||||||
|
{ |
||||||
|
TypeMapDatabase = database; |
||||||
|
Library = library; |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitTagType(TagType tag, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
if (tag.Declaration == null) |
||||||
|
return string.Empty; |
||||||
|
|
||||||
|
return VisitDeclaration(tag.Declaration, quals); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitArrayType(ArrayType array, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
return string.Format("{0}[]", array.Type.Visit(this)); |
||||||
|
|
||||||
|
// C# only supports fixed arrays in unsafe sections
|
||||||
|
// and they are constrained to a set of built-in types.
|
||||||
|
} |
||||||
|
|
||||||
|
public string VisitFunctionType(FunctionType function, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
var arguments = function.Arguments; |
||||||
|
var returnType = function.ReturnType; |
||||||
|
var args = string.Empty; |
||||||
|
|
||||||
|
if (arguments.Count > 0) |
||||||
|
args = GetArgumentsString(function, hasNames: false); |
||||||
|
|
||||||
|
if (returnType.IsPrimitiveType(PrimitiveType.Void)) |
||||||
|
{ |
||||||
|
if (!string.IsNullOrEmpty(args)) |
||||||
|
args = string.Format("<{0}>", args); |
||||||
|
return string.Format("Action{0}", args); |
||||||
|
} |
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(args)) |
||||||
|
args = string.Format(", {0}", args); |
||||||
|
|
||||||
|
return string.Format("Func<{0}{1}>", returnType.Visit(this), args); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitPointerType(PointerType pointer, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
var pointee = pointer.Pointee; |
||||||
|
|
||||||
|
if (pointee is FunctionType) |
||||||
|
{ |
||||||
|
var function = pointee as FunctionType; |
||||||
|
return string.Format("{0}", function.Visit(this, quals)); |
||||||
|
} |
||||||
|
|
||||||
|
if (pointee.IsPrimitiveType(PrimitiveType.Void, walkTypedefs: true) || |
||||||
|
pointee.IsPrimitiveType(PrimitiveType.UInt8, walkTypedefs: true)) |
||||||
|
{ |
||||||
|
return "IntPtr"; |
||||||
|
} |
||||||
|
|
||||||
|
if (pointee.IsPrimitiveType(PrimitiveType.Char) && quals.IsConst) |
||||||
|
{ |
||||||
|
return "string"; |
||||||
|
} |
||||||
|
|
||||||
|
return pointee.Visit(this, quals); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitMemberPointerType(MemberPointerType member, |
||||||
|
TypeQualifiers quals) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
return VisitPrimitiveType(builtin.Type, quals); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitTypedefType(TypedefType typedef, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
var decl = typedef.Declaration; |
||||||
|
|
||||||
|
TypeMap typeMap = null; |
||||||
|
if (TypeMapDatabase.FindTypeMap(decl, out typeMap)) |
||||||
|
{ |
||||||
|
return typeMap.Signature(); |
||||||
|
} |
||||||
|
|
||||||
|
FunctionType func; |
||||||
|
if (decl.Type.IsPointerTo<FunctionType>(out func)) |
||||||
|
{ |
||||||
|
// TODO: Use SafeIdentifier()
|
||||||
|
return string.Format("{0}", VisitDeclaration(decl)); |
||||||
|
} |
||||||
|
|
||||||
|
return decl.Type.Visit(this); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
switch (primitive) |
||||||
|
{ |
||||||
|
case PrimitiveType.Bool: return "bool"; |
||||||
|
case PrimitiveType.Void: return "void"; |
||||||
|
case PrimitiveType.WideChar: return "char"; |
||||||
|
case PrimitiveType.Int8: return "sbyte"; |
||||||
|
case PrimitiveType.UInt8: return "byte"; |
||||||
|
case PrimitiveType.Int16: return "short"; |
||||||
|
case PrimitiveType.UInt16: return "ushort"; |
||||||
|
case PrimitiveType.Int32: return "int"; |
||||||
|
case PrimitiveType.UInt32: return "uint"; |
||||||
|
case PrimitiveType.Int64: return "long"; |
||||||
|
case PrimitiveType.UInt64: return "ulong"; |
||||||
|
case PrimitiveType.Float: return "float"; |
||||||
|
case PrimitiveType.Double: return "double"; |
||||||
|
} |
||||||
|
|
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitDeclaration(Declaration decl, TypeQualifiers quals) |
||||||
|
{ |
||||||
|
return VisitDeclaration(decl); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitDeclaration(Declaration decl) |
||||||
|
{ |
||||||
|
var name = decl.Visit(this); |
||||||
|
return string.Format("{0}", name); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitClassDecl(Class @class) |
||||||
|
{ |
||||||
|
return @class.Name; |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitFieldDecl(Field field) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitFunctionDecl(Function function) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitMethodDecl(Method method) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitParameterDecl(Parameter parameter) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitTypedefDecl(TypedefDecl typedef) |
||||||
|
{ |
||||||
|
return typedef.Name; |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitEnumDecl(Enumeration @enum) |
||||||
|
{ |
||||||
|
return @enum.Name; |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitClassTemplateDecl(ClassTemplate template) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitFunctionTemplateDecl(FunctionTemplate template) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitMacroDefinition(MacroDefinition macro) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string VisitNamespace(Namespace @namespace) |
||||||
|
{ |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
|
||||||
|
public string GetArgumentsString(FunctionType function, bool hasNames) |
||||||
|
{ |
||||||
|
var arguments = function.Arguments; |
||||||
|
var s = string.Empty; |
||||||
|
|
||||||
|
for (var i = 0; i < arguments.Count; ++i) |
||||||
|
{ |
||||||
|
s += GetArgumentString(arguments[i], hasNames); |
||||||
|
if (i < arguments.Count - 1) |
||||||
|
s += ", "; |
||||||
|
} |
||||||
|
|
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
public string GetArgumentString(Parameter arg, bool hasName) |
||||||
|
{ |
||||||
|
var quals = new TypeQualifiers { IsConst = arg.IsConst }; |
||||||
|
|
||||||
|
var type = arg.Type.Visit(this, quals); |
||||||
|
var name = arg.Name; |
||||||
|
|
||||||
|
if (hasName && !string.IsNullOrEmpty(name)) |
||||||
|
return string.Format("{0} {1}", type, name); |
||||||
|
|
||||||
|
return type; |
||||||
|
} |
||||||
|
|
||||||
|
public string ToDelegateString(FunctionType function) |
||||||
|
{ |
||||||
|
return string.Format("delegate {0} {{0}}({1})", |
||||||
|
function.ReturnType.Visit(this), |
||||||
|
GetArgumentsString(function, hasNames: true)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue