Remove Razor from projects

This commit is contained in:
Ryan Brandenburg 2017-03-09 12:34:52 -08:00
parent 1fdc5132cb
commit 270f66198f
23 changed files with 4 additions and 1722 deletions

View File

@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Mvc.Razor.Host;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
@ -64,11 +63,6 @@ namespace Microsoft.Extensions.DependencyInjection
private static void AddRazorViewEngineFeatureProviders(IMvcCoreBuilder builder)
{
if (!builder.PartManager.FeatureProviders.OfType<TagHelperFeatureProvider>().Any())
{
builder.PartManager.FeatureProviders.Add(new TagHelperFeatureProvider());
}
if (!builder.PartManager.FeatureProviders.OfType<MetadataReferenceFeatureProvider>().Any())
{
builder.PartManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider());
@ -158,12 +152,6 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddSingleton<IRazorViewEngine, RazorViewEngine>();
services.TryAddSingleton<ITagHelperTypeResolver, TagHelperTypeResolver>();
services.TryAddSingleton<ITagHelperDescriptorFactory>(s => new TagHelperDescriptorFactory(designTime: false));
services.TryAddSingleton<TagHelperDescriptorResolver>();
services.TryAddSingleton<ViewComponentTagHelperDescriptorResolver>();
services.TryAddSingleton<ITagHelperDescriptorResolver, CompositeTagHelperDescriptorResolver>();
// Caches compilation artifacts across the lifetime of the application.
services.TryAddSingleton<ICompilerCacheProvider, DefaultCompilerCacheProvider>();

View File

@ -1,33 +0,0 @@
// 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.Collections.Generic;
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
public class CompositeTagHelperDescriptorResolver : ITagHelperDescriptorResolver
{
private readonly TagHelperDescriptorResolver _tagHelperDescriptorResolver;
private readonly ViewComponentTagHelperDescriptorResolver _viewComponentTagHelperDescriptorResolver;
public CompositeTagHelperDescriptorResolver(
TagHelperDescriptorResolver tagHelperDescriptorResolver,
ViewComponentTagHelperDescriptorResolver viewComponentTagHelperDescriptorResolver)
{
_tagHelperDescriptorResolver = tagHelperDescriptorResolver;
_viewComponentTagHelperDescriptorResolver = viewComponentTagHelperDescriptorResolver;
}
public IEnumerable<TagHelperDescriptor> Resolve(TagHelperDescriptorResolutionContext resolutionContext)
{
var descriptors = new List<TagHelperDescriptor>();
descriptors.AddRange(_tagHelperDescriptorResolver.Resolve(resolutionContext));
descriptors.AddRange(_viewComponentTagHelperDescriptorResolver.Resolve(resolutionContext));
return descriptors;
}
}
}

View File

@ -5,7 +5,6 @@ using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@ -34,7 +33,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal
}
services.Replace(ServiceDescriptor.Transient<ITagHelperActivator, ServiceBasedTagHelperActivator>());
services.Replace(ServiceDescriptor.Transient<ITagHelperTypeResolver, FeatureTagHelperTypeResolver>());
}
}
}

View File

