Skip to content

Commit

Permalink
Import custom tool, refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
zpqrtbnk committed Oct 27, 2013
1 parent 5db560a commit e4f99c5
Show file tree
Hide file tree
Showing 51 changed files with 2,197 additions and 140 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ obj
*.suo
*.user
packages
refs
16 changes: 16 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/ClassNameExtractor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.IO;

namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public static class ClassNameExtractor
{
public static string GetClassName(string wszInputFilePath)
{
if (!File.Exists(wszInputFilePath))
throw new FileNotFoundException();

var fileInfo = new FileInfo(wszInputFilePath);
return fileInfo.Name.Replace(fileInfo.Extension, string.Empty);
}
}
}
206 changes: 206 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/CodeDomCodeGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.CSharp;

namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class CodeDomCodeGenerator : CodeGenerator, IDisposable
{
private readonly TypeAttributes? classAccessibility;
private readonly VisualStudioVersion visualStudioVersion;
private readonly string className;
private readonly CodeNamespace codeNamespace;
private readonly CodeCompileUnit compileUnit;
private readonly CodeDomProvider provider;

public CodeDomCodeGenerator(IResourceParser resourceParser,
string className,
string defaultNamespace,
CodeDomProvider codeDomProvider = null,
TypeAttributes? classAccessibility = null,
VisualStudioVersion visualStudioVersion = VisualStudioVersion.VS2012)
: base(resourceParser, defaultNamespace)
{
this.className = className;
this.classAccessibility = classAccessibility;
this.visualStudioVersion = visualStudioVersion;
compileUnit = new CodeCompileUnit();
provider = codeDomProvider ?? new CSharpCodeProvider();
codeNamespace = new CodeNamespace(defaultNamespace);
}

public override string GenerateCode()
{
codeNamespace.Comments.Add(
new CodeCommentStatement("--------------------------------------------------------------------------------------------------"));
codeNamespace.Comments.Add(new CodeCommentStatement("<auto-generatedInfo>"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tThis code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tResW File Code Generator was written by Christian Resma Helle"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tand is under GNU General Public License version 2 (GPLv2)"));
codeNamespace.Comments.Add(new CodeCommentStatement(string.Empty));
codeNamespace.Comments.Add(new CodeCommentStatement("\tThis code contains a helper class exposing property representations"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tof the string resources defined in the specified .ResW file"));
codeNamespace.Comments.Add(new CodeCommentStatement(string.Empty));
codeNamespace.Comments.Add(new CodeCommentStatement("\tGenerated: " + DateTime.Now.ToString(CultureInfo.InvariantCulture)));
codeNamespace.Comments.Add(new CodeCommentStatement("</auto-generatedInfo>"));
codeNamespace.Comments.Add(
new CodeCommentStatement("--------------------------------------------------------------------------------------------------"));

codeNamespace.Imports.Add(new CodeNamespaceImport("Windows.ApplicationModel.Resources"));

var targetClass = new CodeTypeDeclaration(className)
{
IsClass = true,
IsPartial = true,
TypeAttributes = classAccessibility.HasValue ? classAccessibility.Value : TypeAttributes.Public
};

const string resourceLoaderType = "ResourceLoader";
var resourceLoaderField = new CodeMemberField(resourceLoaderType, "resourceLoader")
{
Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final
};
targetClass.Members.Add(resourceLoaderField);

var constructor = new CodeTypeConstructor();

var executingAssemblyVar = new CodeVariableDeclarationStatement(typeof (string), "executingAssemblyName");
var executingAssemblyInit = new CodeAssignStatement(new CodeVariableReferenceExpression("executingAssemblyName"),
new CodeSnippetExpression("Windows.UI.Xaml.Application.Current.GetType().AssemblyQualifiedName"));
var executingAssemblySplit = new CodeVariableDeclarationStatement(typeof (string[]), "executingAssemblySplit");
var executingAssemblyInit2 = new CodeAssignStatement(new CodeVariableReferenceExpression("executingAssemblySplit"),
new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("executingAssemblyName"),
"Split",
new CodePrimitiveExpression(',')));
var executingAssemblyInit3 = new CodeAssignStatement(new CodeVariableReferenceExpression("executingAssemblyName"),
new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("executingAssemblySplit"),
new CodePrimitiveExpression(1)));

var currentAssemblyVar = new CodeVariableDeclarationStatement(typeof (string), "currentAssemblyName");
var currentAssemblyInit = new CodeAssignStatement(new CodeVariableReferenceExpression("currentAssemblyName"),
new CodePropertyReferenceExpression(new CodeTypeOfExpression(className), "AssemblyQualifiedName"));
var currentAssemblySplit = new CodeVariableDeclarationStatement(typeof (string[]), "currentAssemblySplit");
var currentAssemblyInit2 = new CodeAssignStatement(new CodeVariableReferenceExpression("currentAssemblySplit"),
new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("currentAssemblyName"),
"Split",
new CodePrimitiveExpression(',')));
var currentAssemblyInit3 = new CodeAssignStatement(new CodeVariableReferenceExpression("currentAssemblyName"),
new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("currentAssemblySplit"),
new CodePrimitiveExpression(1)));

