Generator: rewrite to use T4 templates instead of CodeDom

This commit is contained in:
Alex Corrado 2011-06-13 05:13:07 -04:00
Родитель 40578e03fa
Коммит 2ade762c7e
16 изменённых файлов: 1575 добавлений и 473 удалений

Просмотреть файл

@ -86,7 +86,16 @@ namespace Mono.VisualC.Interop {
#region Wrapper method attributes
[AttributeUsage (AttributeTargets.Method)]
public class OverrideNativeAttribute : Attribute {}
public class OverrideNativeAttribute : Attribute {
public string NativeMethod { get; set; }
public OverrideNativeAttribute ()
{
}
public OverrideNativeAttribute (string nativeMethod)
{
this.NativeMethod = nativeMethod;
}
}
#endregion
}

Просмотреть файл

@ -28,14 +28,14 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.CodeDom;
using System.CodeDom.Compiler;
class Class
{
using Templates;
public class Class {
public Class (Node n) {
Node = n;
BaseClasses = new List<Class> ();
@ -74,150 +74,4 @@ class Class
get; set;
}
public CodeTypeDeclaration GenerateClass (Generator g, CodeTypeDeclaration libDecl, string libFieldName) {
var decl = new CodeTypeDeclaration (Name);
var hasBase = BaseClasses.Count > 0;
decl.IsPartial = true;
if (hasBase)
decl.BaseTypes.Add (new CodeTypeReference (BaseClasses [0].Name));
else
decl.BaseTypes.Add (new CodeTypeReference ("ICppObject"));
var layout = new CodeTypeDeclaration ("_" + Name) {
IsStruct = true,
TypeAttributes = TypeAttributes.NotPublic
};
decl.Members.Add (layout);
foreach (var f in Fields) {
var field = new CodeMemberField {
Name = f.Name,
Type = g.CppTypeToCodeDomType (f.Type),
Attributes = MemberAttributes.Public
};
layout.Members.Add (field);
}
var iface = new CodeTypeDeclaration ("I" + Name);
iface.IsInterface = true;
iface.BaseTypes.Add (new CodeTypeReference ("ICppClassOverridable", new CodeTypeReference [] { new CodeTypeReference (decl.Name) }));
decl.Members.Add (iface);
var implField = new CodeMemberField (new CodeTypeReference (iface.Name), "impl") {
Attributes = MemberAttributes.Private | MemberAttributes.Static
};
var getclass = new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (libDecl.Name), libFieldName), "GetClass", new CodeTypeReference [] { new CodeTypeReference (iface.Name), new CodeTypeReference (layout.Name), new CodeTypeReference (decl.Name) });
implField.InitExpression = new CodeMethodInvokeExpression (getclass, new CodeExpression [] { new CodePrimitiveExpression (Name) });
decl.Members.Add (implField);
//private static IClass impl = global::CppTests.Libs.Test.GetClass <IClass, _Class, Class>("Class");
if (!hasBase) {
var ptrField = new CodeMemberField (new CodeTypeReference ("CppInstancePtr"), "native_ptr") {
Attributes = MemberAttributes.Family
};
decl.Members.Add (ptrField);
}
var implTypeInfo = new CodeFieldReferenceExpression (new CodeFieldReferenceExpression { FieldName = "impl" }, "TypeInfo");
CodeStatement [] initNonPrimaryBases = null;
if (BaseClasses.Count > 1) {
initNonPrimaryBases = new CodeStatement [BaseClasses.Count - 1];
for (var i = 1; i <= initNonPrimaryBases.Length; i++) {
initNonPrimaryBases [i - 1] = new CodeExpressionStatement (new CodeObjectCreateExpression (BaseClasses [i].Name, implTypeInfo));
}
}
var nativeCtor = new CodeConstructor () {
Attributes = MemberAttributes.Public
};
if (hasBase) {
nativeCtor.BaseConstructorArgs.Add (implTypeInfo);
if (initNonPrimaryBases != null)
nativeCtor.Statements.AddRange (initNonPrimaryBases);
}
nativeCtor.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppInstancePtr"), "native"));
nativeCtor.Statements.Add (new CodeAssignStatement (new CodeFieldReferenceExpression (null, "native_ptr"), new CodeArgumentReferenceExpression ("native")));
decl.Members.Add (nativeCtor);
var subclassCtor = new CodeConstructor () {
Attributes = MemberAttributes.Public
};
if (hasBase) {
subclassCtor.BaseConstructorArgs.Add (implTypeInfo);
if (initNonPrimaryBases != null)
subclassCtor.Statements.AddRange (initNonPrimaryBases);
}
subclassCtor.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppTypeInfo"), "subClass"));
subclassCtor.Statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeArgumentReferenceExpression ("subClass"), "AddBase"), new CodeExpression [] { new CodeFieldReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "TypeInfo") })));
decl.Members.Add (subclassCtor);
if (!hasBase) {
var nativeProperty = new CodeMemberProperty () {
Name = "Native",
Type = new CodeTypeReference ("CppInstancePtr"),
Attributes = MemberAttributes.Public|MemberAttributes.Final
};
nativeProperty.GetStatements.Add (new CodeMethodReturnStatement (new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), "native_ptr")));
decl.Members.Add (nativeProperty);
}
var disposeMethod = new CodeMemberMethod () {
Name = "Dispose",
Attributes = MemberAttributes.Public
};
if (hasBase)
disposeMethod.Attributes |= MemberAttributes.Override;
if (Methods.Any (m => m.IsDestructor))
disposeMethod.Statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "Destruct"), new CodeExpression [] { new CodeFieldReferenceExpression (null, "Native") })));
disposeMethod.Statements.Add (new CodeExpressionStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "Native"), "Dispose"))));
decl.Members.Add (disposeMethod);
foreach (Method m in Methods) {
iface.Members.Add (m.GenerateIFaceMethod (g));
if (m.GenWrapperMethod) {
var cm = m.GenerateWrapperMethod (g);
if (m.IsConstructor && hasBase) {
(cm as CodeConstructor).BaseConstructorArgs.Add (implTypeInfo);
if (initNonPrimaryBases != null) {
foreach (var init in initNonPrimaryBases.Reverse ())
cm.Statements.Insert (0, init);
}
}
decl.Members.Add (cm);
}
}
// Add all members inherited from non-primary bases
// With the exception of virtual methods that have been overridden, these methods must be called
// thru a cast to the base class that performs a this ptr adjustment
foreach (var baseClass in BaseClasses.Skip (1)) {
foreach (var method in baseClass.Methods) {
if (method.IsConstructor || (method.IsVirtual && Methods.Any (m => m.Node.CheckValue ("overrides", method.Node.Id))))
continue;
if (method.GenWrapperMethod)
decl.Members.Add (method.GenerateInheritedWrapperMethod (g, baseClass));
}
foreach (var prop in baseClass.Properties) {
decl.Members.Add (prop.GenerateInheritedProperty (g, baseClass));
}
// generate implicit cast to base class
// 1. Create field to cache base casts
decl.Members.Add (new CodeMemberField (baseClass.Name, baseClass.Name + "_base"));
// 2. Add op_Implicit
// FIXME: Can't figure out language-neutral way to do this with codedom.. C# only for now
decl.Members.Add (new CodeSnippetTypeMember (string.Format ("public static implicit operator {0}({1} subClass) {{\n\t\t\tif (subClass.{2} == null)\n\t\t\t\tsubClass.{2} = impl.TypeInfo.Cast<{0}>(subClass);\n\t\t\treturn subClass.{2};\n\t\t}}\n\t\t", baseClass.Name, Name, baseClass.Name + "_base")));
}
foreach (Property p in Properties) {
decl.Members.Add (p.GenerateProperty (g));
}
return decl;
}
}

