//public const string TemplateFileExtension = ".ate"; //ToDo Move this to a config file in a project folder //public static List<string> AutoTemplateExtensions = new List<string> { "*.cs", "*.sln", "*.csproj", "*.html", "*.js", "*.ts", "*.json", "*.cshtml", "*.wsd", "*.puml", "*.project", "*.java" , "*.sql" , "*.yaml", "*.xml", "*.yml", "*.md", "*.txt", "*.name"}; internal static void Compile(CompileContext CompileContext, FileInfo FileInfo) { var FileName = FileInfo.Name; if (FileName.StartsWithTags(Template.Tags, "inject ", out var Tag)) { var InjectionName = FileName.Substring(Tag.Key.Length + 7); InjectionName = InjectionName.Substring(0, InjectionName.IndexOf(Tag.Value)); var CodeSegment = CompileContext.Template.FindOrCreateCodeSegment(InjectionName); CodeSegment.Code = FileInfo.ReadAllText(); } else if (FileName.ContainsTags(Template.Tags, "ignore")) { //Do nothing } else { var PreviousTopSegment = CompileContext.Stack.Peek(); Text.Compile(CompileContext, FileName); var FileSegment = new FileSegment(); FileSegment.SourceFile = FileInfo; var TopSegment = CompileContext.Stack.Peek(); TopSegment.Segments.Add(FileSegment); FileSegment.Class = TopSegment.Class; if (FileName.ContainsTags(Template.Tags, "no overwrite")) { FileSegment.OverWrite = false; } else { FileSegment.OverWrite = true; } if (FileInfo.Name.FitsMasks(CompileContext.Template.CompileMasks.ToList())) { CompileContext.Stack.Push(FileSegment); Text.Compile(CompileContext, System.IO.File.ReadAllText(FileInfo.FullName)); } while (CompileContext.Stack.Peek() != PreviousTopSegment) { CompileContext.Stack.Pop(); } } }
/// <summary> /// Adds text and enum segments to Context /// </summary> /// <param name="CompileContext"></param> /// <param name="SourceText"></param> internal static void Compile(CompileContext CompileContext, string SourceText) { var bits = SourceText.Split(Template.Tags.Values.ToArray(), StringSplitOptions.None); foreach (var bit in bits) { string StaticText; string Code; //string Name; var TopSegment = CompileContext.Stack.Peek(); int Opening = bit.IndexOfTags(Template.Tags, out var Tag); if (Opening > -1) { StaticText = bit.Substring(0, Opening); Code = bit.Substring(Opening + Tag.Key.Length); Code = Code.Trim(); if (Code.IndexOf(Tag.Key) >= 0) { throw new Exception("template syntax error in " + SourceText + " at position " + SourceText.IndexOf(bit) + ": " + bit); } //Name = "M" + Guid.NewGuid().ToString().Replace("-", ""); } else { StaticText = bit; Code = ""; //Name = ""; } StaticText = StaticText.Replace("App_FullCodeName", "App.FullCodeName"); Code = Code.Replace("ʢ", "("); Code = Code.Replace("ʡ", ")"); Code = Code.Replace("ℴ", "."); if (Code.Length > 9 && Code.Substring(0, 9) == "for each ") { var ListSegment = new ListSegment(); //ListSegment.MethodName = Name; ListSegment.StaticText = StaticText; Code = Code.Substring(9); var Alias = ""; var SubTypeName = ""; var AsIndex = Code.IndexOf(" as "); if (AsIndex >= 0) { SubTypeName = Code.Substring(0, AsIndex); Alias = Code.Substring(AsIndex + 4, Code.IndexOf(" in ", AsIndex) - AsIndex - 4); } else { SubTypeName = Code.Substring(0, Code.IndexOf(" in ")); Alias = SubTypeName; } Code = Code.Substring(Code.IndexOf(" in ") + 4); // Code = Code.Substring(9); // var SubTypeName = Code.Substring(0, Code.IndexOf(" in ")); // Code = Code.Substring(Code.IndexOf("in") + 3); ListSegment.ParentClass = TopSegment.Class; var Type = ListSegment.ParentClass.BaseType.Assembly.ExportedTypes.Where( (FindType) => FindType.Name == SubTypeName ).FirstOrDefault(); if (Type == null) { throw new System.Exception("Type not found for " + SubTypeName); } ListSegment.Class = CompileContext.Template.FindOrCreateClass(Type); //ListSegment.ParentClass.MethodSegments.Add(ListSegment); ListSegment.Method = ListSegment.ParentClass.FindOrCreateMethod(Code, TopSegment.ClassAlias, typeof(System.Collections.IEnumerable), ListSegment.Source); ListSegment.ClassAlias = Alias; TopSegment.Segments.Add(ListSegment); CompileContext.Stack.Push(ListSegment); } else if (Code.Length >= 3 && Code.Substring(0, 3) == "if ") { var IfSegment = new IfSegment(); IfSegment.StaticText = StaticText; Code = Code.Substring(3); IfSegment.Class = TopSegment.Class; IfSegment.Method = IfSegment.Class.FindOrCreateMethod(Code, TopSegment.ClassAlias, typeof(bool), IfSegment.Source); TopSegment.Segments.Add(IfSegment); CompileContext.Stack.Push(IfSegment); } else if (Code.Length >= 8 && Code.Substring(0, 8) == "else if ") { var TextSegment = new TextSegment(TopSegment); TextSegment.StaticText = StaticText; TopSegment.Segments.Add(TextSegment); var ElseIfSegment = new IfSegment(); ElseIfSegment.StaticText = ""; Code = Code.Substring(8); ElseIfSegment.Class = TopSegment.Class; ElseIfSegment.Method = ElseIfSegment.Class.FindOrCreateMethod(Code, TopSegment.ClassAlias, typeof(bool), ElseIfSegment.Source); //TopSegment.Segments.Add(ElseIfSegment); ((IfSegment)TopSegment).ElseSegment = ElseIfSegment; CompileContext.Stack.Push(ElseIfSegment); } else if (Code == "else") { var TextSegment = new TextSegment(TopSegment); TextSegment.StaticText = StaticText; TopSegment.Segments.Add(TextSegment); var ElseSegment = new TextSegment(TopSegment); ElseSegment.StaticText = ""; ElseSegment.Class = TopSegment.Class; //TopSegment.Segments.Add(ElseSegment); ((IfSegment)TopSegment).ElseSegment = ElseSegment; CompileContext.Stack.Push(ElseSegment); } else if (Code.Length >= 9 && Code.Substring(0, 9) == "overwrite") { Code = ""; } else if (Code.Length >= 6 && Code.Substring(0, 6) == "ignore") { Code = ""; } else if (Code.Length > 7 && Code.Substring(0, 7) == "inject ") { var InjectionName = Code.Substring(7); var NamePosition = InjectionName.IndexOf(" "); var InjectionCode = InjectionName.Substring(NamePosition); InjectionName = InjectionName.Substring(0, NamePosition); var CodeSegment = CompileContext.Template.FindOrCreateCodeSegment(InjectionName); CodeSegment.Code = InjectionCode; } else { if (Code.Length >= 4 && Code.Substring(0, 4) == "next") { CompileContext.Stack.Pop(); //TopSegment = CompileContext.Stack.Peek(); //ToDo Check that next type matches current for each // if (!ListSegment.GetType().IsAssignableFrom(typeof(ListSegment))) // { // throw new Exception("for each doesn't match with code grouping"); // } Code = ""; } else if (Code.Length >= 6 && Code.Substring(0, 6) == "end if") { var IfSegment = CompileContext.Stack.Pop(); var TopPeek = CompileContext.Stack.Peek(); while (TopPeek.GetType() == typeof(IfSegment) && ((IfSegment)TopPeek).ElseSegment == IfSegment) { IfSegment = CompileContext.Stack.Pop(); TopPeek = CompileContext.Stack.Peek(); } //TopSegment = CompileContext.Stack.Peek(); // if (!IfSegment.GetType().IsAssignableFrom(typeof(IfSegment))) // { // throw new Exception("end if doesn't match with code grouping"); // } Code = ""; } var TextSegment = new TextSegment(TopSegment); TextSegment.StaticText = StaticText; TopSegment.Segments.Add(TextSegment); TextSegment.Class = TopSegment.Class; if (Code != "") { TextSegment.Method = TextSegment.Class.FindOrCreateMethod(Code, TopSegment.ClassAlias, typeof(string), TextSegment.Source); } } } }
//Processes Folder name and then sub folders and then sub files internal static FolderSegment Compile(CompileContext CompileContext, DirectoryInfo DirectoryInfo) { var PreviousTopSegment = CompileContext.Stack.Peek(); Text.Compile(CompileContext, DirectoryInfo.Name); var FolderSegment = new FolderSegment(); FolderSegment.SourceDirectory = DirectoryInfo; var TopSegment = CompileContext.Stack.Peek(); TopSegment.Segments.Add(FolderSegment); FolderSegment.Class = TopSegment.Class; FolderSegment.OverWrite = false; // if (DirectoryInfo.Name.ContainsTags(Template.Tags, "overwrite false")) // { // FolderSegment.OverWrite = false; // } // else // { // FolderSegment.OverWrite = true; // } CompileContext.Stack.Push(FolderSegment); //var DirectoryInfo = new DirectoryInfo(Source); foreach (var ChildDirectory in DirectoryInfo.GetDirectories()) { bool ignoreDirectory = false; string fullname = ChildDirectory.FullName.Replace("\\", "/"); foreach (var ignoreMask in CompileContext.Template.IgnoreMasks) { if ((fullname + "/").FitsMask(ignoreMask)) { ignoreDirectory = true; break; } } if (!ignoreDirectory) { Compile(CompileContext, ChildDirectory); } } foreach (var ChildFile in DirectoryInfo.GetFiles()) { bool ignoreFile = false; string fullname = ChildFile.FullName.Replace("\\", "/"); foreach (var ignoreMask in CompileContext.Template.IgnoreMasks) { if (fullname.FitsMask(ignoreMask)) { ignoreFile = true; break; } } if (!ignoreFile) { File.Compile(CompileContext, ChildFile); } } while (CompileContext.Stack.Peek() != PreviousTopSegment) { CompileContext.Stack.Pop(); } return(FolderSegment); }
private void Compile(string Source) { var CompileContext = new CompileContext(); CompileContext.Template = this; BaseSegment = new Segment(); BaseSegment.Class = FindOrCreateClass(Type); CompileContext.Stack.Push(BaseSegment); //Create a new in memory assembly with classes that inherit from Core Object Model Classes with added functions that contain code from templates //if source is a file then compile it straight //if, however, it is a folder then compile the folder and file names if (Directory.Exists(Source)) { var DirectoryInfo = new DirectoryInfo(Source); ReadIgnoreFile(DirectoryInfo); ReadCompileFile(DirectoryInfo); var FolderSegment = Folder.Compile(CompileContext, DirectoryInfo); FolderSegment.IsTopLevel = true; FolderSegment.OverWrite = false; } else if (System.IO.File.Exists(Source)) { File.Compile(CompileContext, new FileInfo(Source)); } else { Text.Compile(CompileContext, Source); } string TemplateCode = "using System;\nusing System.Linq;\nusing System.Collections;\nusing ate.Extensions;\nusing ate.Projects;\nusing ate.Definitions;\n\n namespace N" + Guid.NewGuid().ToString().CodeName() + " { "; List <SyntaxTree> SyntaxTrees = new List <SyntaxTree>(); foreach (var CodeSegment in CodeSegments.Values) { SyntaxTrees.Add(CSharpSyntaxTree.ParseText(CodeSegment.Code)); } foreach (var Class in Classes.Values) { TemplateCode += Class.CompiledCode(); } TemplateCode += "\n}"; var assemblyName = ".atecode"; System.IO.File.WriteAllText(Path.Combine(Source, assemblyName + ".cs"), TemplateCode); SyntaxTrees.Add(CSharpSyntaxTree.ParseText(TemplateCode)); List <MetadataReference> References = new List <MetadataReference>(); References.Add(MetadataReference.CreateFromFile(typeof(Object).Assembly.Location)); References.Add(MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)); References.Add(MetadataReference.CreateFromFile(typeof(IEnumerable).Assembly.Location)); var EntryAssembly = Assembly.GetEntryAssembly(); foreach (var AssemblyName in EntryAssembly.GetReferencedAssemblies()) { var ReferencedAssembly = Assembly.Load(AssemblyName.FullName); References.Add(MetadataReference.CreateFromFile(ReferencedAssembly.Location)); } var ExecutingAssembly = Assembly.GetExecutingAssembly(); foreach (var AssemblyName in ExecutingAssembly.GetReferencedAssemblies()) { var ReferencedAssembly = Assembly.Load(AssemblyName.FullName); References.Add(MetadataReference.CreateFromFile(ReferencedAssembly.Location)); } foreach (var AssemblyName in Type.Assembly.GetReferencedAssemblies()) { var ReferencedAssembly = Assembly.Load(AssemblyName.FullName); References.Add(MetadataReference.CreateFromFile(ReferencedAssembly.Location)); } References.Add(MetadataReference.CreateFromFile(Type.Assembly.Location)); CSharpCompilation compilation = CSharpCompilation.Create( assemblyName, syntaxTrees: SyntaxTrees, references: References, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using (var ms = new MemoryStream()) { EmitResult result = compilation.Emit(ms); if (!result.Success) { IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (Diagnostic diagnostic in failures) { try { Console.WriteLine("{0}: {1} at {2}\n{3}", diagnostic.Id, diagnostic.GetMessage(), diagnostic.Location.SourceSpan.Start, diagnostic.Location.SourceTree.ToString().Substring(diagnostic.Location.SourceSpan.Start, diagnostic.Location.SourceTree.ToString().IndexOf(Environment.NewLine, diagnostic.Location.SourceSpan.Start) - diagnostic.Location.SourceSpan.Start)); } catch (Exception) { Console.WriteLine("{0}: {1} at {2}\n{3}", diagnostic.Id, diagnostic.GetMessage(), diagnostic.Location.SourceSpan.Start, diagnostic.Location.SourceTree.ToString()); } } throw new Exception("Compile error"); } else { ms.Seek(0, SeekOrigin.Begin); //Assembly = System.Reflection.Assembly.Load(ms.ToArray()); Assembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(ms); } } foreach (var Class in Classes.Values) { Class.CompiledType = Assembly.GetExportedTypes().Where( (FindType) => FindType.Name == Class.BaseType.Name ).FirstOrDefault(); } Console.WriteLine("Successfully compiled"); }