From e097527450680e7d2c3b683b4b191d03be3de21c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Tue, 20 Dec 2005 20:47:07 +0000 Subject: [PATCH] Added WrapperGenerator git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@927 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Tools/WrapperGenerator/AssemblyInfo.cs | 27 + src/Tools/WrapperGenerator/CodeGenerator.cs | 615 ++++++++++++++++++ .../WrapperGenerator/CorDebugGenerator.cs | 46 ++ src/Tools/WrapperGenerator/FileGenerator.cs | 69 ++ src/Tools/WrapperGenerator/MainForm.cs | 85 +++ src/Tools/WrapperGenerator/MainForm.resources | Bin 0 -> 180 bytes src/Tools/WrapperGenerator/Test.cs | 53 ++ src/Tools/WrapperGenerator/Wrapper.cs | 25 + .../WrapperGenerator/WrapperGenerator.csproj | 43 ++ .../WrapperGenerator/WrapperGenerator.sln | 16 + src/Tools/WrapperGenerator/WrapperProxy.cs | 87 +++ .../WrappingClassAttribute.cs | 17 + 12 files changed, 1083 insertions(+) create mode 100644 src/Tools/WrapperGenerator/AssemblyInfo.cs create mode 100644 src/Tools/WrapperGenerator/CodeGenerator.cs create mode 100644 src/Tools/WrapperGenerator/CorDebugGenerator.cs create mode 100644 src/Tools/WrapperGenerator/FileGenerator.cs create mode 100644 src/Tools/WrapperGenerator/MainForm.cs create mode 100644 src/Tools/WrapperGenerator/MainForm.resources create mode 100644 src/Tools/WrapperGenerator/Test.cs create mode 100644 src/Tools/WrapperGenerator/Wrapper.cs create mode 100644 src/Tools/WrapperGenerator/WrapperGenerator.csproj create mode 100644 src/Tools/WrapperGenerator/WrapperGenerator.sln create mode 100644 src/Tools/WrapperGenerator/WrapperProxy.cs create mode 100644 src/Tools/WrapperGenerator/WrappingClassAttribute.cs diff --git a/src/Tools/WrapperGenerator/AssemblyInfo.cs b/src/Tools/WrapperGenerator/AssemblyInfo.cs new file mode 100644 index 0000000000..b8aff24da3 --- /dev/null +++ b/src/Tools/WrapperGenerator/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("1.0.*")] + diff --git a/src/Tools/WrapperGenerator/CodeGenerator.cs b/src/Tools/WrapperGenerator/CodeGenerator.cs new file mode 100644 index 0000000000..c0a3762acf --- /dev/null +++ b/src/Tools/WrapperGenerator/CodeGenerator.cs @@ -0,0 +1,615 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +using Microsoft.CSharp; + +namespace WrapperGenerator +{ + public class CodeGenerator + { + Assembly assembly; + protected string wrapperNamespace; + + string comparsionCode = +@" public bool Is() where T: class" + "\r\n" + +@" {" + "\r\n" + +@" try {" + "\r\n" + +@" CastTo();" + "\r\n" + +@" return true;" + "\r\n" + +@" } catch {" + "\r\n" + +@" return false;" + "\r\n" + +@" }" + "\r\n" + +@" }" + "\r\n" + +@" " + "\r\n" + +@" public T As() where T: class" + "\r\n" + +@" {" + "\r\n" + +@" try {" + "\r\n" + +@" return CastTo();" + "\r\n" + +@" } catch {" + "\r\n" + +@" return null;" + "\r\n" + +@" }" + "\r\n" + +@" }" + "\r\n" + +@" " + "\r\n" + +@" public T CastTo() where T: class" + "\r\n" + +@" {" + "\r\n" + +@" return (T)Activator.CreateInstance(typeof(T), this.WrappedObject);" + "\r\n" + +@" }" + "\r\n" + +@" " + "\r\n" + +@" public static bool operator ==(TheType o1, TheType o2)" + "\r\n" + +@" {" + "\r\n" + +@" return ((object)o1 == null && (object)o2 == null) ||" + "\r\n" + +@" ((object)o1 != null && (object)o2 != null && o1.WrappedObject == o2.WrappedObject);" + "\r\n" + +@" }" + "\r\n" + +@" " + "\r\n" + +@" public static bool operator !=(TheType o1, TheType o2)" + "\r\n" + +@" {" + "\r\n" + +@" return !(o1 == o2);" + "\r\n" + +@" }" + "\r\n" + +@" " + "\r\n" + +@" public override int GetHashCode()" + "\r\n" + +@" {" + "\r\n" + +@" return base.GetHashCode();" + "\r\n" + +@" }" + "\r\n" + +@" " + "\r\n" + +@" public override bool Equals(object o)" + "\r\n" + +@" {" + "\r\n" + +@" TheType casted = o as TheType;" + "\r\n" + +@" return (casted != null) && (casted.WrappedObject == wrappedObject);" + "\r\n" + +@" }" + "\r\n" + +@" "; + + public CodeGenerator(Assembly assembly) + { + this.assembly = assembly; + } + + protected virtual bool ShouldIncludeType(Type type) + { + return true; + } + + protected virtual Type GetBaseClass(Type type) + { + return null; + } + + public IEnumerable MakeCompileUnits() + { + foreach(Type type in assembly.GetTypes()) { + if (!ShouldIncludeType(type)) continue; + + CodeCompileUnit codeCompileUnit; + codeCompileUnit = new CodeCompileUnit(); + codeCompileUnit.UserData.Add("filename", type.Name); + codeCompileUnit.Namespaces.Add(MakeNamespace(type)); + + yield return codeCompileUnit; + } + } + + CodeNamespace MakeNamespace(Type type) + { + CodeNamespace codeNamespace = new CodeNamespace(wrapperNamespace); + codeNamespace.Imports.Add(new CodeNamespaceImport("System")); + codeNamespace.Types.Add(MakeTypeDeclaration(type)); + + return codeNamespace; + } + + CodeTypeDeclaration MakeTypeDeclaration(Type type) + { + if (type.IsEnum) { + return MakeEnumDeclaration(type); + } else { + return MakeClassDeclaration(type); + } + } + + CodeTypeDeclaration MakeEnumDeclaration(Type type) + { + CodeTypeDeclaration enumDeclaration = new CodeTypeDeclaration(); + enumDeclaration.Attributes = MemberAttributes.Private; + enumDeclaration.Name = type.Name; + enumDeclaration.IsEnum = true; + enumDeclaration.BaseTypes.Add(Enum.GetUnderlyingType(type)); + + if (type.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0) { + enumDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("Flags")); + } + + foreach(string name in Enum.GetNames(type)) { + CodeMemberField field = new CodeMemberField(); + field.Name = name; + object val = Convert.ChangeType(Enum.Parse(type, name), Enum.GetUnderlyingType(type)); + field.InitExpression = new CodePrimitiveExpression(val); + enumDeclaration.Members.Add(field); + } + + return enumDeclaration; + } + + CodeTypeDeclaration MakeClassDeclaration(Type type) + { + Type baseType = GetBaseClass(type); + + CodeTypeDeclaration codeTypeDeclaration = new CodeTypeDeclaration(); + codeTypeDeclaration.Attributes = MemberAttributes.Private; + codeTypeDeclaration.Name = type.Name; + if (baseType != null) { + codeTypeDeclaration.BaseTypes.Add(baseType.Name); + } + + codeTypeDeclaration.Members.Add(MakeWrappedObjectField(type)); + codeTypeDeclaration.Members.Add(MakeWrappedObjectProperty(type)); + codeTypeDeclaration.Members.Add(MakeConstructor(type)); + //codeTypeDeclaration.Members.Add(MakeCanWrapMethod(type)); + codeTypeDeclaration.Members.Add(MakeWrapMethod(type)); + codeTypeDeclaration.Members.Add(new CodeSnippetTypeMember(comparsionCode.Replace("TheType", type.Name))); + codeTypeDeclaration.Members.AddRange(MakeMembers(type)); + + return codeTypeDeclaration; + } + + CodeMemberField MakeWrappedObjectField(Type type) + { + CodeMemberField codeWrappedObjectField = new CodeMemberField(); + codeWrappedObjectField.Attributes = MemberAttributes.Private; + codeWrappedObjectField.Type = new CodeTypeReference(type.FullName); + codeWrappedObjectField.Name = "wrappedObject"; + + return codeWrappedObjectField; + } + + CodeExpression ExpressionForWrappedObjectField { + get { + return new CodeFieldReferenceExpression( + new CodeThisReferenceExpression(), + "wrappedObject"); + } + } + + CodeMemberProperty MakeWrappedObjectProperty(Type type) + { + CodeMemberProperty codeWrappedObjectProperty = new CodeMemberProperty(); + codeWrappedObjectProperty.Attributes = MemberAttributes.Assembly | MemberAttributes.Final; + codeWrappedObjectProperty.Type = new CodeTypeReference(type.FullName); + codeWrappedObjectProperty.Name = "WrappedObject"; + codeWrappedObjectProperty.HasGet = true; + codeWrappedObjectProperty.HasSet = false; + + CodeMethodReturnStatement codeGetter = new CodeMethodReturnStatement(ExpressionForWrappedObjectField); + codeWrappedObjectProperty.GetStatements.Add(codeGetter); + + return codeWrappedObjectProperty; + } + + CodeExpression ExpressionForWrappedObjectProperty { + get { + return new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "WrappedObject"); + } + } + + CodeConstructor MakeConstructor(Type type) + { + Type baseType = GetBaseClass(type); + + CodeConstructor codeConstructor = new CodeConstructor(); + codeConstructor.Attributes = MemberAttributes.Public; + codeConstructor.Parameters.Add(new CodeParameterDeclarationExpression(type, "wrappedObject")); + + if (baseType != null) { + codeConstructor.BaseConstructorArgs.Add( + new CodeCastExpression( + GetBaseClass(type).FullName, + new CodeArgumentReferenceExpression("wrappedObject"))); + } + + codeConstructor.Statements.Add( + new CodeAssignStatement( + ExpressionForWrappedObjectField, + new CodeArgumentReferenceExpression("wrappedObject"))); + + return codeConstructor; + } + + /* + CodeMemberMethod MakeCanWrapMethod(Type wrappedType) + { + CodeMemberMethod method = new CodeMemberMethod(); + method.Attributes = MemberAttributes.Static | MemberAttributes.Public; + method.ReturnType = new CodeTypeReference(typeof(bool)); + method.Name = "CanWrap"; + method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "objectToWrap")); + + method.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression("objectToWrap is " + wrappedType.FullName))); + + return method; + } + */ + + CodeMemberMethod MakeWrapMethod(Type wrappedType) + { + CodeMemberMethod method = new CodeMemberMethod(); + method.Attributes = MemberAttributes.Static | MemberAttributes.Public; + method.ReturnType = new CodeTypeReference(wrappedType.Name); + method.Name = "Wrap"; + method.Parameters.Add(new CodeParameterDeclarationExpression(wrappedType, "objectToWrap")); + + /* + foreach(Type type in wrappedType.Assembly.GetTypes()) { + if (ShouldIncludeType(type) && GetBaseClass(type).Name == wrappedType.Name) { + method.Statements.Add( + new CodeConditionStatement( + new CodeMethodInvokeExpression( + new CodeMethodReferenceExpression( + new CodeTypeReferenceExpression(type.Name), + "CanWrap"), + new CodeArgumentReferenceExpression("objectToWrap")), + new CodeMethodReturnStatement( + new CodeMethodInvokeExpression( + new CodeMethodReferenceExpression( + new CodeTypeReferenceExpression(type.Name), + "Wrap"), + new CodeCastExpression( + namespaceToWrap + "." + type.Name, + new CodeArgumentReferenceExpression("objectToWrap")))))); + + } + } + */ + + method.Statements.Add( + new CodeMethodReturnStatement( + new CodeObjectCreateExpression( + wrappedType.Name, + new CodeArgumentReferenceExpression("objectToWrap")))); + + return method; + } + + CodeTypeMember[] MakeMembers(Type type) + { + List codeTypeMembers = new List(); + + foreach(MethodInfo method in type.GetMethods()) { + if (method.DeclaringType == type) { + codeTypeMembers.Add(MakeMember(method)); + } + } + + return codeTypeMembers.ToArray(); + } + + CodeExpression Unwrap(Type rawType, CodeExpression codeExpression) + { + if (rawType.IsEnum) { + return new CodeCastExpression( + new CodeTypeReference(rawType), + codeExpression); + } else { + return new CodePropertyReferenceExpression(codeExpression, "WrappedObject"); + } + } + + CodeExpression Wrap(Type rawType, CodeExpression codeExpression) + { + if (rawType.IsEnum) { + return new CodeCastExpression( + new CodeTypeReference(rawType.Name), + codeExpression); + } else { + return new CodeMethodInvokeExpression( + new CodeMethodReferenceExpression( + new CodeTypeReferenceExpression(rawType.Name), + "Wrap"), + codeExpression); + } + } + + class MethodContext + { + CodeMemberMethod codeMemberMethod = new CodeMemberMethod(); + CodeGenerator generator; + + public string Name; + public bool IsReturnTypeWrapped; + public Type RawReturnType; + public string WrappedReturnType; + + public List WrapperParams = new List(); + public List DoBeforeInvoke = new List(); + public List BaseMethodInvokeParams = new List(); + public List DoAfterInvoke = new List(); + + public MethodContext(CodeGenerator generator, MethodInfo method) + { + this.generator = generator; + Name = method.Name; + RawReturnType = method.ReturnType; + IsReturnTypeWrapped = generator.ShouldIncludeType(method.ReturnType); + if (IsReturnTypeWrapped) { + WrappedReturnType = method.ReturnType.Name; + } else { + WrappedReturnType = method.ReturnType.FullName; + } + + codeMemberMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final; + codeMemberMethod.ReturnType = new CodeTypeReference(WrappedReturnType); + codeMemberMethod.Name = method.Name; + } + + public CodeMemberMethod Emit() + { + CodeExpression baseInvoke = + new CodeMethodInvokeExpression( + new CodeMethodReferenceExpression( + generator.ExpressionForWrappedObjectProperty, + Name), + BaseMethodInvokeParams.ToArray()); + + if (IsReturnTypeWrapped) { + baseInvoke = generator.Wrap(RawReturnType, baseInvoke); + } + + CodeStatement doInvoke; + + if (WrappedReturnType != typeof(void).FullName) { + if (DoAfterInvoke.Count == 0) { + doInvoke = new CodeMethodReturnStatement(baseInvoke); + } else { + DoBeforeInvoke.Insert(0, + new CodeVariableDeclarationStatement(WrappedReturnType, "returnValue")); + doInvoke = + new CodeAssignStatement( + new CodeVariableReferenceExpression("returnValue"), + baseInvoke); + DoAfterInvoke.Add( + new CodeMethodReturnStatement( + new CodeVariableReferenceExpression("returnValue"))); + } + } else { + doInvoke = new CodeExpressionStatement(baseInvoke); + } + + codeMemberMethod.Statements.AddRange(DoBeforeInvoke.ToArray()); + codeMemberMethod.Statements.Add(doInvoke); + codeMemberMethod.Statements.AddRange(DoAfterInvoke.ToArray()); + codeMemberMethod.Parameters.AddRange(WrapperParams.ToArray()); + + return codeMemberMethod; + } + } + + class ParamContext + { + public string Name; + public bool IsWrapped; + public string WrappedType; + public Type RawType; + public CodeTypeReference TypeRef; + public FieldDirection Direction; + public CodeParameterDeclarationExpression ArgDeclaration; + public CodeArgumentReferenceExpression ArgRefExpression; + public CodeExpression UnwrappedArgExpression; + public CodeExpression UnwrappedDirectionalArgExpression; + + public ParamContext(CodeGenerator generator, ParameterInfo par) + { + Name = par.Name; + if (par.ParameterType.IsByRef) { + RawType = par.ParameterType.GetElementType(); + } else { + RawType = par.ParameterType; + } + + IsWrapped = generator.ShouldIncludeType(RawType); + WrappedType = IsWrapped ? RawType.Name : RawType.FullName; + TypeRef = new CodeTypeReference(WrappedType); + if (!par.ParameterType.IsByRef) { + Direction = FieldDirection.In; + } else if (par.IsOut) { + Direction = FieldDirection.Out; + } else { + Direction = FieldDirection.Ref; + } + + ArgDeclaration = new CodeParameterDeclarationExpression(); + ArgDeclaration.Type = TypeRef; + ArgDeclaration.Name = par.Name; + ArgDeclaration.Direction = Direction; + + ArgRefExpression = new CodeArgumentReferenceExpression(par.Name); + UnwrappedArgExpression = IsWrapped?generator.Unwrap(RawType, ArgRefExpression):ArgRefExpression; + UnwrappedDirectionalArgExpression = new CodeDirectionExpression(Direction, UnwrappedArgExpression); + } + } + + CodeMemberMethod MakeMember(MethodInfo method) + { + MethodContext methodContext = new MethodContext(this, method); + + foreach(ParameterInfo par in method.GetParameters()) { + ParamContext parContext = new ParamContext(this, par); + + if (parContext.IsWrapped) { + if (parContext.Direction == FieldDirection.In) { + if (par.ParameterType.IsArray) { + UnwrapArrayArgument(methodContext, parContext); + } else { + UnwrapArgument(methodContext, parContext); + } + } else { + UnwrapRefArgument(methodContext, parContext); + } + } else { + PassArgument(methodContext, parContext); + } + } + + return methodContext.Emit(); + } + + void PassArgument(MethodContext methodContext, ParamContext parContext) + { + methodContext.WrapperParams.Add(parContext.ArgDeclaration); + methodContext.BaseMethodInvokeParams.Add(parContext.UnwrappedDirectionalArgExpression); + } + + void UnwrapArgument(MethodContext methodContext, ParamContext parContext) + { + methodContext.WrapperParams.Add(parContext.ArgDeclaration); + methodContext.BaseMethodInvokeParams.Add(parContext.UnwrappedDirectionalArgExpression); + } + + void UnwrapRefArgument(MethodContext methodContext, ParamContext parContext) + { + methodContext.WrapperParams.Add(parContext.ArgDeclaration); + + CodeVariableDeclarationStatement tmpVariableDeclaration = new CodeVariableDeclarationStatement(parContext.RawType, ((parContext.Direction==FieldDirection.Ref)?"ref":"out") + "_" + parContext.Name); + if (parContext.Direction == FieldDirection.Ref) { + tmpVariableDeclaration.InitExpression = parContext.UnwrappedArgExpression; + } + CodeExpression tmpVariableExpression = new CodeVariableReferenceExpression(tmpVariableDeclaration.Name); + CodeExpression tmpVariableDirectionalExpression = new CodeDirectionExpression(parContext.Direction, tmpVariableExpression); + methodContext.DoBeforeInvoke.Add(tmpVariableDeclaration); + + methodContext.BaseMethodInvokeParams.Add(tmpVariableDirectionalExpression); + + CodeAssignStatement assignExpression = new CodeAssignStatement(parContext.ArgRefExpression, Wrap(parContext.RawType, tmpVariableExpression)); + methodContext.DoAfterInvoke.Add(assignExpression); + } + + void UnwrapArrayArgument(MethodContext methodContext, ParamContext parContext) + { + //OUTPUT: + // + // public void void__array(Test[] arg) + // { + // Debugger.Interop.CorDebug.Test[] array_arg = new Debugger.Interop.CorDebug.Test[arg.Length]; + // for (int i = 0; (i < arg.Length); i = (i + 1)) + // { + // if ((arg[i] != null)) + // { + // array_arg[i] = arg[i].WrappedObject; + // } + // } + // this.WrappedObject.void__array(array_arg); + // for (int i = 0; (i < arg.Length); i = (i + 1)) + // { + // if ((array_arg[i] != null)) + // { + // arg[i] = Test.Wrap(array_arg[i]); + // } else + // { + // arg[i] = null; + // } + // } + // } + + methodContext.WrapperParams.Add(parContext.ArgDeclaration); + + string rawArrayName = "array_" + parContext.Name; + + CodeExpression arg_Length = + // arg.Length + new CodePropertyReferenceExpression(parContext.ArgRefExpression, "Length"); + CodeExpression i = + // i + new CodeVariableReferenceExpression("i"); + CodeStatement loopInit = + // int i = 0 + new CodeVariableDeclarationStatement(typeof(int), "i", new CodePrimitiveExpression(0)); + CodeExpression loopCondition = + // (i < arg.Length) + new CodeBinaryOperatorExpression( + i, + CodeBinaryOperatorType.LessThan, + arg_Length); + CodeStatement loopIteration = + // i = (i + 1) + new CodeAssignStatement( + i, + new CodeBinaryOperatorExpression( + i, + CodeBinaryOperatorType.Add, + new CodePrimitiveExpression(1))); + CodeExpression arg_i = + // arg[i] + new CodeIndexerExpression( + parContext.ArgRefExpression, + i); + CodeVariableReferenceExpression array_arg = + // array_arg + new CodeVariableReferenceExpression(rawArrayName); + CodeExpression array_arg_i = + // array_arg[i] + new CodeIndexerExpression( + array_arg, + i); + + // Debugger.Interop.CorDebug.Test[] array_arg = new Debugger.Interop.CorDebug.Test[arg.Length]; + methodContext.DoBeforeInvoke.Add( + new CodeVariableDeclarationStatement( + new CodeTypeReference(parContext.RawType), + array_arg.VariableName, + new CodeArrayCreateExpression(parContext.RawType, arg_Length))); + + methodContext.DoBeforeInvoke.Add( + new CodeIterationStatement( + loopInit, + loopCondition, + loopIteration, + // if + new CodeConditionStatement( + // (arg[i] != null) + new CodeBinaryOperatorExpression( + arg_i, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression(null)), + // array_arg[i] = arg[i].WrappedObject; + new CodeAssignStatement( + array_arg_i, + Unwrap(parContext.RawType, arg_i))))); + + methodContext.DoAfterInvoke.Add( + new CodeIterationStatement( + loopInit, + loopCondition, + loopIteration, + // if + new CodeConditionStatement( + // (array_arg[i] != null) + new CodeBinaryOperatorExpression( + array_arg_i, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression(null)), + // + new CodeStatement [] { + // arg[i] = Test.Wrap(array_arg[i]); + new CodeAssignStatement( + arg_i, + Wrap( + parContext.RawType.Assembly.GetType(parContext.RawType.FullName.Replace("[]","")), + array_arg_i))}, + // else + new CodeStatement [] { + // arg[i] = null; + new CodeAssignStatement( + arg_i, + new CodePrimitiveExpression(null))}))); + + methodContext.BaseMethodInvokeParams.Add(array_arg); + } + } +} diff --git a/src/Tools/WrapperGenerator/CorDebugGenerator.cs b/src/Tools/WrapperGenerator/CorDebugGenerator.cs new file mode 100644 index 0000000000..2cf7645fa8 --- /dev/null +++ b/src/Tools/WrapperGenerator/CorDebugGenerator.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +using Microsoft.CSharp; + +namespace WrapperGenerator +{ + public class CorDebugGenerator: CodeGenerator + { + string namespaceToWrap = "Debugger.Interop.CorDebug"; + + public CorDebugGenerator(Assembly assembly):base(assembly) + { + wrapperNamespace = "Debugger.Wrappers.CorDebug"; + } + + protected override bool ShouldIncludeType(Type type) + { + return type.Namespace == namespaceToWrap && + (type.IsClass || type.IsInterface || type.IsEnum); + } + + protected override Type GetBaseClass(Type type) + { +// Type[] interfaces = type.GetInterfaces(); +// if (interfaces.Length > 0) { +// return interfaces[0]; +// } +// if (type.Name.EndsWith("2")) { +// return type.Assembly.GetType(type.FullName.Remove(type.FullName.Length - 1)); +// } + return null; + } + } +} diff --git a/src/Tools/WrapperGenerator/FileGenerator.cs b/src/Tools/WrapperGenerator/FileGenerator.cs new file mode 100644 index 0000000000..3c933b37f8 --- /dev/null +++ b/src/Tools/WrapperGenerator/FileGenerator.cs @@ -0,0 +1,69 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.IO; +using System.Reflection; + +using Microsoft.CSharp; + +namespace WrapperGenerator +{ + public class FileGenerator + { + CodeGenerator codeGenerator; + string header; + + public FileGenerator(CodeGenerator codeGenerator, string header) + { + this.codeGenerator = codeGenerator; + this.header = header; + } + + public string SaveFiles(string saveDirectory) + { + string allCode = ""; + + foreach(CodeCompileUnit compileUnit in codeGenerator.MakeCompileUnits()) { + string code = GenerateCode(compileUnit); + code = code.Remove(0, code.IndexOf("namespace")); + + allCode += code; + + string className = (string)compileUnit.UserData["filename"]; + + TextWriter textWriter = new StreamWriter(Path.Combine(saveDirectory, className + ".cs")); + textWriter.Write(header); + textWriter.Write(code); + textWriter.Close(); + } + + return allCode; + } + + string GenerateCode(CodeCompileUnit compileUnit) + { + CSharpCodeProvider provider = new CSharpCodeProvider(); + + TextWriter stringWriter = new StringWriter(); + + CodeGeneratorOptions options = new CodeGeneratorOptions(); + options.BlankLinesBetweenMembers = true; + options.BracingStyle = "C"; + options.ElseOnClosing = true; + options.IndentString = "\t"; + options.VerbatimOrder = true; + + provider.GenerateCodeFromCompileUnit(compileUnit, stringWriter, options); + + return stringWriter.ToString(); + } + } +} diff --git a/src/Tools/WrapperGenerator/MainForm.cs b/src/Tools/WrapperGenerator/MainForm.cs new file mode 100644 index 0000000000..09f242fba1 --- /dev/null +++ b/src/Tools/WrapperGenerator/MainForm.cs @@ -0,0 +1,85 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Drawing; +using System.IO; +using System.Reflection; +using System.Windows.Forms; + +using Microsoft.CSharp; + +namespace WrapperGenerator +{ + public class MainForm : System.Windows.Forms.Form + { + string header = + "// " + "\r\n" + + "// " + "\r\n" + + "// " + "\r\n" + + "// " + "\r\n" + + "// $Revision$" + "\r\n" + + "// " + "\r\n" + + "\r\n"; + //string dllFileName = Assembly.GetExecutingAssembly().Location; + string dllFileName = Path.Combine(Assembly.GetExecutingAssembly().Location, @"..\..\..\..\..\..\AddIns\AddIns\Misc\Debugger\Debugger.Core.dll"); + string saveDirectory = Path.Combine(Assembly.GetExecutingAssembly().Location, @"..\..\..\..\..\..\src\AddIns\Misc\Debugger\Debugger.Core\Project\Src\Wrappers\CorDebug"); + + public MainForm() + { + InitializeComponent(); + + CodeGenerator codeGenerator = new CorDebugGenerator(Assembly.LoadFile(dllFileName)); + textBox1.Text = new FileGenerator(codeGenerator, header).SaveFiles(saveDirectory); + } + + [STAThread] + public static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.Run(new MainForm()); + } + + #region Windows Forms Designer generated code + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 21F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(949, 717); + // + // textBox1 + // + textBox1.Dock = System.Windows.Forms.DockStyle.Fill; + textBox1.Location = new System.Drawing.Point(0, 0); + textBox1.Multiline = true; + textBox1.Name = "textBox1"; + textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + textBox1.Size = new System.Drawing.Size(949, 717); + textBox1.TabIndex = 0; + this.Controls.Add(textBox1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.PerformLayout(); + this.ResumeLayout(false); + } + private System.Windows.Forms.TextBox textBox1; + #endregion + } +} diff --git a/src/Tools/WrapperGenerator/MainForm.resources b/src/Tools/WrapperGenerator/MainForm.resources new file mode 100644 index 0000000000000000000000000000000000000000..06c24d06c1cab750788146ce052b37770f3fa530 GIT binary patch literal 180 zcmX?i>is@O1_p+SK%5g?SzMBus~417oL^d$oLUTL1*ImYq!#HY +// +// +// +// $Revision$ +// + +using System; + +namespace Debugger.Interop.CorDebug +{ + [Flags] + public enum Enumeration:byte { A = 1, B = 2, C = 4, D = 16 }; + + public interface Test { + // Return values + void void__void(); + + int int__void(); + + string string__void(); + + Test Test__void(); + + // Direction of parameter - base type + void void__inString(string str); + + void void__outString(out string str); + + void void__refString(ref string str); + + // Direction of parameter - wrapped type + void void__inTest(Test str); + + void void__outTest(out Test t); + + void void__refTest(ref Test t); + + // Direction of many parameters + return value - base type + void void__out_ref_in_out_ref__string(out string p1, ref string p2, string p3, out string p4, ref string p5); + + string string__out_ref_in_out_ref__string(out string p1, ref string p2, string p3, out string p4, ref string p5); + + // Direction of many parameters + return value - wrapped type + void void__out_ref_in_out_ref__Test(out Test p1, ref Test p2, Test p3, out Test p4, ref Test p5); + + Test Test__out_ref_in_out_ref__Test(out Test p1, ref Test p2, Test p3, out Test p4, ref Test p5); + + // Arrays + + void void__array(Test[] arg); + } +} diff --git a/src/Tools/WrapperGenerator/Wrapper.cs b/src/Tools/WrapperGenerator/Wrapper.cs new file mode 100644 index 0000000000..4da475dc0b --- /dev/null +++ b/src/Tools/WrapperGenerator/Wrapper.cs @@ -0,0 +1,25 @@ +// +// +// +// +// $Revision$ +// + +namespace Debugger.Wrappers.CorDebug +{ + using System; + + + public abstract class Wrapper : MarshalByRefObject + { + public abstract object WrappedObject + { + get; + } + + //public staticType WrappedObjectType + //{ + // get; + //} + } +} diff --git a/src/Tools/WrapperGenerator/WrapperGenerator.csproj b/src/Tools/WrapperGenerator/WrapperGenerator.csproj new file mode 100644 index 0000000000..2c4fdf1328 --- /dev/null +++ b/src/Tools/WrapperGenerator/WrapperGenerator.csproj @@ -0,0 +1,43 @@ + + + WinExe + WrapperGenerator + WrapperGenerator + Debug + AnyCPU + {7ED425D8-30CA-422C-90DF-1CB901E46DE3} + + + bin\Debug\ + False + DEBUG;TRACE + True + Full + True + + + bin\Release\ + True + TRACE + False + None + False + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Tools/WrapperGenerator/WrapperGenerator.sln b/src/Tools/WrapperGenerator/WrapperGenerator.sln new file mode 100644 index 0000000000..e88e7a4dbd --- /dev/null +++ b/src/Tools/WrapperGenerator/WrapperGenerator.sln @@ -0,0 +1,16 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.0.0.920 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WrapperGenerator", "WrapperGenerator.csproj", "{7ED425D8-30CA-422C-90DF-1CB901E46DE3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Release|Any CPU.Build.0 = Release|Any CPU + {7ED425D8-30CA-422C-90DF-1CB901E46DE3}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/Tools/WrapperGenerator/WrapperProxy.cs b/src/Tools/WrapperGenerator/WrapperProxy.cs new file mode 100644 index 0000000000..6466b2d444 --- /dev/null +++ b/src/Tools/WrapperGenerator/WrapperProxy.cs @@ -0,0 +1,87 @@ +// +// +// +// +// $Revision$ +// + +namespace Debugger.Wrappers.CorDebug +{ + using System; + using System.Collections; + using System.Reflection; + using System.Runtime.Remoting; + using System.Runtime.Remoting.Proxies; + using System.Runtime.Remoting.Messaging; + + + public class WrapperProxy : RealProxy, IRemotingTypeInfo + { + Hashtable wrappingClassCache = new Hashtable(); + + MarshalByRefObject wrappedComObject; + + public WrapperProxy(MarshalByRefObject objectToWrapp) : + base (typeof(MarshalByRefObject)) + { + wrappedObject = objectToWrapp; + } + + void GetWrappingClass(Type interfaceType) + { + object cachedItem = wrappingClassCache[interfaceType]; + if (cachedItem != null) { + return cachedItem; + } + + interfaceType.GetCustomAttributes(typeof(WrappingClassAttribute), false); + + // TODO + + Type wrappingClassType; + + object wrappingClass = Activator.CreateInstance(wrappingClassType, wrappedComObject); + + wrappingClassCache.Add(interfaceType, wrappingClass); + } + + public override IMessage Invoke(IMessage msg) + { + Type interfaceType = (msg as IMethodCallMessage).MethodBase.ReflectedType; + + MarshalByRefObject wrappingClass = GetWrappingClass(wrappingClassType); + + return RemotingServices.ExecuteMessage(wrappingClass, msg as IMethodCallMessage); + } + + public string TypeName { + get { + return wrappedObject.GetType().FullName; + } + set { + throw new NotImplementedException(); + } + } + + public bool CanCastTo(Type type, object o) + { + Wrapper wrappedObject = o as Wrapper; + + if (wrappedObject == null) { + return false; + } + + if (!type.IsSubclassOf(typeof(Wrapper))) { + return false; + } + + try { + Activator.CreateInstance(type, wrappedObject.WrappedObject); + return true; + } + catch { + return false; + } + } + } +} diff --git a/src/Tools/WrapperGenerator/WrappingClassAttribute.cs b/src/Tools/WrapperGenerator/WrappingClassAttribute.cs new file mode 100644 index 0000000000..6f1c7cbcd0 --- /dev/null +++ b/src/Tools/WrapperGenerator/WrappingClassAttribute.cs @@ -0,0 +1,17 @@ +// +// +// +// +// $Revision$ +// + +namespace Debugger.Wrappers.CorDebug +{ + using System; + + + public class WrappingClassAttribute + { + + } +}