@ -1,266 +0,0 @@
// 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;
using System.Reflection;
using System.Text;
using Microsoft.AspNetCore.Mvc.Razor.Host;
using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
/// <summary>
/// Provides methods to create tag helper representations of view components.
/// </summary>
public class ViewComponentTagHelperDescriptorFactory
{
private readonly IViewComponentDescriptorProvider _descriptorProvider;
/// <summary>
/// Creates a new <see cref="ViewComponentTagHelperDescriptorFactory"/>,
/// then creates <see cref="TagHelperDescriptor"/>s for <see cref="ViewComponent"/>s
/// in the given <see cref="IViewComponentDescriptorProvider"/>.
/// </summary>
/// <param name="descriptorProvider">The provider of <see cref="ViewComponentDescriptor"/>s.</param>
public ViewComponentTagHelperDescriptorFactory(IViewComponentDescriptorProvider descriptorProvider)
{
if (descriptorProvider == null)
{
throw new ArgumentNullException(nameof(descriptorProvider));
}
_descriptorProvider = descriptorProvider;
}
/// <summary>
/// Creates <see cref="TagHelperDescriptor"/> representations of <see cref="ViewComponent"/>s
/// in an <see href="Assembly"/> represented by the given <paramref name="assemblyName"/>.
/// </summary>
/// <param name="assemblyName">The name of the assembly containing
/// the <see cref="ViewComponent"/>s to translate.</param>
/// <returns>A <see cref="IEnumerable{TagHelperDescriptor}"/>,
/// one for each <see cref="ViewComponent"/>.</returns>
public IEnumerable<TagHelperDescriptor> CreateDescriptors(string assemblyName)
{
if (assemblyName == null)
{
throw new ArgumentNullException(nameof(assemblyName));
}
var viewComponentDescriptors = _descriptorProvider
.GetViewComponents()
.Where(viewComponent => string.Equals(assemblyName, viewComponent.TypeInfo.Assembly.GetName().Name,
StringComparison.Ordinal));
var tagHelperDescriptors = viewComponentDescriptors
.Where(d => !d.MethodInfo.ContainsGenericParameters)
.Select(viewComponentDescriptor => CreateDescriptor(viewComponentDescriptor));
return tagHelperDescriptors;
}
private TagHelperDescriptor CreateDescriptor(ViewComponentDescriptor viewComponentDescriptor)
{
var assemblyName = viewComponentDescriptor.TypeInfo.Assembly.GetName().Name;
var tagName = GetTagName(viewComponentDescriptor);
var typeName = $"__Generated__{viewComponentDescriptor.ShortName}ViewComponentTagHelper";
var tagHelperDescriptor = new TagHelperDescriptor
{
TagName = tagName,
TypeName = typeName,
AssemblyName = assemblyName
};
SetAttributeDescriptors(viewComponentDescriptor, tagHelperDescriptor);
tagHelperDescriptor.PropertyBag.Add(
ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, viewComponentDescriptor.ShortName);
return tagHelperDescriptor;
}
private void SetAttributeDescriptors(ViewComponentDescriptor viewComponentDescriptor,
TagHelperDescriptor tagHelperDescriptor)
{
var methodParameters = viewComponentDescriptor.MethodInfo.GetParameters();
var attributeDescriptors = new List<TagHelperAttributeDescriptor>();
var indexerDescriptors = new List<TagHelperAttributeDescriptor>();
var requiredAttributeDescriptors = new List<TagHelperRequiredAttributeDescriptor>();
foreach (var parameter in methodParameters)
{
var lowerKebabName = TagHelperDescriptorFactory.ToHtmlCase(parameter.Name);
var typeName = GetCSharpTypeName(parameter.ParameterType);
var descriptor = new TagHelperAttributeDescriptor
{
Name = lowerKebabName,
PropertyName = parameter.Name,
TypeName = typeName
};
descriptor.IsEnum = parameter.ParameterType.GetTypeInfo().IsEnum;
descriptor.IsIndexer = false;
attributeDescriptors.Add(descriptor);
var indexerDescriptor = GetIndexerAttributeDescriptor(parameter, lowerKebabName);
if (indexerDescriptor != null)
{
indexerDescriptors.Add(indexerDescriptor);
}
else
{
// Set required attributes only for non-indexer attributes. Indexer attributes can't be required attributes
// because there are two ways of setting values for the attribute.
requiredAttributeDescriptors.Add(new TagHelperRequiredAttributeDescriptor
{
Name = lowerKebabName
});
}
}
attributeDescriptors.AddRange(indexerDescriptors);
tagHelperDescriptor.Attributes = attributeDescriptors;
tagHelperDescriptor.RequiredAttributes = requiredAttributeDescriptors;
}
private TagHelperAttributeDescriptor GetIndexerAttributeDescriptor(ParameterInfo parameter, string name)
{
var dictionaryTypeArguments = ClosedGenericMatcher.ExtractGenericInterface(
parameter.ParameterType,
typeof(IDictionary<,>))
?.GenericTypeArguments
.Select(t => t.IsGenericParameter ? null : t)
.ToArray();
if (dictionaryTypeArguments?[0] != typeof(string))
{
return null;
}
var type = dictionaryTypeArguments[1];
var descriptor = new TagHelperAttributeDescriptor
{
Name = name + "-",
PropertyName = parameter.Name,
TypeName = GetCSharpTypeName(type),
IsEnum = type.GetTypeInfo().IsEnum,
IsIndexer = true
};
return descriptor;
}
private string GetTagName(ViewComponentDescriptor descriptor)
{
return $"vc:{TagHelperDescriptorFactory.ToHtmlCase(descriptor.ShortName)}";
}
// Internal for testing.
internal static string GetCSharpTypeName(Type type)
{
var outputBuilder = new StringBuilder();
WriteCSharpTypeName(type, outputBuilder);
var typeName = outputBuilder.ToString();
// We don't want to add global:: to the top level type because Razor does that for us.
return typeName.Substring("global::".Length);
}
private static void WriteCSharpTypeName(Type type, StringBuilder outputBuilder)
{
var typeInfo = type.GetTypeInfo();
if (typeInfo.IsByRef)
{
WriteCSharpTypeName(typeInfo.GetElementType(), outputBuilder);
}
else if (typeInfo.IsNested)
{
WriteNestedTypes(type, outputBuilder);
}
else if (typeInfo.IsGenericType)
{
outputBuilder.Append("global::");
var part = type.FullName.Substring(0, type.FullName.IndexOf('`'));
outputBuilder.Append(part);
var genericArguments = type.GenericTypeArguments;
WriteGenericArguments(genericArguments, 0, genericArguments.Length, outputBuilder);
}
else
{
outputBuilder.Append("global::");
outputBuilder.Append(type.FullName);
}
}
private static void WriteNestedTypes(Type type, StringBuilder outputBuilder)
{
var nestedTypes = new List<Type>();
var currentType = type;
do
{
nestedTypes.Insert(0, currentType);
currentType = currentType.DeclaringType;
} while (currentType.IsNested);
nestedTypes.Insert(0, currentType);
outputBuilder.Append("global::");
outputBuilder.Append(currentType.Namespace);
outputBuilder.Append(".");
var typeArgumentIndex = 0;
for (var i = 0; i < nestedTypes.Count; i++)
{
var nestedType = nestedTypes[i];
var arityIndex = nestedType.Name.IndexOf('`');
if (arityIndex >= 0)
{
var part = nestedType.Name.Substring(0, arityIndex);
outputBuilder.Append(part);
var genericArguments = type.GenericTypeArguments;
var typeArgumentCount = nestedType.IsConstructedGenericType ?
nestedType.GenericTypeArguments.Length : nestedType.GetTypeInfo().GenericTypeParameters.Length;
WriteGenericArguments(genericArguments, typeArgumentIndex, typeArgumentCount, outputBuilder);
typeArgumentIndex = typeArgumentCount;
}
else
{
outputBuilder.Append(nestedType.Name);
}
if (i + 1 < nestedTypes.Count)
{
outputBuilder.Append(".");
}
}
}
private static void WriteGenericArguments(Type[] genericArguments, int startIndex, int length, StringBuilder outputBuilder)
{
outputBuilder.Append("<");
for (var i = startIndex; i < length; i++)
{
WriteCSharpTypeName(genericArguments[i], outputBuilder);
if (i + 1 < length)
{
outputBuilder.Append(", ");
}
}
outputBuilder.Append(">");
}
}
}

View File

@ -1,31 +0,0 @@
// 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.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
namespace Microsoft.AspNetCore.Mvc.Razor.Internal
{
public class ViewComponentTagHelperDescriptorResolver : TagHelperDescriptorResolver
{
private readonly ViewComponentTagHelperDescriptorFactory _descriptorFactory;
public ViewComponentTagHelperDescriptorResolver(
IViewComponentDescriptorProvider viewComponentDescriptorProvider)
: base(designTime: false)
{
_descriptorFactory = new ViewComponentTagHelperDescriptorFactory(viewComponentDescriptorProvider);
}
protected override IEnumerable<TagHelperDescriptor> ResolveDescriptorsInAssembly(
string assemblyName,
SourceLocation documentLocation,
ErrorSink errorSink)
{
return _descriptorFactory.CreateDescriptors(assemblyName);
}
}
}

View File

