/// <summary> /// Gets the parsed template code. /// </summary> /// <returns>The C# code created from the template functions.</returns> public static string ParseTemplateFileCSharp() { var sb = new StringBuilder(1000); string namespaces = ""; // Get Designer version info string versionNumber; { Assembly designerAssembly = Assembly.GetAssembly(typeof(CompileHelper)); versionNumber = designerAssembly.GetName().Version.ToString(); } // Create namespace list for (int i = 0; i < Project.Instance.Namespaces.Count; i++) { if (Project.Instance.Namespaces[i].Trim().Length > 0) { namespaces += "using " + Project.Instance.Namespaces[i] + ";\n"; } } if (RandomiseTheNamespace) { NamespaceUsed = Project.Instance.ProjectNamespace + RandomNamespaceNumber++; } else { NamespaceUsed = Project.Instance.ProjectNamespace; } string versioningInfo = string.Format( "[assembly: AssemblyVersion(\"{1}\")]{0}[assembly: AssemblyFileVersion(\"{1}\")]{0}[assembly: AssemblyInformationalVersion(\"{2}\")]{0}[assembly: AssemblyProduct(\"Compiled by ArchAngel Designer Version {2}\")]{0}", Environment.NewLine, (string.IsNullOrEmpty(Project.Instance.Version) ? "0.0.0.0" : Project.Instance.Version), versionNumber); sb.Append(@" " + namespaces + @" using System.Reflection; using System.Collections.Generic; " + versioningInfo + @" namespace " + NamespaceUsed + @" {"); #region ScriptFunctionWrappers_String sb.Append( @" public class ScriptFunctionWrapper : ArchAngel.Interfaces.ScriptFunctionWrapper { "); #region RunScriptFunction sb.Append( @" private string GetParamTypeString(object[] parameters) { StringBuilder sb = new StringBuilder(100); foreach (object parameter in parameters) { sb.Append(parameter.GetType().FullName + "",""); } return sb.ToString().TrimEnd(',').Replace(""+"", "".""); } private static TemplateGen instance = new TemplateGen(); public override object RunScriptFunction(string functionName, ref object[] parameters) { object result = null; switch (functionName) { "); var functionComparer = new Comparers.FunctionComparer(); Project.Instance.Functions.Sort(functionComparer); string prevFunctionName = ""; for (int functionCounter = 0; functionCounter < Project.Instance.Functions.Count; functionCounter++) { FunctionInfo fi = Project.Instance.Functions[functionCounter]; if (fi.IsExtensionMethod) continue; DefaultValueFunction defaultValueFunction = Project.Instance.FindDefaultValueFunction(fi.Name, fi.Parameters); if (defaultValueFunction != null) continue; //if (defaultValueFunction != null && !defaultValueFunction.UseCustomCode) //{ // continue; //} string unboxedString = ""; string localVariables = ""; string callee = "TemplateGen"; if (fi.IsTemplateFunction) callee = "instance"; for (int i = 0; i < fi.Parameters.Count; i++) { localVariables += string.Format("{0} {2}param{3}_{1} = ({0})parameters[{1}];", Utility.GetDemangledGenericTypeName(fi.Parameters[i].DataType), i, fi.Name, functionCounter); if (i > 0) { unboxedString += ", "; } unboxedString += string.Format("{1} {2}param{3}_{0}", i, fi.Parameters[i].Modifiers, fi.Name, functionCounter); } // Check whether the function is overloaded - add inner switch if it is bool functionIsOverloaded = Project.Instance.FindFunctions(fi.Name).Count > 1; if (!functionIsOverloaded || !Utility.StringsAreEqual(prevFunctionName, Project.Instance.Functions[functionCounter].Name, true)) { // This is the first function with this name sb.AppendFormat("case \"{0}\":", fi.Name); if (functionIsOverloaded) { sb.Append(@" switch (GetParamTypeString(parameters)) {"); } } prevFunctionName = Project.Instance.Functions[functionCounter].Name; if (functionIsOverloaded) { sb.AppendFormat("case \"{0}\":", GetParamTypeString(Project.Instance.Functions[functionCounter].Parameters)); } if (fi.ReturnType != null && fi.ReturnType.FullName != "System.Void") { sb.Append(@" " + localVariables + @" result = " + callee + "." + fi.Name + @"(" + unboxedString + @"); "); } else { sb.Append(@" " + localVariables + @" " + callee + "." + fi.Name + @"(" + unboxedString + @"); result = null; "); } for (int i = 0; i < fi.Parameters.Count; i++) { sb.Append(string.Format("parameters[{0}] = {1}param{2}_{0};", i, fi.Name, functionCounter)); } sb.Append( @" break; "); if (functionIsOverloaded && (functionCounter == Project.Instance.Functions.Count - 1 || (functionCounter < Project.Instance.Functions.Count - 1 && Project.Instance.Functions[functionCounter].Name != Project.Instance.Functions[functionCounter + 1].Name))) { // This is the last overloaded function with this name //firstFuncWithName = true; sb.Append(@"} break;"); } } #region Wrap calls to Dynamic Filenames foreach (OutputFile file in Project.Instance.GetAllFiles()) { string paramString = string.IsNullOrEmpty(file.IteratorTypes) ? "" : string.Format("({0})parameters[0]", file.IteratorTypes); string[] parts = file.Name.Split('#'); int numAdded = 0; for (int partCounter = 0; partCounter < parts.Length; partCounter++) { if (partCounter % 2 == 1) { sb.AppendFormat( @" case ""DynamicFilenames.File_{0}_{1}"": return TemplateGen.DynamicFilenames.File_{0}_{1}({2}); ", file.Id, numAdded, paramString); numAdded++; } } } #endregion #region Wrap calls to Dynamic FolderNames foreach (OutputFolder folder in Project.Instance.GetAllFolders()) { string paramString = folder.IteratorType == null ? "" : string.Format("({0})parameters[0]", folder.IteratorType.FullName); string[] parts = folder.Name.Split('#'); int numAdded = 0; for (int partCounter = 0; partCounter < parts.Length; partCounter++) { if (partCounter % 2 == 1) { sb.AppendFormat( @" case ""DynamicFolderNames.Folder_{0}_{1}"": return TemplateGen.DynamicFolderNames.Folder_{0}_{1}({2}); ", folder.Id, numAdded, paramString); numAdded++; } } } #endregion sb.Append( @" case ""InternalFunctions.MustSkipCurrentFile"": return instance.SkipCurrentFile; case ""InternalFunctions.ResetSkipCurrentFile"": instance.SkipCurrentFile = false; return null; case ""InternalFunctions.GetCurrentFileName"": return instance.CurrentFileName; case ""InternalFunctions.ResetCurrentFileName"": instance.CurrentFileName = """"; return null; case ""InternalFunctions.SetGeneratedFileName"": instance.GeneratedFileName = (string)parameters[0]; return null; case ""InternalFunctions.ClearTemplateCache"": instance.ClearTemplateCache(); return null; default: throw new Exception(""Function not handled in RunScriptFunction:""+ functionName); } return result; } "); #endregion #region RunApiExtensionFunction sb.Append( @" public override bool RunApiExtensionFunction(string functionName, out object result, ref object[] parameters) { result = null; functionName = functionName.Replace(""."", ""_""); switch (functionName) { "); prevFunctionName = ""; foreach (ApiExtensionMethod extensionMethod in Project.Instance.ApiExtensions) { if (!extensionMethod.HasOverride) { continue; } string unboxedString = ""; string localVariables = ""; var method = extensionMethod.ExtendedMethod; var parameters = method.GetParameters(); for (int i = 0; i < parameters.Length; i++) { localVariables += string.Format("{0} {2}param{1} = ({0})parameters[{1}];", Utility.GetDemangledGenericTypeName(parameters[i].ParameterType), i, method.Name); if (i > 0) { unboxedString += ", "; } unboxedString += string.Format("{1} {2}param{0}", i, GetModifiers(parameters[i]), method.Name); } // Check whether the function is overloaded - add inner switch if it is bool functionIsOverloaded = Project.Instance.FindFunctions(method.Name).Count > 1; if (!Utility.StringsAreEqual(prevFunctionName, method.Name, true)) { // This is the first function with this name sb.AppendFormat("case \"{0}\":", method.Name); if (functionIsOverloaded) { sb.Append(@" switch (GetParamTypeString(parameters)) {"); } } prevFunctionName = method.Name; if (functionIsOverloaded) { sb.AppendFormat("case \"{0}\":", GetParamTypeString(parameters)); } sb.Append( /*string.Format("case \"{0}\":", func.Name) +*/ @" " + localVariables + @" result = ApiExtensionMethods." + GetApiExtensionMethodName(extensionMethod) + @"(" + unboxedString + @"); "); for (int i = 0; i < parameters.Length; i++) { sb.Append(string.Format("parameters[{0}] = {1}param{0};", i, method.Name)); } sb.Append( @" return true; "); } sb.Append( @" default: return false; } } "); #endregion sb.Append(@" }"); #endregion #region LanguageAttribute sb.Append( @" [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true) ] public class LanguageAttribute : Attribute { public LanguageAttribute(string language) { this.language = language; } protected string language; public String Language { get { return this.language; } } public override string ToString() { return language; } } "); #endregion InsertApiExtensionClass(sb, Project.Instance.ApiExtensions); // These need to go outside TemplateGen, as extension methods must be in a non-generic, static classes #region Extension Methods sb.Append(@" public static class TemplateGenExtensionMethods { "); foreach (var fi in Project.Instance.Functions) { if (fi.IsExtensionMethod == false) continue; /* Create Method Signature */ sb.AppendLine("[Language(\"" + fi.TemplateReturnLanguage + "\")]"); sb.AppendFormat("\t\t\tpublic static {0} {1}(", fi.ReturnType == null ? "void" : fi.ReturnType.FullName, fi.Name); // Create parameter list sb.Append(FormatParameters(fi.Parameters)).AppendLine(")"); sb.AppendLine("\t\t\t{"); sb.AppendLine(FormatFunctionBody(fi)); sb.AppendLine("\t\t\t}"); } sb.Append(@" } "); #endregion InsertVirtualProperties(sb, Project.Instance.UserOptions); //InsertDefaultValueFunctions(sb); InsertTemplateGenClass(sb); // Finish the namespace off sb.AppendLine( @" } "); // Fill the Line Number lookup objects with the information they need, // and remove debugging information. FillFunctionHashes(); return ProcessLineCrossReferences(sb); }
/// <summary> /// Sorts the functions into alphabetical order /// </summary> public void SortFunctions() { // Sort the functions Comparers.FunctionComparer comparer = new Comparers.FunctionComparer(); Functions.Sort(comparer); }