예제 #1
0
        static IList <SyntaxTree> GetSyntaxTrees(RazorEngine engine, string rootDir, string[] filenames)
        {
            var codeDocs = GetCodeDocuments(rootDir, filenames);
            var tagNamesToSourceFiles = codeDocs
                                        .Where(cd => !string.IsNullOrEmpty(cd.Items["DetectedTagName"] as string))
                                        .ToDictionary(
                cd => cd.Items["DetectedTagName"] as string,
                cd => "./" + MakeRelativePath(rootDir, cd.Source.FileName).Replace('\\', '/'));

            foreach (var codeDoc in codeDocs)
            {
                codeDoc.Items["tagNamesToSourceFiles"] = tagNamesToSourceFiles;
                engine.Process(codeDoc);
            }

            return(codeDocs.Select(codeDoc =>
            {
                var csharpDocument = codeDoc.GetCSharpDocument();
                var generatedCode = csharpDocument.GeneratedCode;

                // If there's a better way to do this, it's not clear what it is. Don't see any public extension points
                // for this.
                generatedCode = "using System;using System.Collections.Generic;using System.Linq;using Blazor.Http;using Blazor.Util;using System.Threading.Tasks;\n" + generatedCode;
                generatedCode = generatedCode.Replace(
                    "public async override global::System.Threading.Tasks.Task ExecuteAsync()",
                    "protected override void RenderVirtualDom()");
                Log(generatedCode);

                var syntaxTree = CSharpSyntaxTree.ParseText(generatedCode);
                return syntaxTree;
            }).ToList());
        }
예제 #2
0
        static IList <SyntaxTree> GetSyntaxTrees(RazorEngine engine, string rootDir, string[] filenames)
        {
            var codeDocs = GetCodeDocuments(rootDir, filenames);
            var tagNamesToSourceFiles = codeDocs
                                        .Where(cd => !string.IsNullOrEmpty(cd.Items["DetectedTagName"] as string))
                                        .ToDictionary(
                cd => cd.Items["DetectedTagName"] as string,
                cd => "./" + MakeRelativePath(rootDir, cd.Source.FileName).Replace('\\', '/'));

            foreach (var codeDoc in codeDocs)
            {
                codeDoc.Items["tagNamesToSourceFiles"] = tagNamesToSourceFiles;
                engine.Process(codeDoc);
            }

            return(codeDocs.Select(codeDoc =>
            {
                var csharpDocument = codeDoc.GetCSharpDocument();
                var generatedCode = csharpDocument.GeneratedCode;
                var usingNamespaces = (IEnumerable <string>)codeDoc.Items["UsingNamespaces"];
                var allNamespaces = new List <string>
                {
                    "System",
                    "System.Collections.Generic",
                    "System.Linq",
                    "System.Net.Http",
                    "System.Threading.Tasks",
                    "Blazor.Util",
                };
                allNamespaces.AddRange(usingNamespaces);

                // If there's a better way to do this, it's not clear what it is. Don't see any public extension points
                // for this.
                generatedCode = string.Join(string.Empty, allNamespaces.Select(ns => $"using {ns};{Environment.NewLine}")) + generatedCode;
                generatedCode = generatedCode.Replace(
                    "public async override global::System.Threading.Tasks.Task ExecuteAsync()",
                    "protected override void RenderVirtualDom()");

                if ((bool)codeDoc.Items["DetectedPage"])
                {
                    if (codeDoc.Source.FileName.Contains("Validation"))
                    {
                        // TODO: very very temporary. Need to make this dynamic.
                        generatedCode = generatedCode.Replace(
                            "protected override void RenderVirtualDom()",
                            ValidationHack.GetValidationStuffToAppend() +
                            "protected override void RenderVirtualDom()");
                        generatedCode = @"using System.Reflection;
using System.ComponentModel.DataAnnotations; " + generatedCode;
                    }
                }

                Log(generatedCode);

                var syntaxTree = CSharpSyntaxTree.ParseText(generatedCode);
                return syntaxTree;
            }).ToList());
        }