Просмотреть файл

@ -34,8 +34,8 @@ using System.CodeDom.Compiler;
using Mono.VisualC.Interop;
class Field
{
public class Field {
public Field (string name, CppType type) {
Name = name;
Type = type;

Просмотреть файл

@ -9,29 +9,29 @@ using System.Collections.Generic;
using System.Xml;
using System.Linq;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using Templates;
using NDesk.Options;
using Mono.VisualC.Interop;
public class Generator
{
// Command line arguments
string OutputDir;
string Namespace;
string LibBaseName;
string InputFileName;
string FilterFile;
InlineMethods InlinePolicy;
public class Generator {
CodeDomProvider Provider;
CodeGeneratorOptions CodeGenOptions;
// Command line arguments
public string OutputDir { get; set; }
public string Namespace { get; set; }
public string LibBaseName { get; set; }
public string InputFileName { get; set; }
public string FilterFile { get; set; }
public InlineMethods InlinePolicy { get; set; }
// Classes to generate code for
Dictionary<string, string> Filters;
public List<Class> Classes { get; set; }
public Dictionary<Node, Class> NodeToClass { get; set; }
public Dictionary<string, string> Filters { get; set; }
// Code templates
public ITemplate Libs { get; set; }
public ITemplate Class { get; set; }
public static int Main (String[] args) {
var generator = new Generator ();
@ -39,6 +39,23 @@ public class Generator
return 0;
}
void Run (String[] args) {
if (ParseArguments (args) != 0) {
Environment.Exit (1);
}
Node root = LoadXml (InputFileName);
if (FilterFile != null)
LoadFilters (FilterFile);
CreateClasses (root);
CreateMethods ();
GenerateCode ();
}
int ParseArguments (String[] args) {
bool help = false;
@ -68,6 +85,10 @@ public class Generator
return 1;
}
// Code templates
Libs = new CSharpLibs ();
Class = new CSharpClass ();
InputFileName = args [0];
if (LibBaseName == null) {
@ -81,23 +102,6 @@ public class Generator
return 0;
}
void Run (String[] args) {
if (ParseArguments (args) != 0) {
Environment.Exit (1);
}
Node root = LoadXml (InputFileName);
if (FilterFile != null)
LoadFilters (FilterFile);
CreateClasses (root);
CreateMethods ();
GenerateCode ();
}
Node LoadXml (string file) {
XmlReader reader = XmlReader.Create (file, new XmlReaderSettings ());
@ -150,9 +154,6 @@ public class Generator
}
}
List<Class> Classes;
Dictionary<Node, Class> NodeToClass;
void CreateClasses (Node root) {
List<Node> classNodes = root.Children.Where (o => o.Type == "Class" || o.Type == "Struct").ToList ();
classNodes.RemoveAll (o => o.IsTrue ("incomplete") || !o.HasValue ("name"));
@ -207,9 +208,7 @@ public class Generator
fieldName = n.Name;
else
fieldName = "field" + fieldCount++;
if (CppTypeToCodeDomType (fieldType) == null)
// FIXME: Assume IntPtr
fieldType = ((CppType)CppTypes.Void).Modify (CppModifiers.Pointer);
klass.Fields.Add (new Field (fieldName, fieldType));
break;
case "Constructor":
@ -254,7 +253,7 @@ public class Generator
retType = CppTypes.Void;
if (retType.ElementType == CppTypes.Unknown)
skip = true;
if (CppTypeToCodeDomType (retType) == null) {
if (CppTypeToManaged (retType) == null) {
//Console.WriteLine ("\t\tS: " + retType);
skip = true;
}
@ -276,7 +275,7 @@ public class Generator
skip = true;
}
if (CppTypeToCodeDomType (argtype) == null) {
if (CppTypeToManaged (argtype) == null) {
//Console.WriteLine ("\t\tS: " + argtype);
skip = true;
}
@ -409,120 +408,46 @@ public class Generator
return Node.IdToNode [n.Attributes ["type"]];
}
// Return the CodeDom type reference corresponding to T, or null
public CodeTypeReference CppTypeToCodeDomType (CppType t, out bool byref) {
CodeTypeReference rtype = null;
// Return the System.Type name corresponding to T, or null
// Returned as a string, because other wrappers do not have System.Types yet
public string CppTypeToManaged (CppType t) {
byref = false;
Type mtype = t.ToManagedType ();
if (mtype != null && mtype != typeof (ICppObject)) {
if (mtype.IsByRef) {
byref = true;
mtype = mtype.GetElementType ();
}
return new CodeTypeReference (mtype);
return mtype.FullName;
}
// Why is this here?
//if (t.Modifiers.Count > 0 && t.ElementType != CppTypes.Void && t.ElementType != CppTypes.Class)
// return null;
switch (t.ElementType) {
// These cases should all be handled by ToManagedType, no?
/*
case CppTypes.Void:
if (t.Modifiers.Count > 0) {
if (t.Modifiers.Count == 1 && t.Modifiers [0] == CppModifiers.Pointer)
rtype = new CodeTypeReference (typeof (IntPtr));
else
return null;
} else {
rtype = new CodeTypeReference (typeof (void));
}
break;
case CppTypes.Bool:
rtype = new CodeTypeReference (typeof (bool));
break;
case CppTypes.Int:
rtype = new CodeTypeReference (typeof (int));
break;
case CppTypes.Float:
rtype = new CodeTypeReference (typeof (float));
break;
case CppTypes.Double:
rtype = new CodeTypeReference (typeof (double));
break;
case CppTypes.Char:
rtype = new CodeTypeReference (typeof (char));
break;
*/
case CppTypes.Class:
case CppTypes.Struct:
// FIXME: Full name
rtype = new CodeTypeReference (t.ElementTypeName);
break;
default:
return null;
}
return rtype;
}
return t.ElementTypeName;
public CodeTypeReference CppTypeToCodeDomType (CppType t) {
bool byref;
return CppTypeToCodeDomType (t, out byref);
}
return null;
}
void GenerateCode () {
Directory.CreateDirectory (OutputDir);
Provider = new CSharpCodeProvider ();
CodeGenOptions = new CodeGeneratorOptions { BlankLinesBetweenMembers = false, IndentString = "\t" };
CodeTypeDeclaration libDecl = null;
// Generate Libs class
{
var cu = new CodeCompileUnit ();
var ns = new CodeNamespace (Namespace);
ns.Imports.Add(new CodeNamespaceImport("System"));
ns.Imports.Add(new CodeNamespaceImport("Mono.VisualC.Interop"));
cu.Namespaces.Add (ns);
var decl = new CodeTypeDeclaration ("Libs");
var field = new CodeMemberField (new CodeTypeReference ("CppLibrary"), LibBaseName);
field.Attributes = MemberAttributes.Public|MemberAttributes.Static;
field.InitExpression = new CodeObjectCreateExpression (new CodeTypeReference ("CppLibrary"), new CodeExpression [] { new CodePrimitiveExpression (LibBaseName), new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeof (InlineMethods).Name), InlinePolicy.ToString ()) });
decl.Members.Add (field);
ns.Types.Add (decl);
libDecl = decl;
//Provider.GenerateCodeFromCompileUnit(cu, Console.Out, CodeGenOptions);
using (TextWriter w = File.CreateText (Path.Combine (OutputDir, "Libs.cs"))) {
Provider.GenerateCodeFromCompileUnit(cu, w, CodeGenOptions);
}
// Generate Libs file
using (TextWriter w = File.CreateText (Path.Combine (OutputDir, "Libs.cs"))) {
Libs.Generator = this;
w.Write (Libs.TransformText ());
}
// Generate user classes
foreach (Class klass in Classes) {
if (klass.Disable)
continue;
var cu = new CodeCompileUnit ();
var ns = new CodeNamespace (Namespace);
ns.Imports.Add(new CodeNamespaceImport("System"));
ns.Imports.Add(new CodeNamespaceImport("Mono.VisualC.Interop"));
cu.Namespaces.Add (ns);
ns.Types.Add (klass.GenerateClass (this, libDecl, LibBaseName));
//Provider.GenerateCodeFromCompileUnit(cu, Console.Out, CodeGenOptions);
using (TextWriter w = File.CreateText (Path.Combine (OutputDir, klass.Name + ".cs"))) {
// These are reported for the fields of the native layout structures
//Provider.GenerateCodeFromCompileUnit (new CodeSnippetCompileUnit("#pragma warning disable 0414, 0169"), w, CodeGenOptions);
Provider.GenerateCodeFromCompileUnit(cu, w, CodeGenOptions);
Class.Generator = this;
Class.Class = klass;
w.Write (Class.TransformText ());
}
}
}

Просмотреть файл

@ -55,7 +55,11 @@ FILES = \
Node.cs \
Options.cs \
Parameter.cs \
Property.cs
Property.cs \
Templates/Base.cs \
Templates/BaseMembers.cs \
Templates/CSharp/CSharpClass.cs \
Templates/CSharp/CSharpLibs.cs
DATA_FILES =

Просмотреть файл

@ -30,13 +30,11 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.CodeDom;
using System.CodeDom.Compiler;
using Mono.VisualC.Interop;
class Method
{
public class Method {
public Method (Node node) {
Node = node;
Parameters = new List<Parameter> ();
@ -101,152 +99,4 @@ class Method
return "" + Char.ToUpper (Name [0]) + Name.Substring (1);
}
}
string GetCSharpMethodName (string name) {
return "" + Char.ToUpper (name [0]) + name.Substring (1);
}
public CodeMemberMethod GenerateIFaceMethod (Generator g) {
var method = new CodeMemberMethod () {
Name = Name
};
if (!IsStatic)
method.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference ("CppInstancePtr"), "this"));
CodeTypeReference rtype = g.CppTypeToCodeDomType (ReturnType);
method.ReturnType = rtype;
if ((ReturnType.ElementType == CppTypes.Class || ReturnType.ElementType == CppTypes.Struct) &&
!ReturnType.Modifiers.Contains (CppModifiers.Pointer) &&
!ReturnType.Modifiers.Contains (CppModifiers.Reference) &&
!ReturnType.Modifiers.Contains (CppModifiers.Array))
{
method.ReturnTypeCustomAttributes.Add (new CodeAttributeDeclaration ("ByVal"));
}
foreach (var p in Parameters) {
CppType ptype = p.Type;
bool byref;
var ctype = g.CppTypeToCodeDomType (ptype, out byref);
var param = new CodeParameterDeclarationExpression (ctype, p.Name);
if (byref)
param.Direction = FieldDirection.Ref;
if (!IsVirtual && !ptype.ToString ().Equals (string.Empty))
param.CustomAttributes.Add (new CodeAttributeDeclaration ("MangleAsAttribute", new CodeAttributeArgument (new CodePrimitiveExpression (ptype.ToString ()))));
if ((ptype.ElementType == CppTypes.Class || ptype.ElementType == CppTypes.Struct) &&
!ptype.Modifiers.Contains (CppModifiers.Pointer) &&
!ptype.Modifiers.Contains (CppModifiers.Reference) &&
!ptype.Modifiers.Contains (CppModifiers.Array))
{
param.CustomAttributes.Add (new CodeAttributeDeclaration ("ByVal"));
}
method.Parameters.Add (param);
}
// FIXME: Copy ctor
if (IsVirtual)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Virtual"));
if (IsConstructor)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Constructor"));
if (IsDestructor)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Destructor"));
if (IsConst)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Const"));
if (IsInline)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Inline"));
if (IsArtificial)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Artificial"));
if (IsCopyCtor)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("CopyConstructor"));
if (IsStatic)
method.CustomAttributes.Add (new CodeAttributeDeclaration ("Static"));
return method;
}
public CodeMemberMethod GenerateWrapperDeclaration (Generator g) {
CodeMemberMethod method;
if (IsConstructor)
method = new CodeConstructor () {
Name = GetCSharpMethodName (Name)
};
else
method = new CodeMemberMethod () {
Name = GetCSharpMethodName (Name)
};
method.Attributes = MemberAttributes.Public;
if (IsStatic)
method.Attributes |= MemberAttributes.Static;
method.ReturnType = g.CppTypeToCodeDomType (ReturnType);
foreach (var p in Parameters) {
bool byref;
var ptype = g.CppTypeToCodeDomType (p.Type, out byref);
var param = new CodeParameterDeclarationExpression (ptype, p.Name);
if (byref)
param.Direction = FieldDirection.Ref;
method.Parameters.Add (param);
}
return method;
}
IEnumerable<CodeExpression> GetArgumentExpressions (Generator g) {
for (int i = 0; i < Parameters.Count; ++i) {
bool byref;
g.CppTypeToCodeDomType (Parameters [i].Type, out byref);
CodeExpression arg = new CodeArgumentReferenceExpression (Parameters [i].Name);
if (byref)
arg = new CodeDirectionExpression (FieldDirection.Ref, arg);
yield return arg;
}
yield break;
}
// for methods inherited from non-primary bases
public CodeMemberMethod GenerateInheritedWrapperMethod (Generator g, Class baseClass) {
var method = GenerateWrapperDeclaration (g);
var args = GetArgumentExpressions (g).ToArray ();
var call = new CodeMethodInvokeExpression (new CodeCastExpression (baseClass.Name, new CodeThisReferenceExpression ()), method.Name, args);
if (method.ReturnType.BaseType == "System.Void")
method.Statements.Add (call);
else
method.Statements.Add (new CodeMethodReturnStatement (call));
return method;
}
public CodeMemberMethod GenerateWrapperMethod (Generator g) {
var method = GenerateWrapperDeclaration (g);
if (IsConstructor) {
//this.native_ptr = impl.Alloc(this);
method.Statements.Add (new CodeAssignStatement (new CodeFieldReferenceExpression (null, "native_ptr"), new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), "Alloc"), new CodeExpression [] { new CodeThisReferenceExpression () })));
}
// Call the iface method
var args = new CodeExpression [Parameters.Count + (IsStatic ? 0 : 1)];
if (!IsStatic)
args [0] = new CodeFieldReferenceExpression (null, "Native");
var i = 0;
foreach (var arg in GetArgumentExpressions (g)) {
args [i + (IsStatic ? 0 : 1)] = arg;
i++;
}
var call = new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), Name), args);
if (method.ReturnType.BaseType == "System.Void" || IsConstructor)
method.Statements.Add (call);
else
method.Statements.Add (new CodeMethodReturnStatement (call));
return method;
}
}

