Add ability to resolve all TagHelperDescriptors with one method call.
- Modified the AddOrRemoveTagHelperSpanVisitor to no longer manage TagHelperDescriptors found in the system. Instead it now manages TagHelperDirectiveDescriptors which are then used to resolve TagHelperDescriptors. - Changed the signature of ITagHelperDescriptorResolver to take in a TagHelperResolutionContext which will allow us to pass more information without breaking tooling. - TagHelperDescriptorResolver now resolves all TagHelperDescriptors at once and manages descriptors found in the system based on values on the provided TagHelperDirectiveDescriptors. #214
This commit is contained in:
parent
64a5b8ee22
commit
c35d19142c
|
|
@ -30,37 +30,30 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<TagHelperDescriptor> Resolve(string lookupText)
|
||||
public IEnumerable<TagHelperDescriptor> Resolve([NotNull] TagHelperDescriptorResolutionContext context)
|
||||
{
|
||||
var lookupStrings = lookupText?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var resolvedDescriptors = new HashSet<TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
|
||||
|
||||
// Ensure that we have valid lookupStrings to work with. Valid formats are:
|
||||
// "assemblyName"
|
||||
// "typeName, assemblyName"
|
||||
if (string.IsNullOrEmpty(lookupText) ||
|
||||
(lookupStrings.Length != 1 && lookupStrings.Length != 2))
|
||||
foreach (var directiveDescriptor in context.DirectiveDescriptors)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText),
|
||||
nameof(lookupText));
|
||||
var lookupInfo = GetLookupInfo(directiveDescriptor);
|
||||
|
||||
if (directiveDescriptor.DirectiveType == TagHelperDirectiveType.RemoveTagHelper)
|
||||
{
|
||||
resolvedDescriptors.RemoveWhere(descriptor => MatchesLookupInfo(descriptor, lookupInfo));
|
||||
}
|
||||
else if (directiveDescriptor.DirectiveType == TagHelperDirectiveType.AddTagHelper)
|
||||
{
|
||||
var descriptors = ResolveDescriptorsInAssembly(lookupInfo.AssemblyName);
|
||||
|
||||
// Only use descriptors that match our lookup info
|
||||
descriptors = descriptors.Where(descriptor => MatchesLookupInfo(descriptor, lookupInfo));
|
||||
|
||||
resolvedDescriptors.UnionWith(descriptors);
|
||||
}
|
||||
}
|
||||
|
||||
// Grab the assembly name from the lookup text strings. Due to our supported lookupText formats it will
|
||||
// always be the last element provided.
|
||||
var assemblyName = lookupStrings.Last().Trim();
|
||||
var descriptors = ResolveDescriptorsInAssembly(assemblyName);
|
||||
|
||||
// Check if the lookupText specifies a type to search for.
|
||||
if (lookupStrings.Length == 2)
|
||||
{
|
||||
// The user provided a type name. Retrieve it so we can prune our descriptors.
|
||||
var typeName = lookupStrings[0].Trim();
|
||||
|
||||
descriptors = descriptors.Where(descriptor =>
|
||||
string.Equals(descriptor.TypeName, typeName, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
return descriptors;
|
||||
return resolvedDescriptors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -83,5 +76,59 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
|
|||
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
private static bool MatchesLookupInfo(TagHelperDescriptor descriptor, LookupInfo lookupInfo)
|
||||
{
|
||||
if (!string.Equals(descriptor.AssemblyName, lookupInfo.AssemblyName, StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return string.IsNullOrEmpty(lookupInfo.TypeName) ||
|
||||
string.Equals(descriptor.TypeName, lookupInfo.TypeName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static LookupInfo GetLookupInfo(TagHelperDirectiveDescriptor directiveDescriptor)
|
||||
{
|
||||
var lookupText = directiveDescriptor.LookupText;
|
||||
var lookupStrings = lookupText?.Split(new[] { ',' });
|
||||
|
||||
// Ensure that we have valid lookupStrings to work with. Valid formats are:
|
||||
// "assemblyName"
|
||||
// "typeName, assemblyName"
|
||||
if (lookupStrings == null ||
|
||||
lookupStrings.Any(string.IsNullOrWhiteSpace) ||
|
||||
(lookupStrings.Length != 1 && lookupStrings.Length != 2))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText),
|
||||
nameof(lookupText));
|
||||
}
|
||||
|
||||
// Grab the assembly name from the lookup text strings. Due to our supported lookupText formats it will
|
||||
// always be the last element provided.
|
||||
var assemblyName = lookupStrings.Last().Trim();
|
||||
string typeName = null;
|
||||
|
||||
// Check if the lookupText specifies a type to search for.
|
||||
if (lookupStrings.Length == 2)
|
||||
{
|
||||
// The user provided a type name. Retrieve it so we can prune our descriptors.
|
||||
typeName = lookupStrings[0].Trim();
|
||||
}
|
||||
|
||||
return new LookupInfo
|
||||
{
|
||||
AssemblyName = assemblyName,
|
||||
TypeName = typeName
|
||||
};
|
||||
}
|
||||
|
||||
private class LookupInfo
|
||||
{
|
||||
public string AssemblyName { get; set; }
|
||||
|
||||
public string TypeName { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,21 +18,24 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
|||
{
|
||||
private readonly ITagHelperDescriptorResolver _descriptorResolver;
|
||||
|
||||
private List<TagHelperDescriptor> _descriptors;
|
||||
private List<TagHelperDirectiveDescriptor> _directiveDescriptors;
|
||||
|
||||
public AddOrRemoveTagHelperSpanVisitor(ITagHelperDescriptorResolver descriptorResolver)
|
||||
public AddOrRemoveTagHelperSpanVisitor([NotNull] ITagHelperDescriptorResolver descriptorResolver)
|
||||
{
|
||||
_descriptorResolver = descriptorResolver;
|
||||
}
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> GetDescriptors([NotNull] Block root)
|
||||
{
|
||||
_descriptors = new List<TagHelperDescriptor>();
|
||||
_directiveDescriptors = new List<TagHelperDirectiveDescriptor>();
|
||||
|
||||
// This will recurse through the syntax tree.
|
||||
VisitBlock(root);
|
||||
|
||||
return _descriptors;
|
||||
var resolutionContext = new TagHelperDescriptorResolutionContext(_directiveDescriptors);
|
||||
var descriptors = _descriptorResolver.Resolve(resolutionContext);
|
||||
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
public override void VisitSpan(Span span)
|
||||
|
|
@ -43,34 +46,13 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
|
|||
{
|
||||
var codeGenerator = (AddOrRemoveTagHelperCodeGenerator)span.CodeGenerator;
|
||||
|
||||
if (_descriptorResolver == null)
|
||||
{
|
||||
var directive = codeGenerator.RemoveTagHelperDescriptors ?
|
||||
SyntaxConstants.CSharp.RemoveTagHelperKeyword :
|
||||
SyntaxConstants.CSharp.AddTagHelperKeyword;
|
||||
var directive = codeGenerator.RemoveTagHelperDescriptors ?
|
||||
TagHelperDirectiveType.RemoveTagHelper :
|
||||
TagHelperDirectiveType.AddTagHelper;
|
||||
|
||||
throw new InvalidOperationException(
|
||||
RazorResources.FormatTagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver(
|
||||
directive, typeof(ITagHelperDescriptorResolver).FullName, typeof(RazorParser).FullName));
|
||||
}
|
||||
var directiveDescriptor = new TagHelperDirectiveDescriptor(codeGenerator.LookupText, directive);
|
||||
|
||||
// Look up all the descriptors associated with the "LookupText".
|
||||
var descriptors = _descriptorResolver.Resolve(codeGenerator.LookupText);
|
||||
|
||||
if (codeGenerator.RemoveTagHelperDescriptors)
|
||||
{
|
||||
var evaluatedDescriptors =
|
||||
new HashSet<TagHelperDescriptor>(descriptors, TagHelperDescriptorComparer.Default);
|
||||
|
||||
// We remove all found descriptors from the descriptor list to ignore the associated TagHelpers on the
|
||||
// Razor page.
|
||||
_descriptors.RemoveAll(descriptor => evaluatedDescriptors.Contains(descriptor));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add all the found descriptors to our list.
|
||||
_descriptors.AddRange(descriptors);
|
||||
}
|
||||
_directiveDescriptors.Add(directiveDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1526,22 +1526,6 @@ namespace Microsoft.AspNet.Razor
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("ParseError_DirectiveMustBeSurroundedByQuotes"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cannot use directive '{0}' when a {1} has not been provided to the {2}.
|
||||
/// </summary>
|
||||
internal static string TagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver
|
||||
{
|
||||
get { return GetString("TagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cannot use directive '{0}' when a {1} has not been provided to the {2}.
|
||||
/// </summary>
|
||||
internal static string FormatTagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver(object p0, object p1, object p2)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver"), p0, p1, p2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or be self closing.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -421,9 +421,6 @@ Instead, wrap the contents of the block in "{{}}":
|
|||
<data name="ParseError_DirectiveMustBeSurroundedByQuotes" xml:space="preserve">
|
||||
<value>Directive '{0}'s value must be surrounded in double quotes.</value>
|
||||
</data>
|
||||
<data name="TagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver" xml:space="preserve">
|
||||
<value>Cannot use directive '{0}' when a {1} has not been provided to the {2}.</value>
|
||||
</data>
|
||||
<data name="TagHelpersParseTreeRewriter_FoundMalformedTagHelper" xml:space="preserve">
|
||||
<value>Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or be self closing.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
|
|||
public interface ITagHelperDescriptorResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves <see cref="TagHelperDescriptor"/>s matching the given <paramref name="lookupText"/>.
|
||||
/// Resolves <see cref="TagHelperDescriptor"/>s based on the given <paramref name="resolutionContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="lookupText">
|
||||
/// A <see cref="string"/> used to find tag helper <see cref="Type"/>s.
|
||||
/// <param name="resolutionContext">
|
||||
/// <see cref="TagHelperDescriptorResolutionContext"/> used to resolve descriptors for the Razor page.
|
||||
/// </param>
|
||||
/// <returns>An <see cref="IEnumerable{TagHelperDescriptor}"/> of <see cref="TagHelperDescriptor"/>s matching
|
||||
/// the given <paramref name="lookupText"/>.</returns>
|
||||
IEnumerable<TagHelperDescriptor> Resolve(string lookupText);
|
||||
/// <returns>An <see cref="IEnumerable{TagHelperDescriptor}"/> of <see cref="TagHelperDescriptor"/>s based
|
||||
/// on the given <paramref name="resolutionContext"/>.</returns>
|
||||
IEnumerable<TagHelperDescriptor> Resolve(TagHelperDescriptorResolutionContext resolutionContext);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. 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;
|
||||
|
||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains information needed to resolve <see cref="TagHelperDescriptor"/>s.
|
||||
/// </summary>
|
||||
public class TagHelperDescriptorResolutionContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of <see cref="TagHelperDescriptorResolutionContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="directiveDescriptors"><see cref="TagHelperDirectiveDescriptor"/>s used to resolve
|
||||
/// <see cref="TagHelperDescriptor"/>s.</param>
|
||||
public TagHelperDescriptorResolutionContext(
|
||||
[NotNull] IEnumerable<TagHelperDirectiveDescriptor> directiveDescriptors)
|
||||
{
|
||||
DirectiveDescriptors = new List<TagHelperDirectiveDescriptor>(directiveDescriptors);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="TagHelperDirectiveDescriptor"/>s used to resolve <see cref="TagHelperDescriptor"/>s.
|
||||
/// </summary>
|
||||
public IList<TagHelperDirectiveDescriptor> DirectiveDescriptors { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains information needed to resolve <see cref="TagHelperDescriptor"/>s.
|
||||
/// </summary>
|
||||
public class TagHelperDirectiveDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of <see cref="TagHelperDirectiveDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <param name="lookupText">A <see cref="string"/> used to find tag helper <see cref="System.Type"/>s.</param>
|
||||
/// <param name="directiveType">The <see cref="TagHelperDirectiveType"/> of this directive.</param>
|
||||
public TagHelperDirectiveDescriptor([NotNull] string lookupText, TagHelperDirectiveType directiveType)
|
||||
{
|
||||
LookupText = lookupText;
|
||||
DirectiveType = directiveType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="string"/> used to find tag helper <see cref="System.Type"/>s.
|
||||
/// </summary>
|
||||
public string LookupText { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TagHelperDirectiveType"/> of this directive.
|
||||
/// </summary>
|
||||
public TagHelperDirectiveType DirectiveType { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Razor.TagHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of tag helper directive.
|
||||
/// </summary>
|
||||
public enum TagHelperDirectiveType
|
||||
{
|
||||
/// <summary>
|
||||
/// An @addtaghelper directive.
|
||||
/// </summary>
|
||||
AddTagHelper,
|
||||
|
||||
/// <summary>
|
||||
/// A @removetaghelper directive.
|
||||
/// </summary>
|
||||
RemoveTagHelper
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue