/// <summary>
        /// Gets an ordered <see cref="IReadOnlyList{ChunkTreeResult}"/> of parsed <see cref="ChunkTree"/>s and
        /// file paths for each <c>_ViewImports</c> that is applicable to the page located at
        /// <paramref name="pagePath"/>. The list is ordered so that the <see cref="ChunkTreeResult"/>'s
        /// <see cref="ChunkTreeResult.ChunkTree"/> for the <c>_ViewImports</c> closest to the
        /// <paramref name="pagePath"/> in the file system appears first.
        /// </summary>
        /// <param name="pagePath">The path of the page to locate inherited chunks for.</param>
        /// <returns>A <see cref="IReadOnlyList{ChunkTreeResult}"/> of parsed <c>_ViewImports</c>
        /// <see cref="ChunkTree"/>s and their file paths.</returns>
        /// <remarks>
        /// The resulting <see cref="IReadOnlyList{ChunkTreeResult}"/> is ordered so that the result
        /// for a _ViewImport closest to the application root appears first and the _ViewImport
        /// closest to the page appears last i.e.
        /// [ /_ViewImport, /Views/_ViewImport, /Views/Home/_ViewImport ]
        /// </remarks>
        public virtual IReadOnlyList<ChunkTreeResult> GetInheritedChunkTreeResults(string pagePath)
        {
            if (pagePath == null)
            {
                throw new ArgumentNullException(nameof(pagePath));
            }

            var inheritedChunkTreeResults = new List<ChunkTreeResult>();
            var templateEngine = new RazorTemplateEngine(_razorHost);
            foreach (var viewImportsPath in ViewHierarchyUtility.GetViewImportsLocations(pagePath))
            {
                // viewImportsPath contains the app-relative path of the _ViewImports.
                // Since the parsing of a _ViewImports would cause parent _ViewImports to be parsed
                // we need to ensure the paths are app-relative to allow the GetGlobalFileLocations
                // for the current _ViewImports to succeed.
                var chunkTree = _chunkTreeCache.GetOrAdd(
                    viewImportsPath,
                    fileInfo => ParseViewFile(
                        templateEngine,
                        fileInfo,
                        viewImportsPath));

                if (chunkTree != null)
                {
                    var result = new ChunkTreeResult(chunkTree, viewImportsPath);
                    inheritedChunkTreeResults.Insert(0, result);
                }
            }

            return inheritedChunkTreeResults;
        }
        /// <summary>
        /// Gets an ordered <see cref="IReadOnlyList{T}"/> of parsed <see cref="ChunkTree"/> for each
        /// <c>_ViewImports</c> that is applicable to the page located at <paramref name="pagePath"/>. The list is
        /// ordered so that the <see cref="ChunkTree"/> for the <c>_ViewImports</c> closest to the
        /// <paramref name="pagePath"/> in the file system appears first.
        /// </summary>
        /// <param name="pagePath">The path of the page to locate inherited chunks for.</param>
        /// <returns>A <see cref="IReadOnlyList{ChunkTree}"/> of parsed <c>_ViewImports</c>
        /// <see cref="ChunkTree"/>s.</returns>
        public virtual IReadOnlyList<ChunkTree> GetInheritedChunkTrees([NotNull] string pagePath)
        {
            var inheritedChunkTrees = new List<ChunkTree>();
            var templateEngine = new RazorTemplateEngine(_razorHost);
            foreach (var viewImportsPath in ViewHierarchyUtility.GetViewImportsLocations(pagePath))
            {
                // viewImportsPath contains the app-relative path of the _ViewImports.
                // Since the parsing of a _ViewImports would cause parent _ViewImports to be parsed
                // we need to ensure the paths are app-relative to allow the GetGlobalFileLocations
                // for the current _ViewImports to succeed.
                var chunkTree = _chunkTreeCache.GetOrAdd(
                    viewImportsPath,
                    fileInfo => ParseViewFile(
                        templateEngine,
                        fileInfo,
                        viewImportsPath));

                if (chunkTree != null)
                {
                    inheritedChunkTrees.Add(chunkTree);
                }
            }

            return inheritedChunkTrees;
        }
Example #3
0
 /// <inheritdoc />
 public GeneratorResults GenerateCode(string rootRelativePath, Stream inputStream)
 {
     // Adding a prefix so that the main view class can be easily identified.
     var className = MainClassNamePrefix + ParserHelpers.SanitizeClassName(rootRelativePath);
     var engine = new RazorTemplateEngine(this);
     return engine.GenerateCode(inputStream, className, DefaultNamespace, rootRelativePath);
 }
