Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.1@2196 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
3 changed files with 219 additions and 0 deletions
@ -0,0 +1,190 @@ |
|||||||
|
<?xml version="1.0"?> |
||||||
|
<Template originator = "Daniel Grunwald"> |
||||||
|
|
||||||
|
<!-- Template Header --> |
||||||
|
<TemplateConfiguration> |
||||||
|
<Name>Custom Tool</Name> |
||||||
|
<Category>C#</Category> |
||||||
|
<Subcategory>SharpDevelop</Subcategory> |
||||||
|
<Icon>C#.Project.ControlLibrary</Icon> |
||||||
|
<Description>A custom tool that implements a code generator transforming a source file into an output file whenever the source is changed inside SharpDevelop</Description> |
||||||
|
</TemplateConfiguration> |
||||||
|
|
||||||
|
<!-- Actions --> |
||||||
|
<Actions> |
||||||
|
<Open filename = "${ProjectName}.addin"/> |
||||||
|
</Actions> |
||||||
|
|
||||||
|
<Project language="C#"> |
||||||
|
<ProjectItems> |
||||||
|
<Reference Include="System" /> |
||||||
|
<Reference Include="System.Data" /> |
||||||
|
<Reference Include="System.Drawing" /> |
||||||
|
<Reference Include="System.Windows.Forms" /> |
||||||
|
<Reference Include="System.Xml" /> |
||||||
|
</ProjectItems> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<OutputType>Library</OutputType> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
<Files> |
||||||
|
<File name="${ProjectName}.addin" CopyToOutputDirectory="Always"><![CDATA[<AddIn name = "${ProjectName}" |
||||||
|
author = "${USER}" |
||||||
|
url = "" |
||||||
|
description = "TODO: Put description here"> |
||||||
|
|
||||||
|
<Runtime> |
||||||
|
<Import assembly = "${ProjectName}.dll"/> |
||||||
|
</Runtime> |
||||||
|
|
||||||
|
<!-- make SharpDevelop look for file templates in your AddIn's directory --> |
||||||
|
<Path name = "/SharpDevelop/BackendBindings/Templates"> |
||||||
|
<Directory id = "${ProjectName}Template" path = "." /> |
||||||
|
</Path> |
||||||
|
|
||||||
|
<Path name = "/SharpDevelop/CustomTools"> |
||||||
|
<!-- |
||||||
|
Register the custom tool. |
||||||
|
id: ID used to identify the custom tool. This ID will be used in project files to reference your generator. |
||||||
|
class: fully qualified name of a class in your assembly that implements ICustomTool |
||||||
|
fileNamePattern: a regular expression. For file names matched by this regex, SharpDevelop will display |
||||||
|
your custom tool in the drop down box of the property grid when a file with that extension |
||||||
|
is selected. |
||||||
|
--> |
||||||
|
<CustomTool id = "${ProjectName}Generator" |
||||||
|
class = "${StandardNamespace}.${ProjectName}Tool" |
||||||
|
fileNamePattern = "\.xml$"/> |
||||||
|
</Path> |
||||||
|
</AddIn> |
||||||
|
]]></File> |
||||||
|
<File name="${ProjectName}Tool.cs"> |
||||||
|
<![CDATA[${StandardHeader.C#} |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using System.CodeDom; |
||||||
|
using System.Xml; |
||||||
|
using ICSharpCode.EasyCodeDom; // defined in ICSharpCode.SharpDevelop.Dom.dll |
||||||
|
using ICSharpCode.SharpDevelop.Project; // defined in ICSharpCode.SharpDevelop.dll |
||||||
|
|
||||||
|
namespace ${StandardNamespace} |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Description of CustomTool. |
||||||
|
/// </summary> |
||||||
|
public class ${ProjectName}Tool : ICustomTool |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Called by SharpDevelop when your tool has to generate code. |
||||||
|
/// </summary> |
||||||
|
/// <param name="item"> |
||||||
|
/// The file for which your tool should generate code. |
||||||
|
/// </param> |
||||||
|
public void GenerateCode(FileProjectItem item, CustomToolContext context) |
||||||
|
{ |
||||||
|
// make SharpDevelop generate a name for the output file |
||||||
|
string outputFileName = context.GetOutputFileName(item, ".Generated"); |
||||||
|
// if item.FileName is "C:\somedir\SomeName.xml" and is inside a C# project, |
||||||
|
// the output name will be "C:\somedir\SomeName.Generated.cs". |
||||||
|
// context.GetOutputFileName will always append the extension for compilable files in |
||||||
|
// the current project type, so if you want to always output xml, you could use |
||||||
|
// string outputFileName = Path.ChangeExtension(item.FileName, ".Generated.xml"); |
||||||
|
|
||||||
|
// now read the input file: |
||||||
|
XmlDocument doc = new XmlDocument(); |
||||||
|
doc.Load(item.FileName); |
||||||
|
|
||||||
|
// and generate the code using System.CodeDom: |
||||||
|
CodeCompileUnit ccu = GenerateCode(doc, context.OutputNamespace, Path.GetFileNameWithoutExtension(item.FileName)); |
||||||
|
|
||||||
|
// Finally save our generated CodeDom compile unit. SharpDevelop will take care of generating |
||||||
|
// the code using the correct CodeDomProvider for the project type. This means code-generating |
||||||
|
// custom tools are completely language-independent |
||||||
|
context.WriteCodeDomToFile(item, outputFileName, ccu); |
||||||
|
// If you don't want to generate code, you'll have to write the output file yourself and then use |
||||||
|
// context.EnsureOutputFileIsInProject to add the generated file to the project if it isn't already |
||||||
|
// part of it. |
||||||
|
} |
||||||
|
|
||||||
|
CodeCompileUnit GenerateCode(XmlDocument doc, string targetNamespace, string className) |
||||||
|
{ |
||||||
|
// This method does the actual code generation. |
||||||
|
|
||||||
|
// This sample accepts an object graph as XmlDocument and outputs a class with a static method |
||||||
|
// constructing that object graph. |
||||||
|
|
||||||
|
// We'll use ICSharpCode.EasyCodeDom for code generation. This is a small wrapper around CodeDom |
||||||
|
// that provides convenience methods that create new objects and add them to the parent simultaniously. |
||||||
|
// This makes the generation code much more concise. |
||||||
|
// EasyCodeDom classes derive from the System.CodeDom types or have an implicit conversion operator, so |
||||||
|
// use can use EasyCodeDom objects whereever CodeDom is expected. |
||||||
|
EasyCompileUnit ccu = new EasyCompileUnit(); |
||||||
|
EasyTypeDeclaration generatedClass = ccu.AddNamespace(targetNamespace).AddType(className); |
||||||
|
EasyMethod m = generatedClass.AddMethod("Create"); |
||||||
|
m.ReturnType = Easy.TypeRef(doc.DocumentElement.Name); |
||||||
|
m.Attributes = MemberAttributes.Static | MemberAttributes.Public; |
||||||
|
|
||||||
|
// now generate code. helper variables will be named "v#" |
||||||
|
int helperVariableCounter = 0; |
||||||
|
string rootVariableName = GenerateCodeForObject(m.Body, doc.DocumentElement, ref helperVariableCounter); |
||||||
|
|
||||||
|
// generate "return v0;" |
||||||
|
m.Body.Return(Easy.Var(rootVariableName)); |
||||||
|
|
||||||
|
return ccu; |
||||||
|
} |
||||||
|
|
||||||
|
string GenerateCodeForObject(EasyBlock block, XmlElement objectElement, ref int helperVariableCounter) |
||||||
|
{ |
||||||
|
// generate code to create the object represented by "objectElement" and add it to the block |
||||||
|
|
||||||
|
// generate "VarType v#;" |
||||||
|
CodeVariableDeclarationStatement varDecl; |
||||||
|
varDecl = block.DeclareVariable(Easy.TypeRef(objectElement.Name), "v" + helperVariableCounter); |
||||||
|
helperVariableCounter += 1; |
||||||
|
|
||||||
|
// generate "VarType v# = new VarType();" |
||||||
|
varDecl.InitExpression = Easy.New(Easy.TypeRef(objectElement.Name)); |
||||||
|
|
||||||
|
// translate XML attribute to assignments to properties |
||||||
|
foreach (XmlAttribute attribute in objectElement.Attributes) { |
||||||
|
// generate 'v#.attributeName = "attributeValue";' |
||||||
|
// attribute.Value is a string, thus Easy.Prim creates a string literal. |
||||||
|
// This simple code generator does not support using other types for attributes. |
||||||
|
block.Assign(Easy.Var(varDecl.Name).Property(attribute.Name), |
||||||
|
Easy.Prim(attribute.Value)); |
||||||
|
} |
||||||
|
|
||||||
|
foreach (XmlNode collectionNode in objectElement.ChildNodes) { |
||||||
|
XmlElement collectionElement = collectionNode as XmlElement; |
||||||
|
if (collectionElement != null) { |
||||||
|
foreach (XmlNode itemNode in collectionElement.ChildNodes) { |
||||||
|
XmlElement itemElement = itemNode as XmlElement; |
||||||
|
if (itemElement != null) { |
||||||
|
// add the object represented by "itemElement" to the collection represented by |
||||||
|
// "collectionElement". |
||||||
|
|
||||||
|
// generate code to create child object |
||||||
|
string childVariableName = GenerateCodeForObject(block, itemElement, ref helperVariableCounter); |
||||||
|
|
||||||
|
// generate 'v#.collectionName.Add(v##)' |
||||||
|
block.InvokeMethod(Easy.Var(varDecl.Name).Property(collectionElement.Name), |
||||||
|
"Add", |
||||||
|
Easy.Var(childVariableName)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return varDecl.Name; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
]]></File> |
||||||
|
<File name="FileTemplate.xft" src="SharpDevelopCustomToolTemplate.xft.xml" binary="true" CopyToOutputDirectory="Always"/> |
||||||
|
<File name="AssemblyInfo.cs" src="DefaultAssemblyInfo.cs"/> |
||||||
|
</Files> |
||||||
|
</Project> |
||||||
|
</Template> |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
<?xml version="1.0"?> |
||||||
|
<Template author="-" version="1.0"> |
||||||
|
<Config |
||||||
|
name = "CustomTool Template" |
||||||
|
icon = "Icons.32x32.XMLFileIcon" |
||||||
|
category = "${res:Templates.File.Categories.Misc}" |
||||||
|
defaultname = "CustomToolTemplate${Number}.xml" |
||||||
|
language = "XML"/> |
||||||
|
|
||||||
|
<Description>A file template for ${ProjectName}</Description> |
||||||
|
|
||||||
|
<Files> |
||||||
|
<File name="${FullName}" language="XML"><![CDATA[<?xml version="1.0"?> |
||||||
|
<Form Text = "Form title"> |
||||||
|
<Controls> |
||||||
|
<Button Text = "Click me"/> |
||||||
|
<Panel> |
||||||
|
<Controls> |
||||||
|
<Label Text = "A Label"/> |
||||||
|
<Button Text = "Another button"/> |
||||||
|
</Controls> |
||||||
|
</Panel> |
||||||
|
</Controls> |
||||||
|
</Form>]]> |
||||||
|
</File> |
||||||
|
</Files> |
||||||
|
</Template> |
||||||
Loading…
Reference in new issue