var createResourceLoader = new CodeConditionStatement(
new CodeSnippetExpression("executingAssemblyName.Equals(currentAssemblyName)"),
new CodeStatement[] // true
{
visualStudioVersion == VisualStudioVersion.VS2013
? new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("ResourceLoader"),
"GetForCurrentView",
new CodeSnippetExpression("\"" + className + "\"")))
: new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeObjectCreateExpression(new CodeTypeReference("ResourceLoader"),
new CodeSnippetExpression("\"" + className + "\"")))
},
new CodeStatement[] // false
{
visualStudioVersion == VisualStudioVersion.VS2013
? new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("ResourceLoader"),
"GetForCurrentView",
new CodeSnippetExpression("currentAssemblyName + \"/" + className + "\"")))
: new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeObjectCreateExpression(new CodeTypeReference("ResourceLoader"),
new CodeSnippetExpression("currentAssemblyName + \"/" + className + "\"")))
});

constructor.Statements.Add(executingAssemblyVar);
constructor.Statements.Add(executingAssemblyInit);
constructor.Statements.Add(executingAssemblySplit);
constructor.Statements.Add(executingAssemblyInit2);
constructor.Statements.Add(executingAssemblyInit3);
constructor.Statements.Add(currentAssemblyVar);
constructor.Statements.Add(currentAssemblyInit);
constructor.Statements.Add(currentAssemblySplit);
constructor.Statements.Add(currentAssemblyInit2);
constructor.Statements.Add(currentAssemblyInit3);
constructor.Statements.Add(createResourceLoader);

targetClass.Members.Add(constructor);

var resources = ResourceParser.Parse();
foreach (var item in resources)
{
if (string.IsNullOrEmpty(item.Name) || item.Name.Contains("."))
continue;

var property = new CodeMemberProperty
{
Name = item.Name.Trim(),
Attributes = MemberAttributes.Public | MemberAttributes.Static,
HasGet = true,
Type = new CodeTypeReference(typeof (string))
};

property.Comments.Add(new CodeCommentStatement("<summary>", true));
property.Comments.Add(new CodeCommentStatement("Localized resource similar to \"" + (item.Value ?? item.Name) + "\"", true));
property.Comments.Add(new CodeCommentStatement("</summary>", true));
property.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeMethodInvokeExpression(
new CodeFieldReferenceExpression(null, "resourceLoader"),
"GetString",
new CodePrimitiveExpression(item.Name))));

targetClass.Members.Add(property);
}

codeNamespace.Types.Add(targetClass);
compileUnit.Namespaces.Add(codeNamespace);

return GenerateCodeFromCompileUnit();
}

private string GenerateCodeFromCompileUnit()
{
var options = new CodeGeneratorOptions {BracingStyle = "C"};

var code = new StringBuilder();

using (var writer = new StringWriter(code))
provider.GenerateCodeFromCompileUnit(compileUnit, writer, options);

return code.ToString();
}