@ -1,94 +0,0 @@
// 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 Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
using System.Reflection;
namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
{
/// <summary>
/// Resolves tag helper types from the <see cref="ApplicationPartManager.ApplicationParts"/>
/// of the application.
/// </summary>
public class FeatureTagHelperTypeResolver : TagHelperTypeResolver
{
private readonly TagHelperFeature _feature;
/// <summary>
/// Initializes a new <see cref="FeatureTagHelperTypeResolver"/> instance.
/// </summary>
/// <param name="manager">The <see cref="ApplicationPartManager"/> of the application.</param>
public FeatureTagHelperTypeResolver(ApplicationPartManager manager)
{
if (manager == null)
{
throw new ArgumentNullException(nameof(manager));
}
_feature = new TagHelperFeature();
manager.PopulateFeature(_feature);
}
/// <inheritdoc />
protected override IEnumerable<TypeInfo> GetExportedTypes(AssemblyName assemblyName)
{
if (assemblyName == null)
{
throw new ArgumentNullException(nameof(assemblyName));
}
var results = new List<TypeInfo>();
for (var i = 0; i < _feature.TagHelpers.Count; i++)
{
var tagHelperAssemblyName = _feature.TagHelpers[i].Assembly.GetName();
if (AssemblyNameComparer.OrdinalIgnoreCase.Equals(tagHelperAssemblyName, assemblyName))
{
results.Add(_feature.TagHelpers[i]);
}
}
return results;
}
/// <inheritdoc />
protected sealed override bool IsTagHelper(TypeInfo typeInfo)
{
// Return true always as we have already decided what types are tag helpers when GetExportedTypes
// gets called.
return true;
}
private class AssemblyNameComparer : IEqualityComparer<AssemblyName>
{
public static readonly IEqualityComparer<AssemblyName> OrdinalIgnoreCase = new AssemblyNameComparer();
private AssemblyNameComparer()
{
}
public bool Equals(AssemblyName x, AssemblyName y)
{
// Ignore case because that's what Assembly.Load does.
return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase) &&
string.Equals(x.CultureName ?? string.Empty, y.CultureName ?? string.Empty, StringComparison.Ordinal);
}
public int GetHashCode(AssemblyName obj)
{
var hashCode = 0;
if (obj.Name != null)
{
hashCode ^= obj.Name.GetHashCode();
}
hashCode ^= (obj.CultureName ?? string.Empty).GetHashCode();
return hashCode;
}
}
}
}

View File

@ -1,36 +0,0 @@
// 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.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
{
/// <summary>
/// Discovers tag helpers from a list of <see cref="ApplicationPart"/> instances.
/// </summary>
public class TagHelperFeatureProvider : IApplicationFeatureProvider<TagHelperFeature>
{
/// <inheritdoc />
public void PopulateFeature(IEnumerable<ApplicationPart> parts, TagHelperFeature feature)
{
foreach (var type in parts.OfType<IApplicationPartTypeProvider>())
{
ProcessPart(type, feature);
}
}
private static void ProcessPart(IApplicationPartTypeProvider part, TagHelperFeature feature)
{
foreach (var type in part.Types)
{
if (TagHelperConventions.IsTagHelper(type) && !feature.TagHelpers.Contains(type))
{
feature.TagHelpers.Add(type);
}
}
}
}
}

View File

@ -20,6 +20,7 @@
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Razor\Microsoft.AspNetCore.Mvc.Razor.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.TestCommon\Microsoft.AspNetCore.Mvc.TestCommon.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="Moq" Version="$(MoqVersion)" />

View File

@ -1,73 +0,0 @@
// 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.Globalization;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
using Microsoft.AspNetCore.Razor.Text;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols;
namespace Microsoft.AspNetCore.Mvc.Razor
{
internal class RawTextSymbol : ISymbol
{
public SourceLocation Start { get; private set; }
public string Content { get; private set; }
public RawTextSymbol(SourceLocation start, string content)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
Start = start;
Content = content;
}
public override bool Equals(object obj)
{
var other = obj as RawTextSymbol;
return Equals(Start, other.Start) && Equals(Content, other.Content);
}
internal bool EquivalentTo(ISymbol sym)
{
return Equals(Start, sym.Start) && Equals(Content, sym.Content);
}
public override int GetHashCode()
{
return Start.GetHashCode() +
(13 * Content.GetHashCode());
}
public void OffsetStart(SourceLocation documentStart)
{
Start = documentStart + Start;
}
public void ChangeStart(SourceLocation newStart)
{
Start = newStart;
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "{0} RAW - [{1}]", Start, Content);
}
internal void CalculateStart(Span prev)
{
if (prev == null)
{
Start = SourceLocation.Zero;
}
else
{
Start = new SourceLocationTracker(prev.Start).UpdateLocation(prev.Content).CurrentLocation;
}
}
}
}

View File

@ -1,79 +0,0 @@
// 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 Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Chunks.Generators;
using Microsoft.AspNetCore.Razor.Editor;
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols;
namespace Microsoft.AspNetCore.Mvc.Razor
{
public class SpanConstructor
{
public SpanBuilder Builder { get; private set; }
internal static IEnumerable<ISymbol> TestTokenizer(string str)
{
yield return new RawTextSymbol(SourceLocation.Zero, str);
}
public SpanConstructor(SpanKind kind, IEnumerable<ISymbol> symbols)
{
Builder = new SpanBuilder();
Builder.Kind = kind;
Builder.EditHandler = SpanEditHandler.CreateDefault(TestTokenizer);
foreach (ISymbol sym in symbols)
{
Builder.Accept(sym);
}
}
private Span Build()
{
return Builder.Build();
}
public SpanConstructor With(ISpanChunkGenerator generator)
{
Builder.ChunkGenerator = generator;
return this;
}
public SpanConstructor With(SpanEditHandler handler)
{
Builder.EditHandler = handler;
return this;
}
public SpanConstructor With(Action<ISpanChunkGenerator> generatorConfigurer)
{
generatorConfigurer(Builder.ChunkGenerator);
return this;
}
public SpanConstructor With(Action<SpanEditHandler> handlerConfigurer)
{
handlerConfigurer(Builder.EditHandler);
return this;
}
public static implicit operator Span(SpanConstructor self)
{
return self.Build();
}
public SpanConstructor Hidden()
{
Builder.ChunkGenerator = SpanChunkGenerator.Null;
return this;
}
public SpanConstructor Accepts(AcceptedCharacters accepted)
{
return With(eh => eh.AcceptedCharacters = accepted);
}
}
}

View File

