// 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.IO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Razor.Language
{
public static class RazorProjectEngineBuilderExtensions
{
///
/// Registers a class configuration delegate that gets invoked during code generation.
///
/// The .
/// invoked to configure
/// during code generation.
/// The .
public static RazorProjectEngineBuilder ConfigureClass(
this RazorProjectEngineBuilder builder,
Action configureClass)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (configureClass == null)
{
throw new ArgumentNullException(nameof(configureClass));
}
var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder);
configurationFeature.ConfigureClass.Add(configureClass);
return builder;
}
///
/// Sets the base type for generated types.
///
/// The .
/// The name of the base type.
/// The .
public static RazorProjectEngineBuilder SetBaseType(this RazorProjectEngineBuilder builder, string baseType)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder);
configurationFeature.ConfigureClass.Add((document, @class) => @class.BaseType = baseType);
return builder;
}
///
/// Sets the namespace for generated types.
///
/// The .
/// The name of the namespace.
/// The .
public static RazorProjectEngineBuilder SetNamespace(this RazorProjectEngineBuilder builder, string namespaceName)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
var configurationFeature = GetDefaultDocumentClassifierPassFeature(builder);
configurationFeature.ConfigureNamespace.Add((document, @namespace) => @namespace.Content = namespaceName);
return builder;
}
public static void SetImportFeature(this RazorProjectEngineBuilder builder, IImportProjectFeature feature)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (feature == null)
{
throw new ArgumentNullException(nameof(builder));
}
// Remove any existing import features in favor of the new one we're given.
var existingFeatures = builder.Features.OfType().ToArray();
foreach (var existingFeature in existingFeatures)
{
builder.Features.Remove(existingFeature);
}
builder.Features.Add(feature);
}
///
/// Adds the specified .
///
/// The .
/// The to add.
/// The .
public static RazorProjectEngineBuilder AddTargetExtension(this RazorProjectEngineBuilder builder, ICodeTargetExtension extension)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (extension == null)
{
throw new ArgumentNullException(nameof(extension));
}
var targetExtensionFeature = GetTargetExtensionFeature(builder);
targetExtensionFeature.TargetExtensions.Add(extension);
return builder;
}
///
/// Adds the specified .
///
/// The .
/// The to add.
/// The .
public static RazorProjectEngineBuilder AddDirective(this RazorProjectEngineBuilder builder, DirectiveDescriptor directive)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
if (directive == null)
{
throw new ArgumentNullException(nameof(directive));
}
var directiveFeature = GetDirectiveFeature(builder);
directiveFeature.Directives.Add(directive);
return builder;
}
///
/// Adds the provided s as imports to all project items processed
/// by the .
///
/// The .
/// The collection of imports.
/// The .
public static RazorProjectEngineBuilder AddDefaultImports(this RazorProjectEngineBuilder builder, params string[] imports)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
var existingImportFeature = builder.Features.OfType().First();
var testImportFeature = new AdditionalImportsProjectFeature(existingImportFeature, imports);
builder.SetImportFeature(testImportFeature);
return builder;
}
private static IRazorDirectiveFeature GetDirectiveFeature(RazorProjectEngineBuilder builder)
{
var directiveFeature = builder.Features.OfType().FirstOrDefault();
if (directiveFeature == null)
{
directiveFeature = new DefaultRazorDirectiveFeature();
builder.Features.Add(directiveFeature);
}
return directiveFeature;
}
private static IRazorTargetExtensionFeature GetTargetExtensionFeature(RazorProjectEngineBuilder builder)
{
var targetExtensionFeature = builder.Features.OfType().FirstOrDefault();
if (targetExtensionFeature == null)
{
targetExtensionFeature = new DefaultRazorTargetExtensionFeature();
builder.Features.Add(targetExtensionFeature);
}
return targetExtensionFeature;
}
private static DefaultDocumentClassifierPassFeature GetDefaultDocumentClassifierPassFeature(RazorProjectEngineBuilder builder)
{
var configurationFeature = builder.Features.OfType().FirstOrDefault();
if (configurationFeature == null)
{
configurationFeature = new DefaultDocumentClassifierPassFeature();
builder.Features.Add(configurationFeature);
}
return configurationFeature;
}
private class AdditionalImportsProjectFeature : RazorProjectEngineFeatureBase, IImportProjectFeature
{
private readonly IImportProjectFeature _existingImportFeature;
private readonly IEnumerable _imports;
public override RazorProjectEngine ProjectEngine
{
get => base.ProjectEngine;
set
{
_existingImportFeature.ProjectEngine = value;
base.ProjectEngine = value;
}
}
public AdditionalImportsProjectFeature(IImportProjectFeature existingImportFeature, params string[] imports)
{
_existingImportFeature = existingImportFeature;
_imports = imports.Select(import => new InMemoryProjectItem(import));
}
public IReadOnlyList GetImports(RazorProjectItem projectItem)
{
var imports = _existingImportFeature.GetImports(projectItem).ToList();
imports.AddRange(_imports);
return imports;
}
private class InMemoryProjectItem : RazorProjectItem
{
private readonly byte[] _importBytes;
public InMemoryProjectItem(string content)
{
if (string.IsNullOrEmpty(content))
{
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(content));
}
var preamble = Encoding.UTF8.GetPreamble();
var contentBytes = Encoding.UTF8.GetBytes(content);
_importBytes = new byte[preamble.Length + contentBytes.Length];
preamble.CopyTo(_importBytes, 0);
contentBytes.CopyTo(_importBytes, preamble.Length);
}
public override string BasePath => null;
public override string FilePath => null;
public override string PhysicalPath => null;
public override bool Exists => true;
public override Stream Read() => new MemoryStream(_importBytes);
}
}
}
}