// 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.Linq; namespace Microsoft.AspNetCore.Razor.Language { internal class DefaultRazorProjectEngine : RazorProjectEngine { public DefaultRazorProjectEngine( RazorConfiguration configuration, RazorEngine engine, RazorProjectFileSystem fileSystem, IReadOnlyList projectFeatures) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (engine == null) { throw new ArgumentNullException(nameof(engine)); } if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } if (projectFeatures == null) { throw new ArgumentNullException(nameof(projectFeatures)); } Configuration = configuration; Engine = engine; FileSystem = fileSystem; ProjectFeatures = projectFeatures; for (var i = 0; i < projectFeatures.Count; i++) { projectFeatures[i].ProjectEngine = this; } } public override RazorConfiguration Configuration { get; } public override RazorProjectFileSystem FileSystem { get; } public override RazorEngine Engine { get; } public override IReadOnlyList ProjectFeatures { get; } protected override RazorCodeDocument CreateCodeDocumentCore(RazorProjectItem projectItem) { if (projectItem == null) { throw new ArgumentNullException(nameof(projectItem)); } var sourceDocument = RazorSourceDocument.ReadFrom(projectItem); var importFeature = GetRequiredFeature(); var importItems = importFeature.GetImports(projectItem); var importSourceDocuments = importItems.Select(ConvertToSourceDocument); var parserOptions = GetRequiredFeature().Create(ConfigureParserOptions); var codeGenerationOptions = GetRequiredFeature().Create(ConfigureCodeGenerationOptions); return RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions); } protected override RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorProjectItem projectItem) { if (projectItem == null) { throw new ArgumentNullException(nameof(projectItem)); } var sourceDocument = RazorSourceDocument.ReadFrom(projectItem); var importFeature = GetRequiredFeature(); var importItems = importFeature.GetImports(projectItem); var importSourceDocuments = importItems.Select(ConvertToSourceDocument); var parserOptions = GetRequiredFeature().Create(ConfigureDesignTimeParserOptions); var codeGenerationOptions = GetRequiredFeature().Create(ConfigureDesignTimeCodeGenerationOptions); return RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions); } protected override void ProcessCore(RazorCodeDocument codeDocument) { if (codeDocument == null) { throw new ArgumentNullException(nameof(codeDocument)); } Engine.Process(codeDocument); } private TFeature GetRequiredFeature() where TFeature : IRazorProjectEngineFeature { var feature = ProjectFeatures.OfType().FirstOrDefault(); if (feature == null) { throw new InvalidOperationException( Resources.FormatRazorProjectEngineMissingFeatureDependency( typeof(RazorProjectEngine).FullName, typeof(TFeature).FullName)); } return feature; } private void ConfigureParserOptions(RazorParserOptionsBuilder builder) { } private void ConfigureDesignTimeParserOptions(RazorParserOptionsBuilder builder) { builder.SetDesignTime(true); } private void ConfigureCodeGenerationOptions(RazorCodeGenerationOptionsBuilder builder) { } private void ConfigureDesignTimeCodeGenerationOptions(RazorCodeGenerationOptionsBuilder builder) { builder.SetDesignTime(true); builder.SuppressChecksum = true; builder.SuppressMetadataAttributes = true; } // Internal for testing internal static RazorSourceDocument ConvertToSourceDocument(RazorProjectItem importItem) { if (importItem.Exists) { // Normal import, has file paths, content etc. return RazorSourceDocument.ReadFrom(importItem); } // Marker import, doesn't exist, used as an identifier for "there could be something here". var sourceDocumentProperties = new RazorSourceDocumentProperties(importItem.FilePath, importItem.RelativePhysicalPath); return RazorSourceDocument.Create(string.Empty, sourceDocumentProperties); } } }