@ -1,110 +0,0 @@
// 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;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
using Microsoft.AspNetCore.Razor.Text;
using Microsoft.AspNetCore.Razor.Tokenizer;
using Microsoft.AspNetCore.Razor.Tokenizer.Internal;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols.Internal;
namespace Microsoft.AspNetCore.Mvc.Razor
{
public class SpanFactory
{
public Func<ITextDocument, ITokenizer> MarkupTokenizerFactory { get; set; }
public Func<ITextDocument, ITokenizer> CodeTokenizerFactory { get; set; }
public SourceLocationTracker LocationTracker { get; private set; }
public static SpanFactory CreateCsHtml()
{
return new SpanFactory()
{
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
CodeTokenizerFactory = doc => new CSharpTokenizer(doc)
};
}
public SpanFactory()
{
LocationTracker = new SourceLocationTracker();
}
public SpanConstructor Span(SpanKind kind, string content, CSharpSymbolType type)
{
return CreateSymbolSpan(kind, content, st => new CSharpSymbol(st, content, type));
}
public SpanConstructor Span(SpanKind kind, string content, HtmlSymbolType type)
{
return CreateSymbolSpan(kind, content, st => new HtmlSymbol(st, content, type));
}
public SpanConstructor Span(SpanKind kind, string content, bool markup)
{
return new SpanConstructor(kind, Tokenize(new[] { content }, markup));
}
public SpanConstructor Span(SpanKind kind, string[] content, bool markup)
{
return new SpanConstructor(kind, Tokenize(content, markup));
}
public SpanConstructor Span(SpanKind kind, params ISymbol[] symbols)
{
return new SpanConstructor(kind, symbols);
}
private SpanConstructor CreateSymbolSpan(SpanKind kind, string content, Func<SourceLocation, ISymbol> ctor)
{
var start = LocationTracker.CurrentLocation;
LocationTracker.UpdateLocation(content);
return new SpanConstructor(kind, new[] { ctor(start) });
}
public void Reset()
{
LocationTracker.CurrentLocation = SourceLocation.Zero;
}
private IEnumerable<ISymbol> Tokenize(IEnumerable<string> contentFragments, bool markup)
{
return contentFragments.SelectMany(fragment => Tokenize(fragment, markup));
}
private IEnumerable<ISymbol> Tokenize(string content, bool markup)
{
var tok = MakeTokenizer(markup, new SeekableTextReader(content));
ISymbol sym;
ISymbol last = null;
while ((sym = tok.NextSymbol()) != null)
{
OffsetStart(sym, LocationTracker.CurrentLocation);
last = sym;
yield return sym;
}
LocationTracker.UpdateLocation(content);
}
private ITokenizer MakeTokenizer(bool markup, SeekableTextReader seekableTextReader)
{
if (markup)
{
return MarkupTokenizerFactory(seekableTextReader);
}
else
{
return CodeTokenizerFactory(seekableTextReader);
}
}
private void OffsetStart(ISymbol sym, SourceLocation sourceLocation)
{
sym.OffsetStart(sourceLocation);
}
}
}

View File

@ -1,126 +0,0 @@
// 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 Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Chunks.Generators;
using Microsoft.AspNetCore.Razor.Parser;
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
using Microsoft.AspNetCore.Razor.Text;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols.Internal;
namespace Microsoft.AspNetCore.Mvc.Razor
{
public static class SpanFactoryExtensions
{
public static UnclassifiedCodeSpanConstructor EmptyCSharp(this SpanFactory self)
{
var symbol = new CSharpSymbol(self.LocationTracker.CurrentLocation, string.Empty, CSharpSymbolType.Unknown);
return new UnclassifiedCodeSpanConstructor(self.Span(SpanKind.Code, symbol));
}
public static SpanConstructor EmptyHtml(this SpanFactory self)
{
var symbol = new HtmlSymbol(self.LocationTracker.CurrentLocation, string.Empty, HtmlSymbolType.Unknown);
return self.Span(SpanKind.Markup, symbol)
.With(new MarkupChunkGenerator());
}
public static UnclassifiedCodeSpanConstructor Code(this SpanFactory self, string content)
{
return new UnclassifiedCodeSpanConstructor(
self.Span(SpanKind.Code, content, markup: false));
}
public static SpanConstructor CodeTransition(this SpanFactory self)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: false)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor CodeTransition(this SpanFactory self, string content)
{
return self.Span(SpanKind.Transition, content, markup: false).Accepts(AcceptedCharacters.None);
}
public static SpanConstructor CodeTransition(this SpanFactory self, CSharpSymbolType type)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor CodeTransition(this SpanFactory self, string content, CSharpSymbolType type)
{
return self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MarkupTransition(this SpanFactory self)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, markup: true)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MarkupTransition(this SpanFactory self, string content)
{
return self.Span(SpanKind.Transition, content, markup: true).Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MarkupTransition(this SpanFactory self, HtmlSymbolType type)
{
return self.Span(SpanKind.Transition, SyntaxConstants.TransitionString, type)
.Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MarkupTransition(this SpanFactory self, string content, HtmlSymbolType type)
{
return self.Span(SpanKind.Transition, content, type).Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MetaCode(this SpanFactory self, string content)
{
return self.Span(SpanKind.MetaCode, content, markup: false);
}
public static SpanConstructor MetaCode(this SpanFactory self, string content, CSharpSymbolType type)
{
return self.Span(SpanKind.MetaCode, content, type);
}
public static SpanConstructor MetaMarkup(this SpanFactory self, string content)
{
return self.Span(SpanKind.MetaCode, content, markup: true);
}
public static SpanConstructor MetaMarkup(this SpanFactory self, string content, HtmlSymbolType type)
{
return self.Span(SpanKind.MetaCode, content, type);
}
public static SpanConstructor Comment(this SpanFactory self, string content, CSharpSymbolType type)
{
return self.Span(SpanKind.Comment, content, type);
}
public static SpanConstructor Comment(this SpanFactory self, string content, HtmlSymbolType type)
{
return self.Span(SpanKind.Comment, content, type);
}
public static SpanConstructor Markup(this SpanFactory self, string content)
{
return self.Span(SpanKind.Markup, content, markup: true).With(new MarkupChunkGenerator());
}
public static SpanConstructor Markup(this SpanFactory self, params string[] content)
{
return self.Span(SpanKind.Markup, content, markup: true).With(new MarkupChunkGenerator());
}
public static SourceLocation GetLocationAndAdvance(this SourceLocationTracker self, string content)
{
var ret = self.CurrentLocation;
self.UpdateLocation(content);
return ret;
}
}
}

View File

@ -1,22 +0,0 @@
// 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 Microsoft.AspNetCore.Razor.Chunks.Generators;
namespace Microsoft.AspNetCore.Mvc.Razor
{
public class UnclassifiedCodeSpanConstructor
{
private readonly SpanConstructor _self;
public UnclassifiedCodeSpanConstructor(SpanConstructor self)
{
_self = self;
}
public SpanConstructor As(ISpanChunkGenerator codeGenerator)
{
return _self.With(codeGenerator);
}
}
}

View File

@ -26,7 +26,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
.ConfigureApplicationPartManager(manager =>
{
manager.ApplicationParts.Add(new TestApplicationPart());
manager.FeatureProviders.Add(new TagHelperFeatureProvider());
});
// Act
@ -35,9 +34,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
// Assert
var activatorDescriptor = Assert.Single(services.ToList(), d => d.ServiceType == typeof(ITagHelperActivator));
Assert.Equal(typeof(ServiceBasedTagHelperActivator), activatorDescriptor.ImplementationType);
var resolverDescriptor = Assert.Single(services.ToList(), d => d.ServiceType == typeof(ITagHelperTypeResolver));
Assert.Equal(typeof(FeatureTagHelperTypeResolver), resolverDescriptor.ImplementationType);
}
[Fact]
@ -60,9 +56,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
// Assert
var collection = services.ToList();
Assert.Equal(4, collection.Count);
Assert.Equal(3, collection.Count);
var tagHelperOne = Assert.Single(collection,t => t.ServiceType == typeof(TestTagHelperOne));
var tagHelperOne = Assert.Single(collection, t => t.ServiceType == typeof(TestTagHelperOne));
Assert.Equal(typeof(TestTagHelperOne), tagHelperOne.ImplementationType);
Assert.Equal(ServiceLifetime.Transient, tagHelperOne.Lifetime);
@ -73,10 +69,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
var activator = Assert.Single(collection, t => t.ServiceType == typeof(ITagHelperActivator));
Assert.Equal(typeof(ServiceBasedTagHelperActivator), activator.ImplementationType);
Assert.Equal(ServiceLifetime.Transient, activator.Lifetime);
var typeResolver = Assert.Single(collection, t => t.ServiceType == typeof(ITagHelperTypeResolver));
Assert.Equal(typeof(FeatureTagHelperTypeResolver), typeResolver.ImplementationType);
Assert.Equal(ServiceLifetime.Transient, typeResolver.Lifetime);
}
private class TestTagHelperOne : TagHelper