#region IDisposable

private bool disposed;

public void Dispose()
{
Dispose(true);
}

~CodeDomCodeGenerator()
{
Dispose(false);
}

protected virtual void Dispose(bool dispose)
{
if (disposed)
return;
disposed = true;

if (dispose)
provider.Dispose();
}

#endregion
}
}
16 changes: 16 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/CodeGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public abstract class CodeGenerator : ICodeGenerator
{
protected CodeGenerator(IResourceParser resourceParser, string defaultNamespace)
{
ResourceParser = resourceParser;
Namespace = defaultNamespace;
}

public IResourceParser ResourceParser { get; set; }
public string Namespace { get; set; }

public abstract string GenerateCode();
}
}
14 changes: 14 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/CodeGeneratorFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;

namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class CodeGeneratorFactory
{
public ICodeGenerator Create(string className, string defaultNamespace, string inputFileContents, CodeDomProvider codeDomProvider = null, TypeAttributes? classAccessibility = null)
{
return new CodeDomCodeGenerator(new ResourceParser(inputFileContents), className, defaultNamespace, codeDomProvider, classAccessibility);
}
}
}
9 changes: 9 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/ICodeGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public interface ICodeGenerator
{
IResourceParser ResourceParser { get; set; }
string Namespace { get; set; }
string GenerateCode();
}
}
10 changes: 10 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/IResourceParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Collections.Generic;

namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public interface IResourceParser
{
string ReswFileContents { get; set; }
List<ResourceItem> Parse();
}
}
9 changes: 9 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/ResourceItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class ResourceItem
{
public string Name { get; set; }
public string Value { get; set; }
public string Comment { get; set; }
}
}
53 changes: 53 additions & 0 deletions Zbu.ModelsBuilder.CustomTool/CustomTool/ResourceParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class ResourceParser : IResourceParser
{
public ResourceParser(string reswFileContents)
{
ReswFileContents = reswFileContents;
}

public string ReswFileContents { get; set; }

public List<ResourceItem> Parse()
{
var doc = XDocument.Parse(ReswFileContents);

var list = new List<ResourceItem>();

foreach (var element in doc.Descendants("data"))
{
if (element.Attributes().All(c => c.Name != "name"))
continue;

var item = new ResourceItem();

var nameAttribute = element.Attribute("name");
if (nameAttribute != null)
item.Name = nameAttribute.Value;

if (element.Descendants().Any(c => c.Name == "value"))
{
var valueElement = element.Descendants("value").FirstOrDefault();
if (valueElement != null)
item.Value = valueElement.Value;
}

if (element.Descendants().Any(c => c.Name == "comment"))
{
var commentElement = element.Descendants("comment").FirstOrDefault();
if (commentElement != null)
item.Comment = commentElement.Value;
}

list.Add(item);
}

return list;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.CodeDom;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.CSharp;

namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
[Guid("151F74CA-404D-4188-B994-D7683C32ACF4")]
[ComVisible(true)]
public class ReswFileCSharpCodeGeneratorInternal : ReswFileCodeGenerator
{
public ReswFileCSharpCodeGeneratorInternal()
: base(new CSharpCodeProvider(), TypeAttributes.NestedAssembly)
{
}

public override int DefaultExtension(out string pbstrDefaultExtension)
{
pbstrDefaultExtension = ".cs";
return 0;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;

namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
[Guid("92DFB543-7138-419B-99D9-90CC77607671")]
[ComVisible(true)]
public class ReswFileVisualBasicCodeGenerator : ReswFileCodeGenerator
{
public ReswFileVisualBasicCodeGenerator()
: base(new VBCodeProvider())
{
}

public override int DefaultExtension(out string pbstrDefaultExtension)
{
pbstrDefaultExtension = ".vb";
return 0;
}
}
}
Loading

0 comments on commit e4f99c5

Please sign in to comment.