Example #4
0
        /// <summary>
        /// Generates code for a razor template in the specified namespace.
        /// </summary>
        /// <param name="cshtmlFilePath">Full path to razor template.</param>
        /// <param name="rootNamespace">Root namespace for razor-generated class.</param>
        private void GenerateCodeFile(string cshtmlFilePath, string rootNamespace)
        {
            var basePath = Path.GetDirectoryName(cshtmlFilePath);
            var fileName = Path.GetFileName(cshtmlFilePath);
            var fileNameNoExtension = Path.GetFileNameWithoutExtension(fileName);
            var codeLang = new CSharpRazorCodeLanguage();
            var host = new RazorEngineHost(codeLang);
            host.GeneratedClassContext = new GeneratedClassContext(
                executeMethodName: GeneratedClassContext.DefaultExecuteMethodName,
                writeMethodName: GeneratedClassContext.DefaultWriteMethodName,
                writeLiteralMethodName: GeneratedClassContext.DefaultWriteLiteralMethodName,
                writeToMethodName: "WriteTo",
                writeLiteralToMethodName: "WriteLiteralTo",
                templateTypeName: "HelperResult",
                defineSectionMethodName: "DefineSection",
                generatedTagHelperContext: new GeneratedTagHelperContext());
            var engine = new RazorTemplateEngine(host);

            using (var fileStream = File.OpenText(cshtmlFilePath))
            {
                var code = engine.GenerateCode(
                    input: fileStream,
                    className: fileNameNoExtension,
                    rootNamespace: rootNamespace,
                    sourceFileName: fileName);

                var source = code.GeneratedCode;
                source = CopyrightHeader + "\r\n\r\n" + source;
                var startIndex = 0;
                while (startIndex < source.Length)
                {
                    var startMatch = @"<%$ include: ";
                    var endMatch = @" %>";
                    startIndex = source.IndexOf(startMatch, startIndex);
                    if (startIndex == -1)
                    {
                        break;
                    }
                    var endIndex = source.IndexOf(endMatch, startIndex);
                    if (endIndex == -1)
                    {
                        break;
                    }
                    var includeFileName = source.Substring(startIndex + startMatch.Length,
                        endIndex - (startIndex + startMatch.Length));
                    Console.WriteLine("    Inlining file {0}", includeFileName);
                    var replacement =
                        File.ReadAllText(Path.Combine(basePath, includeFileName))
                            .Replace("\"", "\\\"")
                            .Replace("\r\n", "\\r\\n");
                    source = source.Substring(0, startIndex) + replacement +
                             source.Substring(endIndex + endMatch.Length);
                    startIndex = startIndex + replacement.Length;
                }
                File.WriteAllText(Path.Combine(basePath, string.Format("{0}.cs", fileNameNoExtension)), source);
            }
        }
        public virtual async Task<TemplateResult> RunTemplateAsync([NotNull] string content,
            [NotNull] dynamic templateModel, CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(content, nameof(content));
            Check.NotNull(templateModel, nameof(templateModel));

            cancellationToken.ThrowIfCancellationRequested();

            var host = new RazorTemplatingHost(typeof(RazorReverseEngineeringBase));
            var engine = new RazorTemplateEngine(host);

            using (var reader = new StringReader(content))
            {
                var generatorResults = engine.GenerateCode(reader);

                if (!generatorResults.Success)
                {
                    var messages = generatorResults.ParserErrors.Select(e => e.Message);
                    return new TemplateResult
                    {
                        GeneratedText = string.Empty,
                        ProcessingException = new TemplateProcessingException(messages)
                    };
                }

                var references = _metadataReferencesProvider.GetApplicationReferences();
                var templateResult = _compilationService.Compile(
                    new List<string> { generatorResults.GeneratedCode }, references);
                if (templateResult.Messages.Any())
                {
                    return new TemplateResult
                    {
                        GeneratedText = string.Empty,
                        ProcessingException = new TemplateProcessingException(templateResult.Messages)
                    };
                }

                var compiledObject = Activator.CreateInstance(templateResult.CompiledType);
                var razorTemplate = compiledObject as RazorReverseEngineeringBase;

                var result = String.Empty;
                if (razorTemplate != null)
                {
                    razorTemplate.Model = templateModel;
                    razorTemplate.ModelUtilities = _modelUtilities;
                    razorTemplate.CSharpUtilities = _csharpUtiliies;
                    //ToDo: If there are errors executing the code, they are missed here.
                    result = await razorTemplate.ExecuteTemplateAsync(cancellationToken);
                }

                return new TemplateResult
                {
                    GeneratedText = result,
                    ProcessingException = null
                };
            }
        }