View File

@ -115,7 +115,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
.ConfigureApplicationPartManager(manager =>
{
manager.ApplicationParts.Add(new TestApplicationPart());
manager.FeatureProviders.Add(new TagHelperFeatureProvider());
});
// Act
@ -124,9 +123,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
// Assert
var activatorDescriptor = Assert.Single(services.ToList(), d => d.ServiceType == typeof(ITagHelperActivator));
Assert.Equal(typeof(ServiceBasedTagHelperActivator), activatorDescriptor.ImplementationType);
var resolverDescriptor = Assert.Single(services.ToList(), d => d.ServiceType == typeof(ITagHelperTypeResolver));
Assert.Equal(typeof(FeatureTagHelperTypeResolver), resolverDescriptor.ImplementationType);
}
[Fact]
@ -149,7 +145,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
// Assert
var collection = services.ToList();
Assert.Equal(4, collection.Count);
Assert.Equal(3, collection.Count);
var tagHelperOne = Assert.Single(collection, t => t.ServiceType == typeof(TestTagHelperOne));
Assert.Equal(typeof(TestTagHelperOne), tagHelperOne.ImplementationType);
@ -162,10 +158,6 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test.DependencyInjection
var activator = Assert.Single(collection, t => t.ServiceType == typeof(ITagHelperActivator));
Assert.Equal(typeof(ServiceBasedTagHelperActivator), activator.ImplementationType);
Assert.Equal(ServiceLifetime.Transient, activator.Lifetime);
var typeResolver = Assert.Single(collection, t => t.ServiceType == typeof(ITagHelperTypeResolver));
Assert.Equal(typeof(FeatureTagHelperTypeResolver), typeResolver.ImplementationType);
Assert.Equal(ServiceLifetime.Transient, typeResolver.Lifetime);
}
private class TestTagHelperOne : TagHelper

View File