Просмотреть файл

@ -36,7 +36,7 @@ using System.Collections.Generic;
//
// This class represents an XML node read from the output of gccxml
//
class Node {
public class Node {
// The XML element type
public string Type {

Просмотреть файл

@ -27,13 +27,11 @@
using System;
using System.Collections.Generic;
using System.CodeDom;
using System.CodeDom.Compiler;
using Mono.VisualC.Interop;
class Property
{
public class Property {
public Property (string name, CppType type) {
Name = name;
Type = type;
@ -54,28 +52,4 @@ class Property
public Method SetMethod {
get; set;
}
public CodeMemberProperty GenerateProperty (Generator g) {
var p = new CodeMemberProperty () { Name = Name, Attributes = MemberAttributes.Public|MemberAttributes.Final };
p.Type = g.CppTypeToCodeDomType (Type);
if (GetMethod != null) {
p.GetStatements.Add (new CodeMethodReturnStatement (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), GetMethod.Name), new CodeExpression [] { new CodeFieldReferenceExpression (null, "Native") })));
}
if (SetMethod != null) {
p.SetStatements.Add (new CodeMethodInvokeExpression (new CodeMethodReferenceExpression (new CodeFieldReferenceExpression (null, "impl"), SetMethod.Name), new CodeExpression [] { new CodeFieldReferenceExpression (null, "Native"), new CodePropertySetValueReferenceExpression () }));
}
return p;
}
public CodeMemberProperty GenerateInheritedProperty (Generator g, Class baseClass) {
var p = new CodeMemberProperty () { Name = Name, Attributes = MemberAttributes.Public|MemberAttributes.Final };
p.Type = g.CppTypeToCodeDomType (Type);
if (GetMethod != null) {
p.GetStatements.Add (new CodeMethodReturnStatement (new CodePropertyReferenceExpression (new CodeCastExpression (baseClass.Name, new CodeThisReferenceExpression ()), GetMethod.Name)));
}
if (SetMethod != null) {
p.SetStatements.Add (new CodeAssignStatement (new CodePropertyReferenceExpression (new CodeCastExpression (baseClass.Name, new CodeThisReferenceExpression ()), SetMethod.Name), new CodePropertySetValueReferenceExpression ()));
}
return p;
}
}

Просмотреть файл

@ -0,0 +1,181 @@
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace Templates {
using System;
public partial class Base : BaseBase {
public virtual string TransformText() {
this.GenerationEnvironment = null;
#line 2 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/Base.tt"
/* This is a dummy template that language-specific templates may inherit from */
#line default
#line hidden
return this.GenerationEnvironment.ToString();
}
protected virtual void Initialize() {
}
}
public class BaseBase {
private global::System.Text.StringBuilder builder;
private global::System.Collections.Generic.IDictionary<string, object> session;
private global::System.CodeDom.Compiler.CompilerErrorCollection errors;
private string currentIndent = string.Empty;
private global::System.Collections.Generic.Stack<int> indents;
private ToStringInstanceHelper _toStringHelper = new ToStringInstanceHelper();
public virtual global::System.Collections.Generic.IDictionary<string, object> Session {
get {
return this.session;
}
set {
this.session = value;
}
}
public global::System.Text.StringBuilder GenerationEnvironment {
get {
if ((this.builder == null)) {
this.builder = new global::System.Text.StringBuilder();
}
return this.builder;
}
set {
this.builder = value;
}
}
protected global::System.CodeDom.Compiler.CompilerErrorCollection Errors {
get {
if ((this.errors == null)) {
this.errors = new global::System.CodeDom.Compiler.CompilerErrorCollection();
}
return this.errors;
}
}
public string CurrentIndent {
get {
return this.currentIndent;
}
}
private global::System.Collections.Generic.Stack<int> Indents {
get {
if ((this.indents == null)) {
this.indents = new global::System.Collections.Generic.Stack<int>();
}
return this.indents;
}
}
public ToStringInstanceHelper ToStringHelper {
get {
return this._toStringHelper;
}
}
public void Error(string message) {
this.Errors.Add(new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message));
}
public void Warning(string message) {
global::System.CodeDom.Compiler.CompilerError val = new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message);
val.IsWarning = true;
this.Errors.Add(val);
}
public string PopIndent() {
if ((this.Indents.Count == 0)) {
return string.Empty;
}
int lastPos = (this.currentIndent.Length - this.Indents.Pop());
string last = this.currentIndent.Substring(lastPos);
this.currentIndent = this.currentIndent.Substring(0, lastPos);
return last;
}
public void PushIndent(string indent) {
this.Indents.Push(indent.Length);
this.currentIndent = (this.currentIndent + indent);
}
public void ClearIndent() {
this.currentIndent = string.Empty;
this.Indents.Clear();
}
public void Write(string textToAppend) {
this.GenerationEnvironment.Append(textToAppend);
}
public void Write(string format, params object[] args) {
this.GenerationEnvironment.AppendFormat(format, args);
}
public void WriteLine(string textToAppend) {
this.GenerationEnvironment.Append(this.currentIndent);
this.GenerationEnvironment.AppendLine(textToAppend);
}
public void WriteLine(string format, params object[] args) {
this.GenerationEnvironment.Append(this.currentIndent);
this.GenerationEnvironment.AppendFormat(format, args);
this.GenerationEnvironment.AppendLine();
}
public class ToStringInstanceHelper {
private global::System.IFormatProvider formatProvider = global::System.Globalization.CultureInfo.InvariantCulture;
public global::System.IFormatProvider FormatProvider {
get {
return this.formatProvider;
}
set {
if ((this.formatProvider == null)) {
throw new global::System.ArgumentNullException("formatProvider");
}
this.formatProvider = value;
}
}
public string ToStringWithCulture(object objectToConvert) {
if ((objectToConvert == null)) {
throw new global::System.ArgumentNullException("objectToConvert");
}
global::System.Type type = objectToConvert.GetType();
global::System.Type iConvertibleType = typeof(global::System.IConvertible);
if (iConvertibleType.IsAssignableFrom(type)) {
return ((global::System.IConvertible)(objectToConvert)).ToString(this.formatProvider);
}
global::System.Reflection.MethodInfo methInfo = type.GetMethod("ToString", new global::System.Type[] {
iConvertibleType});
if ((methInfo != null)) {
return ((string)(methInfo.Invoke(objectToConvert, new object[] {
this.formatProvider})));
}
return objectToConvert.ToString();
}
}
}
}