Example #6
0
 public GeneratorResults GenerateCode(string rootRelativePath, Stream inputStream)
 {
     var className = ParserHelpers.SanitizeClassName(rootRelativePath);
     using (var reader = new StreamReader(inputStream))
     {
         var engine = new RazorTemplateEngine(this);
         return engine.GenerateCode(reader, className, ViewNamespace, rootRelativePath);
     }
 }
        public virtual async Task<TemplateResult> RunTemplateAsync(string content,
            dynamic templateModel, IDatabaseMetadataModelProvider provider,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            RazorTemplatingHost host = new RazorTemplatingHost(typeof(RazorReverseEngineeringBase));
            RazorTemplateEngine engine = new RazorTemplateEngine(host);

            using (var reader = new StringReader(content))
            {
                var generatorResults = engine.GenerateCode(reader);

                if (!generatorResults.Success)
                {
                    var messages = generatorResults.ParserErrors.Select(e => e.Message);
                    return new TemplateResult()
                    {
                        GeneratedText = string.Empty,
                        ProcessingException = new TemplateProcessingException(messages, generatorResults.GeneratedCode)
                    };
                }

                provider.AddReferencesForTemplates(_metadataReferencesProvider);
                var references = _metadataReferencesProvider.GetApplicationReferences();
                var templateResult = _compilationService.Compile(generatorResults.GeneratedCode, references);
                if (templateResult.Messages.Any())
                {
                    return new TemplateResult()
                    {
                        GeneratedText = string.Empty,
                        ProcessingException = new TemplateProcessingException(templateResult.Messages, generatorResults.GeneratedCode)
                    };
                }

                var compiledObject = Activator.CreateInstance(templateResult.CompiledType);
                var razorTemplate = compiledObject as RazorReverseEngineeringBase;

                string result = String.Empty;
                if (razorTemplate != null)
                {
                    razorTemplate.Model = templateModel;
                    //ToDo: If there are errors executing the code, they are missed here.
                    result = await razorTemplate.ExecuteTemplateAsync();
                }

                return new TemplateResult()
                {
                    GeneratedText = result,
                    ProcessingException = null
                };
            }
        }