@ -1,368 +0,0 @@
// 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;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Razor.Host;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.AspNetCore.Razor.Compilation.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers.Testing;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.Test.Internal
{
public class ViewComponentTagHelperDescriptorFactoryTest
{
public static TheoryData AssemblyData
{
get
{
var provider = new TestViewComponentDescriptorProvider();
var assemblyOne = "Microsoft.AspNetCore.Mvc.Razor";
var assemblyTwo = "Microsoft.AspNetCore.Mvc.Razor.Test";
var assemblyNone = string.Empty;
return new TheoryData<string, IEnumerable<TagHelperDescriptor>>
{
{ assemblyOne, new [] { provider.GetTagHelperDescriptorOne() } },
{ assemblyTwo, new [] { provider.GetTagHelperDescriptorTwo(), provider.GetTagHelperDescriptorGeneric() } },
{ assemblyNone, Enumerable.Empty<TagHelperDescriptor>() }
};
}
}
[Theory]
[MemberData(nameof(AssemblyData))]
public void CreateDescriptors_ReturnsCorrectDescriptors(
string assemblyName,
IEnumerable<TagHelperDescriptor> expectedDescriptors)
{
// Arrange
var provider = new TestViewComponentDescriptorProvider();
var factory = new ViewComponentTagHelperDescriptorFactory(provider);
// Act
var descriptors = factory.CreateDescriptors(assemblyName);
// Assert
Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default);
}
public static TheoryData TypeData
{
get
{
var refParamType = typeof(ViewComponentTagHelperDescriptorFactoryTest).GetMethod("MethodWithRefParam").GetParameters().First().ParameterType;
return new TheoryData<Type, string>
{
{ typeof(string), "System.String" },
{ typeof(string[,]), "System.String[,]" },
{ typeof(List<int*[]>), "System.Collections.Generic.List<global::System.Int32*[]>" },
{ typeof(List<string[,,]>), "System.Collections.Generic.List<global::System.String[,,]>" },
{ typeof(Dictionary<string[], List<string>>),
"System.Collections.Generic.Dictionary<global::System.String[], global::System.Collections.Generic.List<global::System.String>>" },
{ typeof(Dictionary<string, List<string[,]>>),
"System.Collections.Generic.Dictionary<global::System.String, global::System.Collections.Generic.List<global::System.String[,]>>" },
{ refParamType, "System.String[]" },
{ typeof(NonGeneric.Nested1<bool, string>.Nested2),
"Microsoft.AspNetCore.Mvc.Razor.Test.Internal.ViewComponentTagHelperDescriptorFactoryTest.NonGeneric.Nested1<global::System.Boolean, global::System.String>.Nested2" },
{ typeof(GenericType<string, int>.GenericNestedType<bool, string>),
"Microsoft.AspNetCore.Mvc.Razor.Test.Internal.ViewComponentTagHelperDescriptorFactoryTest.GenericType<global::System.String, global::System.Int32>.GenericNestedType<global::System.Boolean, global::System.String>" },
{ typeof(GenericType<string, int>.NonGenericNested.MultiNestedType<bool, string>),
"Microsoft.AspNetCore.Mvc.Razor.Test.Internal.ViewComponentTagHelperDescriptorFactoryTest.GenericType<global::System.String, global::System.Int32>.NonGenericNested.MultiNestedType<global::System.Boolean, global::System.String>" },
{ typeof(Dictionary<GenericType<string, int>.NonGenericNested.MultiNestedType<bool, string>, List<string[]>>),
"System.Collections.Generic.Dictionary<global::Microsoft.AspNetCore.Mvc.Razor.Test.Internal.ViewComponentTagHelperDescriptorFactoryTest.GenericType<global::System.String, global::System.Int32>.NonGenericNested.MultiNestedType<global::System.Boolean, global::System.String>, global::System.Collections.Generic.List<global::System.String[]>>" },
};
}
}
[Theory]
[MemberData(nameof(TypeData))]
public void GetCSharpTypeName_ReturnsCorrectTypeNames(Type type, string expected)
{
// Act
var typeName = ViewComponentTagHelperDescriptorFactory.GetCSharpTypeName(type);
// Assert
Assert.Equal(expected, typeName);
}
// Separated from GetCSharpTypeName_ReturnsCorrectTypeNames to work around problems serializing and
// deserializing this ref type.
[Fact]
public void GetCSharpTypeName_ReturnsCorrectTypeNames_ForOutParameter()
{
// Arrange
var type = typeof(ViewComponentTagHelperDescriptorFactoryTest).GetMethod("MethodWithOutParam").GetParameters().First().ParameterType;
var expected = "System.Collections.Generic.List<global::System.Char*[]>";
// Act
var typeName = ViewComponentTagHelperDescriptorFactory.GetCSharpTypeName(type);
// Assert
Assert.Equal(expected, typeName);
}
// Test invokes are needed for method creation in TestViewComponentDescriptorProvider.
public enum TestEnum
{
A = 1,
B = 2,
C = 3
}
public void TestInvokeOne(string foo, string bar)
{
}
public void TestInvokeTwo(TestEnum testEnum, string testString, int baz = 5)
{
}
public void InvokeWithGenericParams(List<string> Foo, Dictionary<string, int> Bar)
{
}
public void InvokeWithOpenGeneric<T>(List<T> baz)
{
}
private class TestViewComponentDescriptorProvider : IViewComponentDescriptorProvider
{
private readonly ViewComponentDescriptor _viewComponentDescriptorOne = new ViewComponentDescriptor
{
DisplayName = "OneDisplayName",
FullName = "OneViewComponent",
ShortName = "One",
MethodInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.TestInvokeOne)),
TypeInfo = typeof(ViewComponentTagHelperDescriptorFactory).GetTypeInfo(),
Parameters = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.TestInvokeOne)).GetParameters()
};
private readonly ViewComponentDescriptor _viewComponentDescriptorTwo = new ViewComponentDescriptor
{
DisplayName = "TwoDisplayName",
FullName = "TwoViewComponent",
ShortName = "Two",
MethodInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.TestInvokeTwo)),
TypeInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest).GetTypeInfo(),
Parameters = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.TestInvokeTwo)).GetParameters()
};
private readonly ViewComponentDescriptor _viewComponentDescriptorGeneric = new ViewComponentDescriptor
{
DisplayName = "GenericDisplayName",
FullName = "GenericViewComponent",
ShortName = "Generic",
MethodInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.InvokeWithGenericParams)),
TypeInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest).GetTypeInfo(),
Parameters = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.InvokeWithGenericParams)).GetParameters()
};
private readonly ViewComponentDescriptor _viewComponentDescriptorOpenGeneric = new ViewComponentDescriptor
{
DisplayName = "OpenGenericDisplayName",
FullName = "OpenGenericViewComponent",
ShortName = "OpenGeneric",
MethodInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.InvokeWithOpenGeneric)),
TypeInfo = typeof(ViewComponentTagHelperDescriptorFactoryTest).GetTypeInfo(),
Parameters = typeof(ViewComponentTagHelperDescriptorFactoryTest)
.GetMethod(nameof(ViewComponentTagHelperDescriptorFactoryTest.InvokeWithOpenGeneric)).GetParameters()
};
public TagHelperDescriptor GetTagHelperDescriptorOne()
{
var descriptor = new TagHelperDescriptor
{
TagName = "vc:one",
TypeName = "__Generated__OneViewComponentTagHelper",
AssemblyName = "Microsoft.AspNetCore.Mvc.Razor",
Attributes = new List<TagHelperAttributeDescriptor>
{
new TagHelperAttributeDescriptor
{
Name = "foo",
PropertyName = "foo",
TypeName = typeof(string).FullName
},
new TagHelperAttributeDescriptor
{
Name = "bar",
PropertyName = "bar",
TypeName = typeof(string).FullName
}
},
RequiredAttributes = new List<TagHelperRequiredAttributeDescriptor>
{
new TagHelperRequiredAttributeDescriptor
{
Name = "foo"
},
new TagHelperRequiredAttributeDescriptor
{
Name = "bar"
}
}
};
descriptor.PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "One");
return descriptor;
}
public TagHelperDescriptor GetTagHelperDescriptorTwo()
{
var descriptor = new TagHelperDescriptor
{
TagName = "vc:two",
TypeName = "__Generated__TwoViewComponentTagHelper",
AssemblyName = "Microsoft.AspNetCore.Mvc.Razor.Test",
Attributes = new List<TagHelperAttributeDescriptor>
{
new TagHelperAttributeDescriptor
{
Name = "test-enum",
PropertyName = "testEnum",
TypeName = ViewComponentTagHelperDescriptorFactory.GetCSharpTypeName(typeof(TestEnum)),
IsEnum = true
},
new TagHelperAttributeDescriptor
{
Name = "test-string",
PropertyName = "testString",
TypeName = typeof(string).FullName
},
new TagHelperAttributeDescriptor
{
Name = "baz",
PropertyName = "baz",
TypeName = typeof(int).FullName
}
},
RequiredAttributes = new List<TagHelperRequiredAttributeDescriptor>
{
new TagHelperRequiredAttributeDescriptor
{
Name = "test-enum"
},
new TagHelperRequiredAttributeDescriptor
{
Name = "test-string"
},
new TagHelperRequiredAttributeDescriptor
{
Name = "baz"
}
}
};
descriptor.PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "Two");
return descriptor;
}
public TagHelperDescriptor GetTagHelperDescriptorGeneric()
{
var descriptor = new TagHelperDescriptor
{
TagName = "vc:generic",
TypeName = "__Generated__GenericViewComponentTagHelper",
AssemblyName = "Microsoft.AspNetCore.Mvc.Razor.Test",
Attributes = new List<TagHelperAttributeDescriptor>
{
new TagHelperAttributeDescriptor
{
Name = "foo",
PropertyName = "Foo",
TypeName = ViewComponentTagHelperDescriptorFactory.GetCSharpTypeName(typeof(List<string>))
},
new TagHelperAttributeDescriptor
{
Name = "bar",
PropertyName = "Bar",
TypeName = ViewComponentTagHelperDescriptorFactory.GetCSharpTypeName(typeof(Dictionary<string, int>))
},
new TagHelperAttributeDescriptor
{
Name = "bar-",
PropertyName = "Bar",
TypeName = typeof(int).FullName,
IsIndexer = true
}
},
RequiredAttributes = new List<TagHelperRequiredAttributeDescriptor>
{
new TagHelperRequiredAttributeDescriptor
{
Name = "foo"
}
}
};
descriptor.PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "Generic");
return descriptor;
}
public IEnumerable<ViewComponentDescriptor> GetViewComponents()
{
return new List<ViewComponentDescriptor>
{
_viewComponentDescriptorOne,
_viewComponentDescriptorTwo,
_viewComponentDescriptorGeneric,
_viewComponentDescriptorOpenGeneric
};
}
}
public void MethodWithOutParam(out List<char*[]> foo)
{
foo = null;
}
public void MethodWithRefParam(ref string[] bar)
{
}
private class GenericType<T1, T2>
{
public class GenericNestedType<T3, T4>
{
}
public class NonGenericNested
{
public class MultiNestedType<T5, T6>
{
}
}
}
private class NonGeneric
{
public class Nested1<T1, T2>
{
public class Nested2
{
}
}
}
}
}

