Browse Source

Extension method generator for COM types. It converts out parameters to return values and allows tracking of created objects.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5130 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
e4dbd77923
  1. 3423
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebugExtensionMethods.cs
  2. 1227
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorSymExtensionMethods.cs
  3. 239
      src/Tools/ComExtensionMethodGenerator/ComExtensionMethodGenerator.cs
  4. 45
      src/Tools/ComExtensionMethodGenerator/ComExtensionMethodGenerator.csproj
  5. 18
      src/Tools/ComExtensionMethodGenerator/ComExtensionMethodGenerator.sln
  6. 31
      src/Tools/ComExtensionMethodGenerator/Properties/AssemblyInfo.cs

3423
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebugExtensionMethods.cs

File diff suppressed because it is too large Load Diff

1227
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorSymExtensionMethods.cs

File diff suppressed because it is too large Load Diff

239
src/Tools/ComExtensionMethodGenerator/ComExtensionMethodGenerator.cs

@ -0,0 +1,239 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Parser.CSharp;
using ICSharpCode.NRefactory.PrettyPrinter;
using System.Reflection;
namespace ComExtensionMethodGenerator
{
public class Program
{
static string header =
"// <file>" + "\r\n" +
"// <copyright see=\"prj:///doc/copyright.txt\"/>" + "\r\n" +
"// <license see=\"prj:///doc/license.txt\"/>" + "\r\n" +
"// <owner name=\"David Srbecký\" email=\"dsrbecky@gmail.com\"/>" + "\r\n" +
"// <version>$Revision$</version>" + "\r\n" +
"// </file>" + "\r\n" + "\r\n";
static string path = Path.Combine(Assembly.GetExecutingAssembly().Location, @"..\..\..\..\..\..\src\AddIns\Misc\Debugger\Debugger.Core\Project\Src\Interop\");
public static void Main(string[] args)
{
new ComExtensionMethodGenerator() {
InputFile = path + "CorDebug.cs",
OutputFile = path + "CorDebugExtensionMethods.cs",
Header = header,
Namespace = "Debugger.Interop.CorDebug",
TypeName = "CorDebugExtensionMethods",
}.Generate();
new ComExtensionMethodGenerator() {
InputFile = path + "CorSym.cs",
OutputFile = path + "CorSymExtensionMethods.cs",
Header = header,
Namespace = "Debugger.Interop.CorSym",
TypeName = "CorSymExtensionMethods",
}.Generate();
}
}
public class ComExtensionMethodGenerator
{
public string InputFile;
public string OutputFile;
public string Header;
public string Namespace;
public string TypeName = "ExtensionMethods";
public string ThisParameterName = "instance";
public bool ProcessOutParameter = true;
public string ProcessOutParameterMethodName = "ProcessOutParameter";
public string[] ProcessOutParameterIgnores = new string[] { "System.Int32", "System.UInt32", "System.Int64", "System.UInt64", "System.Boolean", "Guid" };
public bool ConvertOutParameterToReturn = true;
public string ReturnValueName = "returnValue";
public string Generate()
{
// Parse the source code
IParser parser = ParserFactory.CreateParser(InputFile);
parser.Parse();
// Prepare the output
CompilationUnit generated = new CompilationUnit();
if (Header != null)
generated.AddChild(new IdentifierExpression(Header));
foreach(UsingDeclaration usingDec in parser.CompilationUnit.Children.OfType<UsingDeclaration>()) {
generated.AddChild(usingDec);
}
if (generated.Children.OfType<UsingDeclaration>().Count() > 0)
generated.AddChild(new IdentifierExpression("\r\n"));
TypeDeclaration extensionMethodsType = new TypeDeclaration(Modifiers.Public | Modifiers.Static, new List<AttributeSection>()) { Name = TypeName };
generated.AddChild(
Namespace == null ?
(INode)extensionMethodsType :
new NamespaceDeclaration(Namespace) { Children = extensionMethodsType.ToList<INode>() }
);
// Add the ProcessOutParameter method
if (ProcessOutParameter) {
extensionMethodsType.AddChild(
new MethodDeclaration() {
Modifier = Modifiers.Static,
TypeReference = new TypeReference("void", true),
Name = ProcessOutParameterMethodName,
Parameters =
new ParameterDeclarationExpression(
new TypeReference("object", true),
"parameter"
).ToList(),
Body = new BlockStatement()
}
);
extensionMethodsType.AddChild(new IdentifierExpression("\t\t\r\n"));
}
// Add the extesion methods
foreach(NamespaceDeclaration ns in parser.CompilationUnit.Children.OfType<NamespaceDeclaration>()) {
foreach(TypeDeclaration type in ns.Children.OfType<TypeDeclaration>()) {
foreach(MethodDeclaration method in type.Children.OfType<MethodDeclaration>()) {
MethodDeclaration extensionMethod = new MethodDeclaration();
// Signature
extensionMethod.Modifier = Modifiers.Public | Modifiers.Static;
extensionMethod.TypeReference = method.TypeReference;
extensionMethod.Name = method.Name;
extensionMethod.IsExtensionMethod = true;
// Parameters
extensionMethod.Parameters.Add(new ParameterDeclarationExpression(new TypeReference(type.Name), ThisParameterName));
foreach(ParameterDeclarationExpression param in method.Parameters) {
ParameterDeclarationExpression newParam = new ParameterDeclarationExpression(param.TypeReference, param.ParameterName) { ParamModifier = param.ParamModifier };
extensionMethod.Parameters.Add(newParam);
}
// Invocation
extensionMethod.Body = new BlockStatement();
InvocationExpression invoc = new InvocationExpression(
new MemberReferenceExpression(new IdentifierExpression(ThisParameterName), method.Name)
);
// Generate arguments
foreach(ParameterDeclarationExpression param in method.Parameters) {
// Add argument to invocation
if (param.ParamModifier == ParameterModifiers.Ref) {
invoc.Arguments.Add(new DirectionExpression(FieldDirection.Ref, new IdentifierExpression(param.ParameterName)));
} else if (param.ParamModifier == ParameterModifiers.Out) {
invoc.Arguments.Add(new DirectionExpression(FieldDirection.Out, new IdentifierExpression(param.ParameterName)));
} else {
invoc.Arguments.Add(new IdentifierExpression(param.ParameterName));
}
// Call ProcessOutParameter
if (ProcessOutParameter) {
if (param.ParamModifier == ParameterModifiers.Ref ||
param.ParamModifier == ParameterModifiers.Out ||
param.TypeReference.IsArrayType)
{
if (!ProcessOutParameterIgnores.Contains(param.TypeReference.Type)) {
extensionMethod.Body.AddChild(
new ExpressionStatement(
new InvocationExpression(
new IdentifierExpression(ProcessOutParameterMethodName),
new IdentifierExpression(param.ParameterName).ToList<Expression>()
)
)
);
}
}
}
}
// Process return value
if (method.TypeReference.Type == typeof(void).FullName) {
extensionMethod.Body.Children.Insert(0, new ExpressionStatement(invoc));
} else {
if (!ProcessOutParameter ||
ProcessOutParameterIgnores.Contains(method.TypeReference.Type))
{
extensionMethod.Body.Children.Insert(0, new ReturnStatement(invoc));
} else {
// Declare and get return value
extensionMethod.Body.Children.Insert(0,
new LocalVariableDeclaration(
new VariableDeclaration(ReturnValueName, invoc, method.TypeReference)
)
);
// Call ProcessOutParameter
extensionMethod.Body.AddChild(
new ExpressionStatement(
new InvocationExpression(
new IdentifierExpression(ProcessOutParameterMethodName),
new IdentifierExpression(ReturnValueName).ToList<Expression>()
)
)
);
// Return it
extensionMethod.Body.AddChild(
new ReturnStatement(new IdentifierExpression(ReturnValueName))
);
}
}
// Convert out parameter to return value
if (ConvertOutParameterToReturn &&
method.TypeReference.Type == typeof(void).FullName &&
extensionMethod.Parameters.Count > 0 &&
extensionMethod.Parameters.Last().ParamModifier == ParameterModifiers.Out &&
extensionMethod.Parameters.Where(p => p.ParamModifier == ParameterModifiers.Out).Count() == 1)
{
ParameterDeclarationExpression param = extensionMethod.Parameters.Last();
// Change signature
extensionMethod.TypeReference = param.TypeReference;
extensionMethod.Parameters.Remove(param);
// Define local variable instead
extensionMethod.Body.Children.Insert(
0,
new LocalVariableDeclaration(
new VariableDeclaration(param.ParameterName, Expression.Null, param.TypeReference)
)
);
// Return it
extensionMethod.Body.AddChild(
new ReturnStatement(new IdentifierExpression(param.ParameterName))
);
}
extensionMethodsType.AddChild(extensionMethod);
extensionMethodsType.AddChild(new IdentifierExpression("\t\t\r\n"));
}
}
}
// Pretty print
CSharpOutputVisitor csOut = new CSharpOutputVisitor();
csOut.VisitCompilationUnit(generated, null);
string output = csOut.Text;
// Save to file
if (OutputFile != null) {
File.WriteAllText(OutputFile, output);
}
return output;
}
}
static class ExtensionMethods
{
public static List<T> ToList<T>(this T obj)
{
List<T> list = new List<T>(1);
list.Add(obj);
return list;
}
}
}

45
src/Tools/ComExtensionMethodGenerator/ComExtensionMethodGenerator.csproj

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{38FD49E0-97FB-4015-B294-557291C708E8}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Exe</OutputType>
<RootNamespace>ComExtensionMethodGenerator</RootNamespace>
<AssemblyName>ComExtensionMethodGenerator</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>True</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="ICSharpCode.NRefactory">
<HintPath>..\..\..\bin\ICSharpCode.NRefactory.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ComExtensionMethodGenerator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

18
src/Tools/ComExtensionMethodGenerator/ComExtensionMethodGenerator.sln

@ -0,0 +1,18 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 10
# SharpDevelop 4.0.0.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComExtensionMethodGenerator", "ComExtensionMethodGenerator.csproj", "{38FD49E0-97FB-4015-B294-557291C708E8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{38FD49E0-97FB-4015-B294-557291C708E8}.Debug|x86.Build.0 = Debug|x86
{38FD49E0-97FB-4015-B294-557291C708E8}.Debug|x86.ActiveCfg = Debug|x86
{38FD49E0-97FB-4015-B294-557291C708E8}.Release|x86.Build.0 = Release|x86
{38FD49E0-97FB-4015-B294-557291C708E8}.Release|x86.ActiveCfg = Release|x86
EndGlobalSection
EndGlobal

31
src/Tools/ComExtensionMethodGenerator/Properties/AssemblyInfo.cs

@ -0,0 +1,31 @@
#region Using directives
using System;
using System.Reflection;
using System.Runtime.InteropServices;
#endregion
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ComExtensionMethodGenerator")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ComExtensionMethodGenerator")]
[assembly: AssemblyCopyright("Copyright 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
Loading…
Cancel
Save