// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Microsoft.AspNet.Razor.Chunks.Generators; using Microsoft.AspNet.Razor.CodeGenerators; using Microsoft.AspNet.Razor.Parser; using Microsoft.AspNet.Razor.TagHelpers; using Microsoft.Framework.Internal; namespace Microsoft.AspNet.Razor { /// /// Defines the environment in which a Razor template will live /// /// /// The host defines the following things: /// * What method names will be used for rendering markup, expressions etc. For example "Write", "WriteLiteral" /// * The namespace imports to be added to every page generated via this host /// * The default Base Class to inherit the generated class from /// * The default Class Name and Namespace for the generated class (can be overridden by parameters in RazorTemplateEngine.GeneratedCode) /// * The language of the code in a Razor page /// * The markup, code parsers and chunk generators to use (the system will select defaults, but a Host gets a change to augment them) /// ** See DecorateNNN methods /// * Additional code to add to the generated code (see PostProcessGeneratedCode) /// public class RazorEngineHost { internal const string InternalDefaultClassName = "__CompiledTemplate"; internal const string InternalDefaultNamespace = "Razor"; private bool _instrumentationActive = false; private Func _markupParserFactory; private int _tabSize = 4; [SuppressMessage( "Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "The code path is safe, it is a property setter and not dependent on other state")] protected RazorEngineHost() { GeneratedClassContext = GeneratedClassContext.Default; NamespaceImports = new HashSet(); DesignTimeMode = false; DefaultNamespace = InternalDefaultNamespace; DefaultClassName = InternalDefaultClassName; EnableInstrumentation = false; } /// /// Creates a host which uses the specified code language and the HTML markup language /// /// The code language to use public RazorEngineHost([NotNull] RazorCodeLanguage codeLanguage) : this(codeLanguage, () => new HtmlMarkupParser()) { } [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "The code path is safe, it is a property setter and not dependent on other state")] public RazorEngineHost( [NotNull] RazorCodeLanguage codeLanguage, [NotNull] Func markupParserFactory) : this() { CodeLanguage = codeLanguage; _markupParserFactory = markupParserFactory; } /// /// Details about the methods and types that should be used to generate code for Razor constructs /// public virtual GeneratedClassContext GeneratedClassContext { get; set; } /// /// A list of namespaces to import in the generated file /// public virtual ISet NamespaceImports { get; private set; } /// /// The base-class of the generated class /// public virtual string DefaultBaseClass { get; set; } /// /// Indicates if the parser and chunk generator should run in design-time mode /// public virtual bool DesignTimeMode { get; set; } /// /// The name of the generated class /// public virtual string DefaultClassName { get; set; } /// /// The namespace which will contain the generated class /// public virtual string DefaultNamespace { get; set; } /// /// Boolean indicating if helper methods should be instance methods or static methods /// public virtual bool StaticHelpers { get; set; } /// /// The language of the code within the Razor template. /// public virtual RazorCodeLanguage CodeLanguage { get; protected set; } /// /// The used to resolve s. /// public virtual ITagHelperDescriptorResolver TagHelperDescriptorResolver { get; set; } /// /// Boolean indicating if instrumentation code should be injected into the output page /// public virtual bool EnableInstrumentation { // Always disable instrumentation in DesignTimeMode. get { return !DesignTimeMode && _instrumentationActive; } set { _instrumentationActive = value; } } /// /// Gets or sets whether the design time editor is using tabs or spaces for indentation. /// public virtual bool IsIndentingWithTabs { get; set; } /// /// Tab size used by the hosting editor, when indenting with tabs. /// public virtual int TabSize { get { return _tabSize; } set { _tabSize = Math.Max(value, 1); } } /// /// Gets or sets the path to use for this document when generating Instrumentation calls /// public virtual string InstrumentedSourceFilePath { get; set; } /// /// Constructs the markup parser. Must return a new instance on EVERY call to ensure thread-safety /// public virtual ParserBase CreateMarkupParser() { if (_markupParserFactory != null) { return _markupParserFactory(); } return null; } /// /// Provides an opportunity for derived types to modify the instance of /// used by the to parse the Razor tree. /// /// The /// The file name of the Razor file being parsed. /// Either the same code parser, after modifications, or a different code parser. public virtual RazorParser DecorateRazorParser( [NotNull] RazorParser incomingRazorParser, string sourceFileName) { return incomingRazorParser; } /// /// Gets an instance of the code parser and is provided an opportunity to decorate or replace it /// /// The code parser /// Either the same code parser, after modifications, or a different code parser public virtual ParserBase DecorateCodeParser([NotNull] ParserBase incomingCodeParser) { return incomingCodeParser; } /// /// Gets an instance of the markup parser and is provided an opportunity to decorate or replace it /// /// The markup parser /// Either the same markup parser, after modifications, or a different markup parser public virtual ParserBase DecorateMarkupParser([NotNull] ParserBase incomingMarkupParser) { return incomingMarkupParser; } /// /// Gets an instance of the chunk generator and is provided an opportunity to decorate or replace it /// /// The chunk generator /// Either the same chunk generator, after modifications, or a different chunk generator public virtual RazorChunkGenerator DecorateChunkGenerator([NotNull] RazorChunkGenerator incomingChunkGenerator) { return incomingChunkGenerator; } /// /// Gets an instance of the code generator and is provided an opportunity to decorate or replace it /// /// The code generator /// Either the same code generator, after modifications, or a different code generator. public virtual CodeGenerator DecorateCodeGenerator( [NotNull] CodeGenerator incomingBuilder, CodeGeneratorContext context) { return incomingBuilder; } // If a user wants to modify the chunk generation process they do it via the DecorateChunkGenerator method // which is why this is internal. internal RazorChunkGenerator CreateChunkGenerator(string className, string rootNamespace, string sourceFileName) { return DecorateChunkGenerator( CodeLanguage.CreateChunkGenerator(className, rootNamespace, sourceFileName, host: this)); } } }