Просмотреть файл

@ -0,0 +1,2 @@
<#@ template language="C#" #>
<# /* This is a dummy template that language-specific templates may inherit from */ #>

Просмотреть файл

@ -0,0 +1,16 @@
using System;
namespace Templates {
public interface ITemplate {
Generator Generator { get; set; }
Class Class { get; set; }
string TransformText ();
}
public partial class Base : ITemplate {
public Generator Generator { get; set; }
public Class Class { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,828 @@
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace Templates {
using System.IO;
using System.Linq;
using System.Collections.Generic;
using Mono.VisualC.Interop;
using System;
public partial class CSharpClass : Base {
#line 204 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
private void WriteMethodHeader (Method method, string initBases)
{
var returnType = GetCSharpType (Generator.CppTypeToManaged (method.ReturnType));
if (method.IsVirtual)
WriteLine (string.Format ("[OverrideNative (\"{0}\")]", method.Name));
Write (CurrentIndent + "public ");
if (method.IsConstructor) {
Write (method.FormattedName);
} else {
if (method.IsStatic) Write ("static ");
if (method.IsVirtual) Write ("virtual ");
// ...?
Write (returnType);
Write (" ");
Write (method.FormattedName);
}
Write (" (");
WriteParameters (method.Parameters, true, false);
Write (")\n");
if (method.IsConstructor)
WriteLine (initBases);
else
WriteLine ("{");
PushIndent ("\t");
Write (CurrentIndent);
if (returnType != "void")
Write ("return ");
}
private void WriteParameters (IList<Parameter> parameters, bool writeType, bool writeAttributes)
{
for (var i = 0; i < parameters.Count; i++) {
if (i != 0)
Write (", ");
var type = GetCSharpType (Generator.CppTypeToManaged (parameters [i].Type));
if (writeAttributes) {
var mangleAs = parameters [i].Type.ToString ();
if (mangleAs != "" && mangleAs != type)
Write (string.Format ("[MangleAs (\"{0}\")] ", mangleAs));
if (IsByVal (parameters [i].Type))
Write ("[ByVal] ");
}
if (type.EndsWith ("&")) {
Write ("ref ");
type = GetCSharpType (type.TrimEnd ('&'));
}
if (writeType) {
Write (type);
Write (" ");
}
Write (parameters [i].Name);
}
}
private string GetCSharpType (string str)
{
switch (str) {
case "System.Void": return "void";
case "System.Boolean": return "bool";
case "System.Byte": return "byte";
case "System.SByte": return "sbyte";
case "System.Char": return "char";
case "System.Int16": return "short";
case "System.UInt16": return "ushort";
case "System.Decimal": return "decimal";
case "System.Single": return "float";
case "System.Double": return "double";
case "System.Int32": return "int";
case "System.UInt32": return "uint";
case "System.Int64": return "long";
case "System.UInt64": return "ulong";
case "System.Object": return "object";
case "System.String": return "string";
}
var lastDot = str.LastIndexOf ('.');
if (str.StartsWith ("System") && lastDot == "System".Length)
return str.Substring (lastDot + 1);
return str;
}
private string GetBaseString ()
{
if (Class.BaseClasses.Count == 0)
return "ICppObject";
var str = Class.BaseClasses [0].Name;
if (Class.BaseClasses.Count > 1) {
str = string.Format ("{0} /*, {1} */", str, string.Join (", ", Class.BaseClasses.Skip (1).Select (bc => bc.Name).ToArray ()));
}
return str;
}
private bool IsByVal (CppType t)
{
return ((t.ElementType == CppTypes.Class || t.ElementType == CppTypes.Struct) &&
!t.Modifiers.Contains (CppModifiers.Pointer) &&
!t.Modifiers.Contains (CppModifiers.Reference) &&
!t.Modifiers.Contains (CppModifiers.Array));
}
#line default
#line hidden
public override string TransformText() {
this.GenerationEnvironment = null;
#line 6 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
var hasBase = Class.BaseClasses.Count > 0;
var wrapper = Class.Name;
var iface = "I" + Class.Name;
var layout = "_" + Class.Name;
var initBases = "{";
if (hasBase) {
initBases = "\t: base (impl.TypeInfo) {";
foreach (var nonPrimaryBase in Class.BaseClasses.Skip (1)) {
initBases = string.Format ("{0}\n\t\t\tnew {1} (impl.TypeInfo);", initBases, nonPrimaryBase.Name);
}
}
#line default
#line hidden
#line 20 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("// -------------------------------------------------------------------------\n// Managed wrapper for ");
#line default
#line hidden
#line 21 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Class.Name ));
#line default
#line hidden
#line 21 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n// Generated from ");
#line default
#line hidden
#line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Path.GetFileName (Generator.InputFileName) ));
#line default
#line hidden
#line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" on ");
#line default
#line hidden
#line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( DateTime.Now ));
#line default
#line hidden
#line 22 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n//\n// This file was auto generated. Do not edit.\n// -------------------------------------------------------------------------\n\nusing System;\nusing Mono.VisualC.Interop;\n\nnamespace ");
#line default
#line hidden
#line 30 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Generator.Namespace ));
#line default
#line hidden
#line 30 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" {\n\n\tpublic partial class ");
#line default
#line hidden
#line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( wrapper ));
#line default
#line hidden
#line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" : ");
#line default
#line hidden
#line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( GetBaseString () ));
#line default
#line hidden
#line 32 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" {\n\n\t\tprivate static readonly ");
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( iface ));
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" impl = Libs.");
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Generator.LibBaseName ));
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(".GetClass<");
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( iface + "," + layout + "," + wrapper ));
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("> (\"");
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Class.Name ));
#line default
#line hidden
#line 34 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\");\n");
#line default
#line hidden
#line 35 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
if (!hasBase) {
#line default
#line hidden
#line 36 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\tpublic CppInstancePtr Native { get; protected set; }\n");
#line default
#line hidden
#line 37 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
}
#line default
#line hidden
#line 38 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n");
#line default
#line hidden
#line 39 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
/* Interface */
#line default
#line hidden
#line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\tpublic interface ");
#line default
#line hidden
#line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( iface ));
#line default
#line hidden
#line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" : ICppClassOverridable<");
#line default
#line hidden
#line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( wrapper ));
#line default
#line hidden
#line 40 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("> {\n");
#line default
#line hidden
#line 41 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
PushIndent ("\t\t\t");
foreach (var method in Class.Methods) {
Write (CurrentIndent);
if (method.IsVirtual) Write ("[Virtual] ");
if (method.IsStatic) Write ("[Static] ");
if (method.IsArtificial) Write ("[Artificial] ");
if (method.IsInline) Write ("[Inline] ");
if (method.IsConst) Write ("[Const] ");
if (method.IsConstructor) Write ("[Constructor] ");
if (method.IsDestructor) Write ("[Destructor] ");
if (method.IsCopyCtor) Write ("[CopyConstructor] ");
if (IsByVal (method.ReturnType)) {
Write ("[return: ByVal] ");
}
Write (GetCSharpType (Generator.CppTypeToManaged (method.ReturnType)));
Write (" ");
Write (method.Name);
Write (" (");
if (!method.IsStatic) {
Write ("CppInstancePtr @this");
if (method.Parameters.Count != 0)
Write (", ");
}
WriteParameters (method.Parameters, true, !method.IsVirtual);
Write (");\n");
}
ClearIndent ();
#line default
#line hidden
#line 72 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\t}\n");
#line default
#line hidden
#line 73 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
/* Native layout */
#line default
#line hidden
#line 74 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\tprivate struct ");
#line default
#line hidden
#line 74 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( layout ));
#line default
#line hidden
#line 74 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" {\n");
#line default
#line hidden
#line 75 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
foreach (var field in Class.Fields) {
#line default
#line hidden
#line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\t\tpublic ");
#line default
#line hidden
#line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( GetCSharpType (Generator.CppTypeToManaged (field.Type)) ));
#line default
#line hidden
#line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" ");
#line default
#line hidden
#line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( field.Name ));
#line default
#line hidden
#line 76 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(";\n");
#line default
#line hidden
#line 77 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
}
#line default
#line hidden
#line 78 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\t}\n\n");
#line default
#line hidden
#line 80 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
/* Native constructor */
#line default
#line hidden
#line 81 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\tpublic ");
#line default
#line hidden
#line 81 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( wrapper ));
#line default
#line hidden
#line 81 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" (CppInstancePtr native)\n\t\t");
#line default
#line hidden
#line 82 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( initBases ));
#line default
#line hidden
#line 82 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n\t\t\tNative = native;\n\t\t}\n\n");
#line default
#line hidden
#line 86 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
/* Subclass constructor */
#line default
#line hidden
#line 87 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\tpublic ");
#line default
#line hidden
#line 87 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( wrapper ));
#line default
#line hidden
#line 87 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" (CppTypeInfo subClass)\n\t\t");
#line default
#line hidden
#line 88 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( initBases ));
#line default
#line hidden
#line 88 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n\t\t\tsubClass.AddBase (impl.TypeInfo);\n\t\t}\n\n");
#line default
#line hidden
#line 92 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
/* Wrapper methods */
#line default
#line hidden
#line 93 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
PushIndent ("\t\t");
foreach (var method in Class.Methods.Where (m => m.GenWrapperMethod)) {
WriteMethodHeader (method, initBases);
if (method.IsConstructor) {
Write ("Native = impl.Alloc (this);\n");
Write (CurrentIndent);
}
Write (string.Format ("impl.{0} (", method.Name));
if (!method.IsStatic) {
Write ("Native");
if (method.Parameters.Count != 0)
Write (", ");
}
WriteParameters (method.Parameters, false, false);
PopIndent ();
Write (string.Format (");\n{0}}}\n\n", CurrentIndent));
}
ClearIndent ();
#line default
#line hidden
#line 115 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n");
#line default
#line hidden
#line 116 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
/* Wrapper properties */
#line default
#line hidden
#line 117 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
PushIndent ("\t\t");
foreach (var prop in Class.Properties) {
var type = GetCSharpType (Generator.CppTypeToManaged (prop.Type));
Write (CurrentIndent + "public ");
if ((prop.GetMethod == null || prop.GetMethod.IsVirtual) &&
(prop.SetMethod == null || prop.SetMethod.IsVirtual))
Write ("virtual ");
Write (type);
Write (" ");
Write (prop.Name);
Write (" {\n");
PushIndent ("\t");
Write (CurrentIndent);
if (prop.GetMethod != null) {
if (prop.GetMethod.IsVirtual)
Write (string.Format ("[OverrideNative (\"{0}\")] ", prop.GetMethod.Name));
Write ("get {\n");
PushIndent ("\t");
WriteLine (string.Format ("return impl.{0} (Native);", prop.GetMethod.Name));
PopIndent ();
WriteLine ("}");
}
if (prop.SetMethod != null) {
if (prop.SetMethod.IsVirtual)
Write (string.Format ("[OverrideNative (\"{0}\")] ", prop.SetMethod.Name));
Write ("set {\n");
PushIndent ("\t");
WriteLine (string.Format ("impl.{0} (Native, value);", prop.SetMethod.Name));
PopIndent ();
WriteLine ("}");
}
PopIndent ();
WriteLine ("}\n");
}
ClearIndent ();
#line default
#line hidden
#line 160 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n");
#line default
#line hidden
#line 161 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
/* Make this wrapper castable to non-primary bases */
foreach (var npBase in Class.BaseClasses.Skip (1)) {
var npImpl = npBase.Name + "_impl";
#line default
#line hidden
#line 165 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\t// Non-primary base class implementation for ");
#line default
#line hidden
#line 165 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name ));
#line default
#line hidden
#line 165 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(":\n\t\tprivate ");
#line default
#line hidden
#line 166 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name ));
#line default
#line hidden
#line 166 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" ");
#line default
#line hidden
#line 166 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npImpl ));
#line default
#line hidden
#line 166 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(";\n\t\tpublic static implicit operator ");
#line default
#line hidden
#line 167 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name ));
#line default
#line hidden
#line 167 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("(");
#line default
#line hidden
#line 167 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( wrapper ));
#line default
#line hidden
#line 167 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" subClass)\n\t\t{\n\t\t\tif (subClass.");
#line default
#line hidden
#line 169 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npImpl ));
#line default
#line hidden
#line 169 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" == null)\n\t\t\t\tsubClass.");
#line default
#line hidden
#line 170 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npImpl ));
#line default
#line hidden
#line 170 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" = impl.TypeInfo.Cast<");
#line default
#line hidden
#line 170 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npBase.Name ));
#line default
#line hidden
#line 170 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("> (subClass);\n\t\t\treturn subClass.");
#line default
#line hidden
#line 171 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( npImpl ));
#line default
#line hidden
#line 171 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(";\n\t\t}\n\n");
#line default
#line hidden
#line 174 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
PushIndent ("\t\t");
foreach (var method in npBase.Methods) {
// With the exception of virtual methods that have been overridden, these methods must be called
// thru a cast to the base class that performs a this ptr adjustment
if (!method.GenWrapperMethod || method.IsConstructor || method.IsStatic ||
(method.IsVirtual && Class.Methods.Any (m => m.Node.CheckValue ("overrides", method.Node.Id))))
continue;
WriteMethodHeader (method, initBases);
Write (string.Format ("(({0})this).{1} (", npBase.Name, method.FormattedName));
WriteParameters (method.Parameters, false, false);
PopIndent ();
Write (string.Format (");\n{0}}}\n\n", CurrentIndent));
}
ClearIndent ();
}
#line default
#line hidden
#line 192 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\n\t\tpublic ");
#line default
#line hidden
#line 193 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( hasBase? "override" : "virtual" ));
#line default
#line hidden
#line 193 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write(" void Dispose ()\n\t\t{\n");
#line default
#line hidden
#line 195 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
if (Class.Methods.Any (m => m.IsDestructor && !m.IsArtificial)) {
#line default
#line hidden
#line 196 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\t\timpl.Destruct (Native);\n");
#line default
#line hidden
#line 197 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
}
#line default
#line hidden
#line 198 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpClass.tt"
this.Write("\t\t\tNative.Dispose ();\n\t\t}\n\n\t}\n}\n\n");
#line default
#line hidden
return this.GenerationEnvironment.ToString();
}
protected override void Initialize() {
base.Initialize();
}
}
}