Example #8
0
        static void Main(string[] args)
        {
            const string rootNamespace = "RazorOnConsole";
            var viewPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Views\Index.cshtml");
            var basePath = Path.GetDirectoryName(viewPath);
            var fileName = Path.GetFileName(viewPath);
            var fileNameNoExtension = Path.GetFileNameWithoutExtension(fileName);
            using (var file = File.Create(fileNameNoExtension + ".html")) { new Index { Model = "foobarfoo" }.ExecuteAsync(file).Wait(); }

            var codeLang = new CSharpRazorCodeLanguage();
            var host = new RazorEngineHost(codeLang)
            {
                DefaultBaseClass = "RazorOnConsole.Views.BaseView",
                GeneratedClassContext = new GeneratedClassContext(
                    executeMethodName: GeneratedClassContext.DefaultExecuteMethodName,
                    writeMethodName: GeneratedClassContext.DefaultWriteMethodName,
                    writeLiteralMethodName: GeneratedClassContext.DefaultWriteLiteralMethodName,
                    writeToMethodName: "WriteTo",
                    writeLiteralToMethodName: "WriteLiteralTo",
                    templateTypeName: "HelperResult",
                    defineSectionMethodName: "DefineSection",
                    generatedTagHelperContext: new GeneratedTagHelperContext())
            };

            host.NamespaceImports.Add("System");

            var engine = new RazorTemplateEngine(host);

            using (var fileStream = File.OpenText(viewPath))
            {
                GeneratorResults code = engine.GenerateCode(
                    input: fileStream,
                    className: fileNameNoExtension,
                    rootNamespace: rootNamespace,
                    sourceFileName: fileName);

                string source = code.GeneratedCode;
                File.WriteAllText(Path.Combine(basePath, @"..\..\..\", "Views", string.Format("{0}.cs", fileNameNoExtension)), source);
            }
        }
        private static ChunkTree ParseViewFile(
            RazorTemplateEngine engine,
            IFileInfo fileInfo,
            string viewImportsPath)
        {
            using (var stream = fileInfo.CreateReadStream())
            {
                using (var streamReader = new StreamReader(stream))
                {
                    var parseResults = engine.ParseTemplate(streamReader, viewImportsPath);
                    var className = ParserHelpers.SanitizeClassName(fileInfo.Name);
                    var language = engine.Host.CodeLanguage;
                    var chunkGenerator = language.CreateChunkGenerator(
                        className,
                        engine.Host.DefaultNamespace,
                        viewImportsPath,
                        engine.Host);
                    chunkGenerator.Visit(parseResults);

                    // Rewrite the location of inherited chunks so they point to the global import file.
                    var chunkTree = chunkGenerator.Context.ChunkTreeBuilder.ChunkTree;
                    foreach (var chunk in chunkTree.Chunks)
                    {
                        chunk.Start = new SourceLocation(
                            viewImportsPath,
                            chunk.Start.AbsoluteIndex,
                            chunk.Start.LineIndex,
                            chunk.Start.CharacterIndex);
                    }

                    return chunkTree;
                }
            }
        }
Example #10
0
        public void ModelVisitor_GeneratesCorrectLineMappings()
        {
            // Arrange
            var host = new MvcRazorHost("RazorView")
            {
                DesignTimeMode = true
            };
            host.NamespaceImports.Clear();
            var engine = new RazorTemplateEngine(host);
            var source = ReadResource("TestFiles/Input/Model.cshtml");
            var expectedCode = ReadResource("TestFiles/Output/Model.cs");
            var expectedLineMappings = new List<LineMapping>
            {
                BuildLineMapping(7, 0, 7, 126, 6, 7, 30),
            };

            // Act
            GeneratorResults results;
            using (var buffer = new StringTextBuffer(source))
            {
                results = engine.GenerateCode(buffer);
            }

            // Assert
            Assert.True(results.Success);
            Assert.Equal(expectedCode, results.GeneratedCode);
            Assert.Empty(results.ParserErrors);
            Assert.Equal(expectedLineMappings, results.DesignTimeLineMappings);
        }
        private static CodeTree ParseViewFile(RazorTemplateEngine engine,
                                              IFileInfo fileInfo,
                                              string viewStartPath)
        {
            using (var stream = fileInfo.CreateReadStream())
            {
                using (var streamReader = new StreamReader(stream))
                {
                    var parseResults = engine.ParseTemplate(streamReader, viewStartPath);
                    var className = ParserHelpers.SanitizeClassName(fileInfo.Name);
                    var language = engine.Host.CodeLanguage;
                    var codeGenerator = language.CreateCodeGenerator(className,
                                                                     engine.Host.DefaultNamespace,
                                                                     viewStartPath,
                                                                     engine.Host);
                    codeGenerator.Visit(parseResults);

                    return codeGenerator.Context.CodeTreeBuilder.CodeTree;
                }
            }
        }
Example #12
0
 private static RazorTemplateEngine CreateEngine(ITemplateHost host)
 {
     RazorTemplateEngine engine = new RazorTemplateEngine(host.CreateHost());
     return engine;
 }
Example #13
0
        private static string GetRazorSyntaxTree()
        {
            var viewPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Views\Index.cshtml");
            var fileName = Path.GetFileName(viewPath);
            var fileNameNoExtension = Path.GetFileNameWithoutExtension(fileName);
            var className = MainClassNamePrefix + fileNameNoExtension;

            var codeLang = new CSharpRazorCodeLanguage();
            var host = new RazorEngineHost(codeLang)
            {
                DefaultBaseClass = typeof(BaseView).FullName,
                GeneratedClassContext = new GeneratedClassContext(
                    executeMethodName: GeneratedClassContext.DefaultExecuteMethodName,
                    writeMethodName: GeneratedClassContext.DefaultWriteMethodName,
                    writeLiteralMethodName: GeneratedClassContext.DefaultWriteLiteralMethodName,
                    writeToMethodName: "WriteTo",
                    writeLiteralToMethodName: "WriteLiteralTo",
                    templateTypeName: "HelperResult",
                    defineSectionMethodName: "DefineSection",
                    generatedTagHelperContext: new GeneratedTagHelperContext())
            };

            host.NamespaceImports.Add("System");

            var engine = new RazorTemplateEngine(host);

            using (var fileStream = File.OpenText(viewPath))
            {
                GeneratorResults code = engine.GenerateCode(
                    input: fileStream,
                    className: className,
                    rootNamespace: RootNamespace,
                    sourceFileName: fileName);

                return code.GeneratedCode;
            }
        }