예제 #3
0
        protected virtual Type Load(RazorSourceDocument source, string relativePath)
        {
            var document = _engine.CreateCodeDocument(source);

            var parsed = RazorParser.Parse(source);

            document.SetSyntaxTree(RazorParser.Parse(source));
            foreach (var error in parsed.Diagnostics)
            {
                document.ErrorSink.OnError(error);
            }

            AddVirtualDocuments(document, relativePath);

            var @namespace = GetNamespace(relativePath);
            var @class     = "Generated_" + Path.GetFileNameWithoutExtension(Path.GetFileName(relativePath));

            document.WithClassName(@namespace, @class);

            _engine.Process(document);
            if (document.ErrorSink.Errors.Any())
            {
                throw CreateException(document);
            }

            var compilation = CreateCompilation(@class, @namespace, relativePath, document.GetGeneratedCSharpDocument().GeneratedCode);
            var text        = compilation.SyntaxTrees[0].ToString();

            using (var pe = new MemoryStream())
            {
                using (var pdb = new MemoryStream())
                {
                    var emitResult = compilation.Emit(
                        peStream: pe,
                        pdbStream: pdb,
                        options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb));
                    if (!emitResult.Success)
                    {
                        throw CreateException(document, relativePath, text, compilation.AssemblyName, emitResult.Diagnostics);
                    }

                    pe.Seek(0, SeekOrigin.Begin);
                    pdb.Seek(0, SeekOrigin.Begin);

                    var assembly = LoadStream(pe, pdb);
                    var type     = assembly.GetExportedTypes().FirstOrDefault(a => !a.IsNested);
                    return(type);
                }
            }
        }
예제 #4
0
 public void Process(RazorCodeDocument document)
 => _engine.Process(document);
예제 #5
0
        protected void Generate()
        {
            Setup();

            var stringBuilder = new StringBuilder();

            stringBuilder.Append(@"namespace Razor.Orm.Template { 
                        internal static class GeneratedTemplateFactory {");

            foreach (var item in assembly.GetManifestResourceNames())
            {
                var name = item.Replace('.', '_');

                RazorSourceDocument razorSourceDocument = null;

                var stream = new MemoryStream();

                assembly.GetManifestResourceStream(item).CopyTo(stream);

                using (stream)
                    using (var writer = new StreamWriter(stream, Encoding.UTF8))
                    {
                        writer.WriteLine("@using System");
                        writer.WriteLine("@using System");
                        writer.WriteLine("@using System.Collections.Generic");
                        writer.WriteLine("@using System.Linq");
                        writer.WriteLine("@using System.Threading.Tasks");
                        writer.Flush();
                        stream.Position     = 0;
                        razorSourceDocument = RazorSourceDocument.ReadFrom(stream, name, Encoding.UTF8);
                    }

                var razorCodeDocument = RazorCodeDocument.Create(razorSourceDocument);
                engine.Process(razorCodeDocument);
                var generatedCode = razorCodeDocument.GetCSharpDocument().GeneratedCode;
                Parse(generatedCode);

                stringBuilder.Append($@"
                    private static {name}_GeneratedTemplate private_{name}_instance = new {name}_GeneratedTemplate();

                    internal static {name}_GeneratedTemplate {name}_Instance 
                    {{ 
                        get
                        {{
                            return private_{name}_instance;
                        }}
                    }} ");
            }

            stringBuilder.Append(" } }");

            var defaultTemplateFactoryCode = stringBuilder.ToString();

            Parse(defaultTemplateFactoryCode);

            var references = DependencyContext.Load(Assembly.GetEntryAssembly()).CompileLibraries.SelectMany(library => library.ResolveReferencePaths());

            if (!references.Any())
            {
                throw new Exception(Labels.CantLoadMetadataReferenceException);
            }

            var metadataRerefences = new List <MetadataReference>
            {
                AssemblyMetadata.CreateFromFile(assembly.Location).GetReference()
            };

            var libraryPaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var reference in references)
            {
                if (libraryPaths.Add(reference))
                {
                    using (var stream = File.OpenRead(reference))
                    {
                        metadataRerefences.Add(AssemblyMetadata.Create(ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata))
                                               .GetReference(filePath: reference));
                    }
                }
            }

            var compilation = CSharpCompilation.Create(assemblyName)
                              .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
                              .AddReferences(metadataRerefences).AddSyntaxTrees(syntaxTrees);

            using (var assemblyStream = new MemoryStream())
            {
                var result = compilation.Emit(assemblyStream);

                if (!result.Success)
                {
                    var diagnostics = new StringBuilder();

                    diagnostics.AppendLine(Labels.CompileException);

                    foreach (var diagnostic in result.Diagnostics.Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error))
                    {
                        var lineSpan = diagnostic.Location.SourceTree.GetMappedLineSpan(diagnostic.Location.SourceSpan);
                        diagnostics.AppendLine($"- ({lineSpan.StartLinePosition.Line}:{lineSpan.StartLinePosition.Character}) {diagnostic.GetMessage()}");
                    }

                    throw new Exception(diagnostics.ToString());
                }

                assemblyStream.Seek(0, SeekOrigin.Begin);

                var generatedAssembly = AssemblyLoadContext.Default.LoadFromStream(assemblyStream);

                foreach (var item in generatedAssembly.GetExportedTypes())
                {
                    GeneratedDao(types.First(e => e.IsAssignableFrom(item)), item);
                }
            }
        }