View File

@ -1,248 +0,0 @@
// 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.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Chunks.Generators;
using Microsoft.AspNetCore.Razor.Editor;
using Microsoft.AspNetCore.Razor.Parser.SyntaxTree;
using Microsoft.AspNetCore.Razor.Text;
using Microsoft.AspNetCore.Razor.Tokenizer;
using Microsoft.AspNetCore.Razor.Tokenizer.Internal;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols;
using Microsoft.AspNetCore.Razor.Tokenizer.Symbols.Internal;
namespace Microsoft.AspNetCore.Mvc.Razor.Host.Test
{
public static class SpanFactoryExtensions
{
public static SpanConstructor EmptyHtml(this SpanFactory self)
{
return self.Span(SpanKind.Markup, new HtmlSymbol(self.LocationTracker.CurrentLocation, String.Empty, HtmlSymbolType.Unknown))
.With(new MarkupChunkGenerator());
}
public static UnclassifiedCodeSpanConstructor Code(this SpanFactory self, string content)
{
return new UnclassifiedCodeSpanConstructor(
self.Span(SpanKind.Code, content, markup: false));
}
public static SpanConstructor CodeTransition(this SpanFactory self, string content)
{
return self.Span(SpanKind.Transition, content, markup: false).Accepts(AcceptedCharacters.None);
}
public static SpanConstructor MetaCode(this SpanFactory self, string content)
{
return self.Span(SpanKind.MetaCode, content, markup: false);
}
public static SpanConstructor Markup(this SpanFactory self, string content)
{
return self.Span(SpanKind.Markup, content, markup: true).With(new MarkupChunkGenerator());
}
}
public class SpanFactory
{
public Func<ITextDocument, ITokenizer> MarkupTokenizerFactory { get; set; }
public Func<ITextDocument, ITokenizer> CodeTokenizerFactory { get; set; }
public SourceLocationTracker LocationTracker { get; private set; }
public static SpanFactory CreateCsHtml()
{
return new SpanFactory()
{
MarkupTokenizerFactory = doc => new HtmlTokenizer(doc),
CodeTokenizerFactory = doc => new CSharpTokenizer(doc)
};
}
public SpanFactory()
{
LocationTracker = new SourceLocationTracker();
}
public SpanConstructor Span(SpanKind kind, string content, bool markup)
{
return new SpanConstructor(kind, Tokenize(new[] { content }, markup));
}
public SpanConstructor Span(SpanKind kind, params ISymbol[] symbols)
{
return new SpanConstructor(kind, symbols);
}
private IEnumerable<ISymbol> Tokenize(IEnumerable<string> contentFragments, bool markup)
{
return contentFragments.SelectMany(fragment => Tokenize(fragment, markup));
}
private IEnumerable<ISymbol> Tokenize(string content, bool markup)
{
ITokenizer tok = MakeTokenizer(markup, new SeekableTextReader(content));
ISymbol sym;
ISymbol last = null;
while ((sym = tok.NextSymbol()) != null)
{
OffsetStart(sym, LocationTracker.CurrentLocation);
last = sym;
yield return sym;
}
LocationTracker.UpdateLocation(content);
}
private ITokenizer MakeTokenizer(bool markup, SeekableTextReader seekableTextReader)
{
if (markup)
{
return MarkupTokenizerFactory(seekableTextReader);
}
else
{
return CodeTokenizerFactory(seekableTextReader);
}
}
private void OffsetStart(ISymbol sym, SourceLocation sourceLocation)
{
sym.OffsetStart(sourceLocation);
}
}
public static class SpanConstructorExtensions
{
public static SpanConstructor Accepts(this SpanConstructor self, AcceptedCharacters accepted)
{
return self.With(eh => eh.AcceptedCharacters = accepted);
}
}
public class UnclassifiedCodeSpanConstructor
{
SpanConstructor _self;
public UnclassifiedCodeSpanConstructor(SpanConstructor self)
{
_self = self;
}
public SpanConstructor As(ISpanChunkGenerator codeGenerator)
{
return _self.With(codeGenerator);
}
}
public class SpanConstructor
{
public SpanBuilder Builder { get; private set; }
internal static IEnumerable<ISymbol> TestTokenizer(string str)
{
yield return new RawTextSymbol(SourceLocation.Zero, str);
}
public SpanConstructor(SpanKind kind, IEnumerable<ISymbol> symbols)
{
Builder = new SpanBuilder();
Builder.Kind = kind;
Builder.EditHandler = SpanEditHandler.CreateDefault(TestTokenizer);
foreach (ISymbol sym in symbols)
{
Builder.Accept(sym);
}
}
private Span Build()
{
return Builder.Build();
}
public SpanConstructor With(ISpanChunkGenerator generator)
{
Builder.ChunkGenerator = generator;
return this;
}
public SpanConstructor With(SpanEditHandler handler)
{
Builder.EditHandler = handler;
return this;
}
public SpanConstructor With(Action<SpanEditHandler> handlerConfigurer)
{
handlerConfigurer(Builder.EditHandler);
return this;
}
public static implicit operator Span(SpanConstructor self)
{
return self.Build();
}
}
internal class RawTextSymbol : ISymbol
{
public SourceLocation Start { get; private set; }
public string Content { get; private set; }
public RawTextSymbol(SourceLocation start, string content)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
Start = start;
Content = content;
}
public override bool Equals(object obj)
{
RawTextSymbol other = obj as RawTextSymbol;
return Equals(Start, other.Start) && Equals(Content, other.Content);
}
internal bool EquivalentTo(ISymbol sym)
{
return Equals(Start, sym.Start) && Equals(Content, sym.Content);
}
public override int GetHashCode()
{
return Start.GetHashCode();
}
public void OffsetStart(SourceLocation documentStart)
{
Start = documentStart + Start;
}
public void ChangeStart(SourceLocation newStart)
{
Start = newStart;
}
public override string ToString()
{
return String.Format(CultureInfo.InvariantCulture, "{0} RAW - [{1}]", Start, Content);
}
internal void CalculateStart(Span prev)
{
if (prev == null)
{
Start = SourceLocation.Zero;
}
else
{
Start = new SourceLocationTracker(prev.Start).UpdateLocation(prev.Content).CurrentLocation;
}
}
}
}

View File