Просмотреть файл

@ -0,0 +1,318 @@
<#@ template language="C#" inherits="Base" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Mono.VisualC.Interop" #>
<#
var hasBase = Class.BaseClasses.Count > 0;
var wrapper = Class.Name;
var iface = "I" + Class.Name;
var layout = "_" + Class.Name;
var initBases = "{";
if (hasBase) {
initBases = "\t: base (impl.TypeInfo) {";
foreach (var nonPrimaryBase in Class.BaseClasses.Skip (1)) {
initBases = string.Format ("{0}\n\t\t\tnew {1} (impl.TypeInfo);", initBases, nonPrimaryBase.Name);
}
}
#>
// -------------------------------------------------------------------------
// Managed wrapper for <#= Class.Name #>
// Generated from <#= Path.GetFileName (Generator.InputFileName) #> on <#= DateTime.Now #>
//
// This file was auto generated. Do not edit.
// -------------------------------------------------------------------------
using System;
using Mono.VisualC.Interop;
namespace <#= Generator.Namespace #> {
public partial class <#= wrapper #> : <#= GetBaseString () #> {
private static readonly <#= iface #> impl = Libs.<#= Generator.LibBaseName #>.GetClass<<#= iface + "," + layout + "," + wrapper #>> ("<#= Class.Name #>");
<# if (!hasBase) { #>
public CppInstancePtr Native { get; protected set; }
<# } #>
<# /* Interface */ #>
public interface <#= iface #> : ICppClassOverridable<<#= wrapper #>> {
<# PushIndent ("\t\t\t");
foreach (var method in Class.Methods) {
Write (CurrentIndent);
if (method.IsVirtual) Write ("[Virtual] ");
if (method.IsStatic) Write ("[Static] ");
if (method.IsArtificial) Write ("[Artificial] ");
if (method.IsInline) Write ("[Inline] ");
if (method.IsConst) Write ("[Const] ");
if (method.IsConstructor) Write ("[Constructor] ");
if (method.IsDestructor) Write ("[Destructor] ");
if (method.IsCopyCtor) Write ("[CopyConstructor] ");
if (IsByVal (method.ReturnType)) {
Write ("[return: ByVal] ");
}
Write (GetCSharpType (Generator.CppTypeToManaged (method.ReturnType)));
Write (" ");
Write (method.Name);
Write (" (");
if (!method.IsStatic) {
Write ("CppInstancePtr @this");
if (method.Parameters.Count != 0)
Write (", ");
}
WriteParameters (method.Parameters, true, !method.IsVirtual);
Write (");\n");
}
ClearIndent (); #>
}
<# /* Native layout */ #>
private struct <#= layout #> {
<# foreach (var field in Class.Fields) { #>
public <#= GetCSharpType (Generator.CppTypeToManaged (field.Type)) #> <#= field.Name #>;
<# } #>
}
<# /* Native constructor */ #>
public <#= wrapper #> (CppInstancePtr native)
<#= initBases #>
Native = native;
}
<# /* Subclass constructor */ #>
public <#= wrapper #> (CppTypeInfo subClass)
<#= initBases #>
subClass.AddBase (impl.TypeInfo);
}
<# /* Wrapper methods */ #>
<# PushIndent ("\t\t");
foreach (var method in Class.Methods.Where (m => m.GenWrapperMethod)) {
WriteMethodHeader (method, initBases);
if (method.IsConstructor) {
Write ("Native = impl.Alloc (this);\n");
Write (CurrentIndent);
}
Write (string.Format ("impl.{0} (", method.Name));
if (!method.IsStatic) {
Write ("Native");
if (method.Parameters.Count != 0)
Write (", ");
}
WriteParameters (method.Parameters, false, false);
PopIndent ();
Write (string.Format (");\n{0}}}\n\n", CurrentIndent));
}
ClearIndent (); #>
<# /* Wrapper properties */ #>
<# PushIndent ("\t\t");
foreach (var prop in Class.Properties) {
var type = GetCSharpType (Generator.CppTypeToManaged (prop.Type));
Write (CurrentIndent + "public ");
if ((prop.GetMethod == null || prop.GetMethod.IsVirtual) &&
(prop.SetMethod == null || prop.SetMethod.IsVirtual))
Write ("virtual ");
Write (type);
Write (" ");
Write (prop.Name);
Write (" {\n");
PushIndent ("\t");
Write (CurrentIndent);
if (prop.GetMethod != null) {
if (prop.GetMethod.IsVirtual)
Write (string.Format ("[OverrideNative (\"{0}\")] ", prop.GetMethod.Name));
Write ("get {\n");
PushIndent ("\t");
WriteLine (string.Format ("return impl.{0} (Native);", prop.GetMethod.Name));
PopIndent ();
WriteLine ("}");
}
if (prop.SetMethod != null) {
if (prop.SetMethod.IsVirtual)
Write (string.Format ("[OverrideNative (\"{0}\")] ", prop.SetMethod.Name));
Write ("set {\n");
PushIndent ("\t");
WriteLine (string.Format ("impl.{0} (Native, value);", prop.SetMethod.Name));
PopIndent ();
WriteLine ("}");
}
PopIndent ();
WriteLine ("}\n");
}
ClearIndent (); #>
<# /* Make this wrapper castable to non-primary bases */
foreach (var npBase in Class.BaseClasses.Skip (1)) {
var npImpl = npBase.Name + "_impl";
#>
// Non-primary base class implementation for <#= npBase.Name #>:
private <#= npBase.Name #> <#= npImpl #>;
public static implicit operator <#= npBase.Name #>(<#= wrapper #> subClass)
{
if (subClass.<#= npImpl #> == null)
subClass.<#= npImpl #> = impl.TypeInfo.Cast<<#= npBase.Name #>> (subClass);
return subClass.<#= npImpl #>;
}
<# PushIndent ("\t\t");
foreach (var method in npBase.Methods) {
// With the exception of virtual methods that have been overridden, these methods must be called
// thru a cast to the base class that performs a this ptr adjustment
if (!method.GenWrapperMethod || method.IsConstructor || method.IsStatic ||
(method.IsVirtual && Class.Methods.Any (m => m.Node.CheckValue ("overrides", method.Node.Id))))
continue;
WriteMethodHeader (method, initBases);
Write (string.Format ("(({0})this).{1} (", npBase.Name, method.FormattedName));
WriteParameters (method.Parameters, false, false);
PopIndent ();
Write (string.Format (");\n{0}}}\n\n", CurrentIndent));
}
ClearIndent ();
} #>
public <#= hasBase? "override" : "virtual" #> void Dispose ()
{
<# if (Class.Methods.Any (m => m.IsDestructor && !m.IsArtificial)) { #>
impl.Destruct (Native);
<# } #>
Native.Dispose ();
}
}
}
<#+
private void WriteMethodHeader (Method method, string initBases)
{
var returnType = GetCSharpType (Generator.CppTypeToManaged (method.ReturnType));
if (method.IsVirtual)
WriteLine (string.Format ("[OverrideNative (\"{0}\")]", method.Name));
Write (CurrentIndent + "public ");
if (method.IsConstructor) {
Write (method.FormattedName);
} else {
if (method.IsStatic) Write ("static ");
if (method.IsVirtual) Write ("virtual ");
// ...?
Write (returnType);
Write (" ");
Write (method.FormattedName);
}
Write (" (");
WriteParameters (method.Parameters, true, false);
Write (")\n");
if (method.IsConstructor)
WriteLine (initBases);
else
WriteLine ("{");
PushIndent ("\t");
Write (CurrentIndent);
if (returnType != "void")
Write ("return ");
}
private void WriteParameters (IList<Parameter> parameters, bool writeType, bool writeAttributes)
{
for (var i = 0; i < parameters.Count; i++) {
if (i != 0)
Write (", ");
var type = GetCSharpType (Generator.CppTypeToManaged (parameters [i].Type));
if (writeAttributes) {
var mangleAs = parameters [i].Type.ToString ();
if (mangleAs != "" && mangleAs != type)
Write (string.Format ("[MangleAs (\"{0}\")] ", mangleAs));
if (IsByVal (parameters [i].Type))
Write ("[ByVal] ");
}
if (type.EndsWith ("&")) {
Write ("ref ");
type = GetCSharpType (type.TrimEnd ('&'));
}
if (writeType) {
Write (type);
Write (" ");
}
Write (parameters [i].Name);
}
}
private string GetCSharpType (string str)
{
switch (str) {
case "System.Void": return "void";
case "System.Boolean": return "bool";
case "System.Byte": return "byte";
case "System.SByte": return "sbyte";
case "System.Char": return "char";
case "System.Int16": return "short";
case "System.UInt16": return "ushort";
case "System.Decimal": return "decimal";
case "System.Single": return "float";
case "System.Double": return "double";
case "System.Int32": return "int";
case "System.UInt32": return "uint";
case "System.Int64": return "long";
case "System.UInt64": return "ulong";
case "System.Object": return "object";
case "System.String": return "string";
}
var lastDot = str.LastIndexOf ('.');
if (str.StartsWith ("System") && lastDot == "System".Length)
return str.Substring (lastDot + 1);
return str;
}
private string GetBaseString ()
{
if (Class.BaseClasses.Count == 0)
return "ICppObject";
var str = Class.BaseClasses [0].Name;
if (Class.BaseClasses.Count > 1) {
str = string.Format ("{0} /*, {1} */", str, string.Join (", ", Class.BaseClasses.Skip (1).Select (bc => bc.Name).ToArray ()));
}
return str;
}
private bool IsByVal (CppType t)
{
return ((t.ElementType == CppTypes.Class || t.ElementType == CppTypes.Struct) &&
!t.Modifiers.Contains (CppModifiers.Pointer) &&
!t.Modifiers.Contains (CppModifiers.Reference) &&
!t.Modifiers.Contains (CppModifiers.Array));
}
#>

Просмотреть файл

@ -0,0 +1,92 @@
// ------------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Mono Runtime Version: 4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
// ------------------------------------------------------------------------------
namespace Templates {
using System;
public partial class CSharpLibs : Base {
public override string TransformText() {
this.GenerationEnvironment = null;
#line 2 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write("// -------------------------------------------------------------------------\n// C++ libarary declarations\n// Generated on ");
#line default
#line hidden
#line 4 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( DateTime.Now ));
#line default
#line hidden
#line 4 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write("\n//\n// This file was auto generated. Do not edit.\n// -------------------------------------------------------------------------\n\nusing System;\nusing Mono.VisualC.Interop;\n\nnamespace ");
#line default
#line hidden
#line 12 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Generator.Namespace ));
#line default
#line hidden
#line 12 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(" {\n\n\tpublic static partial class Libs {\n\n\t\tpublic static readonly CppLibrary ");
#line default
#line hidden
#line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Generator.LibBaseName ));
#line default
#line hidden
#line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(" = new CppLibrary (\"");
#line default
#line hidden
#line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Generator.LibBaseName ));
#line default
#line hidden
#line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write("\", InlineMethods.");
#line default
#line hidden
#line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(this.ToStringHelper.ToStringWithCulture( Generator.InlinePolicy.ToString () ));
#line default
#line hidden
#line 16 "/Users/alex/OpenSource/cppinterop/src/generator/Templates/CSharp/CSharpLibs.tt"
this.Write(");\n\n\t}\n}\n");
#line default
#line hidden
return this.GenerationEnvironment.ToString();
}
protected override void Initialize() {
base.Initialize();
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
<#@ template language="C#" inherits="Base" #>
// -------------------------------------------------------------------------
// C++ libarary declarations
// Generated on <#= DateTime.Now #>
//
// This file was auto generated. Do not edit.
// -------------------------------------------------------------------------
using System;
using Mono.VisualC.Interop;
namespace <#= Generator.Namespace #> {
public static partial class Libs {
public static readonly CppLibrary <#= Generator.LibBaseName #> = new CppLibrary ("<#= Generator.LibBaseName #>", InlineMethods.<#= Generator.InlinePolicy.ToString () #>);
}
}

Просмотреть файл

@ -7,7 +7,6 @@
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{AD0F9378-789C-4AF1-B0DD-6DD9A63C3401}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>generator</RootNamespace>
<AssemblyName>generator</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileUpgradeFlags>
@ -30,6 +29,7 @@
<IsWebBootstrapper>true</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<RootNamespace>Templates</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -58,6 +58,16 @@
<Compile Include="Node.cs" />
<Compile Include="Parameter.cs" />
<Compile Include="Property.cs" />
<Compile Include="Templates\Base.cs">
<DependentUpon>Base.tt</DependentUpon>
</Compile>
<Compile Include="Templates\BaseMembers.cs" />
<Compile Include="Templates\CSharp\CSharpClass.cs">
<DependentUpon>CSharpClass.tt</DependentUpon>
</Compile>
<Compile Include="Templates\CSharp\CSharpLibs.cs">
<DependentUpon>CSharpLibs.tt</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Reference Include="System">
@ -67,10 +77,6 @@
<Reference Include="System.Xml.Linq">
</Reference>
<Reference Include="System.Core" />
<Reference Include="Mono.VisualC.Interop, Version=1.0.4180.30887, Culture=neutral, PublicKeyToken=null">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\bin\Debug\Mono.VisualC.Interop.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@ -105,4 +111,28 @@
</Properties>
</MonoDevelop>
</ProjectExtensions>
<ItemGroup>
<ProjectReference Include="..\Mono.VisualC.Interop\Mono.VisualC.Interop.csproj">
<Project>{4A864586-93C5-4DC1-8A80-F094A88506D7}</Project>
<Name>Mono.VisualC.Interop</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Templates\Base.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>Base.cs</LastGenOutput>
</None>
<None Include="Templates\CSharp\CSharpClass.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>CSharpClass.cs</LastGenOutput>
</None>
<None Include="Templates\CSharp\CSharpLibs.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>CSharpLibs.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Templates\" />
<Folder Include="Templates\CSharp\" />
</ItemGroup>
</Project>