@ -1,99 +0,0 @@
// 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;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
{
public class FeatureTagHelperTypeResolverTest
{
[Fact]
public void Resolve_ReturnsTagHelpers_FromApplicationParts()
{
// Arrange
var manager = new ApplicationPartManager();
var types = new[] { typeof(TestTagHelper) };
manager.ApplicationParts.Add(new TestApplicationPart(types));
manager.FeatureProviders.Add(new TestFeatureProvider());
var resolver = new FeatureTagHelperTypeResolver(manager);
var assemblyName = typeof(FeatureTagHelperTypeResolverTest).GetTypeInfo().Assembly.GetName().Name;
// Act
var result = resolver.Resolve(assemblyName, SourceLocation.Undefined, new ErrorSink());
// Assert
var type = Assert.Single(result);
Assert.Equal(typeof(TestTagHelper), type);
}
[Fact]
public void Resolve_ReturnsTagHelpers_FilteredByAssembly()
{
// Arrange
var manager = new ApplicationPartManager();
var types = new[] { typeof(TestTagHelper) };
manager.ApplicationParts.Add(new AssemblyPart(typeof(InputTagHelper).GetTypeInfo().Assembly));
manager.ApplicationParts.Add(new TestApplicationPart(types));
manager.FeatureProviders.Add(new TestFeatureProvider());
var resolver = new FeatureTagHelperTypeResolver(manager);
var assemblyName = typeof(FeatureTagHelperTypeResolverTest).GetTypeInfo().Assembly.GetName().Name;
// Act
var result = resolver.Resolve(assemblyName, SourceLocation.Undefined, new ErrorSink());
// Assert
var type = Assert.Single(result);
Assert.Equal(typeof(TestTagHelper), type);
}
[Fact]
public void Resolve_ReturnsEmptyTypesList_IfAssemblyLoadFails()
{
// Arrange
var manager = new ApplicationPartManager();
var types = new[] { typeof(TestTagHelper) };
manager.ApplicationParts.Add(new AssemblyPart(typeof(InputTagHelper).GetTypeInfo().Assembly));
manager.ApplicationParts.Add(new TestApplicationPart(types));
manager.FeatureProviders.Add(new TestFeatureProvider());
var resolver = new FeatureTagHelperTypeResolver(manager);
// Act
var result = resolver.Resolve("UnknownAssembly", SourceLocation.Undefined, new ErrorSink());
// Assert
Assert.Empty(result);
}
private class TestFeatureProvider : IApplicationFeatureProvider<TagHelperFeature>
{
public void PopulateFeature(IEnumerable<ApplicationPart> parts, TagHelperFeature feature)
{
foreach (var type in parts.OfType<IApplicationPartTypeProvider>().SelectMany(tp => tp.Types))
{
feature.TagHelpers.Add(type);
}
}
}
private class TestTagHelper : TagHelper
{
}
private class NotInPartsTagHelper : TagHelper
{
}
}
}

View File

@ -1,87 +0,0 @@
// 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.Collections.Generic;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers.TagHelperFeatureProviderTests;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
{
public class TagHelperFeatureProviderTest
{
[Fact]
public void Populate_IncludesTagHelpers()
{
// Arrange
var manager = new ApplicationPartManager();
manager.ApplicationParts.Add(new TestApplicationPart(typeof(DiscoveryTagHelper)));
manager.FeatureProviders.Add(new TagHelperFeatureProvider());
var feature = new TagHelperFeature();
// Act
manager.PopulateFeature(feature);
// Assert
var tagHelperType = Assert.Single(feature.TagHelpers, th => th == typeof(DiscoveryTagHelper).GetTypeInfo());
}
[Fact]
public void Populate_DoesNotIncludeDuplicateTagHelpers()
{
// Arrange
var manager = new ApplicationPartManager();
manager.ApplicationParts.Add(new TestApplicationPart(typeof(DiscoveryTagHelper)));
manager.ApplicationParts.Add(new TestApplicationPart(typeof(DiscoveryTagHelper)));
manager.FeatureProviders.Add(new TagHelperFeatureProvider());
var feature = new TagHelperFeature();
// Act
manager.PopulateFeature(feature);
// Assert
var tagHelperType = Assert.Single(feature.TagHelpers, th => th == typeof(DiscoveryTagHelper).GetTypeInfo());
}
[Fact]
public void Populate_OnlyRunsOnPartsThatExportTypes()
{
// Arrange
var manager = new ApplicationPartManager();
manager.ApplicationParts.Add(new TestApplicationPart(typeof(DiscoveryTagHelper)));
manager.ApplicationParts.Add(new NonApplicationTypeProviderPart());
manager.FeatureProviders.Add(new TagHelperFeatureProvider());
var feature = new TagHelperFeature();
// Act
manager.PopulateFeature(feature);
// Assert
var tagHelperType = Assert.Single(feature.TagHelpers, th => th == typeof(DiscoveryTagHelper).GetTypeInfo());
}
private class NonApplicationTypeProviderPart : ApplicationPart
{
public override string Name => nameof(NonApplicationTypeProviderPart);
public IEnumerable<TypeInfo> Types => new[] { typeof(AnotherTagHelper).GetTypeInfo() };
}
}
}
// These types need to be public for the test to work.
namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers.TagHelperFeatureProviderTests
{
public class DiscoveryTagHelper : TagHelper
{
}
public class AnotherTagHelper : TagHelper
{
}
}

View File

@ -212,7 +212,6 @@ namespace Microsoft.AspNetCore.Mvc
Assert.Collection(manager.FeatureProviders,
feature => Assert.IsType<ControllerFeatureProvider>(feature),
feature => Assert.IsType<ViewComponentFeatureProvider>(feature),
feature => Assert.IsType<TagHelperFeatureProvider>(feature),
feature => Assert.IsType<MetadataReferenceFeatureProvider>(feature),
feature => Assert.IsType<ViewsFeatureProvider>(feature));
}

View File

@ -11,7 +11,6 @@
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.ViewFeatures\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Options" Version="$(AspNetCoreVersion)" />

View File

@ -1,10 +1,8 @@
// 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.Text.RegularExpressions;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Testing;
namespace Microsoft.AspNetCore.Mvc
@ -42,14 +40,5 @@ namespace Microsoft.AspNetCore.Mvc
return input;
}
// Assuming windows based source location is passed in,
// it gets normalized to other platforms.
public static SourceLocation NormalizedSourceLocation(int absoluteIndex, int lineIndex, int characterIndex)
{
var windowsNewLineLength = "\r\n".Length;
var differenceInLength = windowsNewLineLength - Environment.NewLine.Length;
return new SourceLocation(absoluteIndex - (differenceInLength * lineIndex), lineIndex, characterIndex);
}
}
}

View File

@ -1,10 +1,6 @@
// 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;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace ControllersFromServicesWebSite.TagHelpers