diff --git a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs
index 9978fff71f..ec1ade272a 100644
--- a/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs
+++ b/src/Microsoft.AspNet.Razor.Runtime/TagHelpers/TagHelperDescriptorResolver.cs
@@ -30,37 +30,30 @@ namespace Microsoft.AspNet.Razor.Runtime.TagHelpers
}
///
- public IEnumerable Resolve(string lookupText)
+ public IEnumerable Resolve([NotNull] TagHelperDescriptorResolutionContext context)
{
- var lookupStrings = lookupText?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ var resolvedDescriptors = new HashSet(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;
}
///
@@ -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; }
+ }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/Parser/TagHelpers/AddOrRemoveTagHelperSpanVisitor.cs b/src/Microsoft.AspNet.Razor/Parser/TagHelpers/AddOrRemoveTagHelperSpanVisitor.cs
index fa5cc139bf..98283ee077 100644
--- a/src/Microsoft.AspNet.Razor/Parser/TagHelpers/AddOrRemoveTagHelperSpanVisitor.cs
+++ b/src/Microsoft.AspNet.Razor/Parser/TagHelpers/AddOrRemoveTagHelperSpanVisitor.cs
@@ -18,21 +18,24 @@ namespace Microsoft.AspNet.Razor.Parser.TagHelpers
{
private readonly ITagHelperDescriptorResolver _descriptorResolver;
- private List _descriptors;
+ private List _directiveDescriptors;
- public AddOrRemoveTagHelperSpanVisitor(ITagHelperDescriptorResolver descriptorResolver)
+ public AddOrRemoveTagHelperSpanVisitor([NotNull] ITagHelperDescriptorResolver descriptorResolver)
{
_descriptorResolver = descriptorResolver;
}
public IEnumerable GetDescriptors([NotNull] Block root)
{
- _descriptors = new List();
+ _directiveDescriptors = new List();
// 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(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);
}
}
}
diff --git a/src/Microsoft.AspNet.Razor/Properties/RazorResources.Designer.cs b/src/Microsoft.AspNet.Razor/Properties/RazorResources.Designer.cs
index cd468b4d71..0bab77f769 100644
--- a/src/Microsoft.AspNet.Razor/Properties/RazorResources.Designer.cs
+++ b/src/Microsoft.AspNet.Razor/Properties/RazorResources.Designer.cs
@@ -1526,22 +1526,6 @@ namespace Microsoft.AspNet.Razor
return string.Format(CultureInfo.CurrentCulture, GetString("ParseError_DirectiveMustBeSurroundedByQuotes"), p0);
}
- ///
- /// Cannot use directive '{0}' when a {1} has not been provided to the {2}.
- ///
- internal static string TagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver
- {
- get { return GetString("TagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver"); }
- }
-
- ///
- /// Cannot use directive '{0}' when a {1} has not been provided to the {2}.
- ///
- internal static string FormatTagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver(object p0, object p1, object p2)
- {
- return string.Format(CultureInfo.CurrentCulture, GetString("TagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver"), p0, p1, p2);
- }
-
///
/// Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or be self closing.
///
diff --git a/src/Microsoft.AspNet.Razor/RazorResources.resx b/src/Microsoft.AspNet.Razor/RazorResources.resx
index 476f47f4ce..cdca65f247 100644
--- a/src/Microsoft.AspNet.Razor/RazorResources.resx
+++ b/src/Microsoft.AspNet.Razor/RazorResources.resx
@@ -421,9 +421,6 @@ Instead, wrap the contents of the block in "{{}}":
Directive '{0}'s value must be surrounded in double quotes.
-
- Cannot use directive '{0}' when a {1} has not been provided to the {2}.
-
Found a malformed '{0}' tag helper. Tag helpers must have a start and end tag or be self closing.
diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/ITagHelperDescriptorResolver.cs b/src/Microsoft.AspNet.Razor/TagHelpers/ITagHelperDescriptorResolver.cs
index 747242a8a0..be9fb00209 100644
--- a/src/Microsoft.AspNet.Razor/TagHelpers/ITagHelperDescriptorResolver.cs
+++ b/src/Microsoft.AspNet.Razor/TagHelpers/ITagHelperDescriptorResolver.cs
@@ -11,13 +11,13 @@ namespace Microsoft.AspNet.Razor.TagHelpers
public interface ITagHelperDescriptorResolver
{
///
- /// Resolves s matching the given .
+ /// Resolves s based on the given .
///
- ///
- /// A used to find tag helper s.
+ ///
+ /// used to resolve descriptors for the Razor page.
///
- /// An of s matching
- /// the given .
- IEnumerable Resolve(string lookupText);
+ /// An of s based
+ /// on the given .
+ IEnumerable Resolve(TagHelperDescriptorResolutionContext resolutionContext);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptorResolutionContext.cs b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptorResolutionContext.cs
new file mode 100644
index 0000000000..9a127edf55
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDescriptorResolutionContext.cs
@@ -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
+{
+ ///
+ /// Contains information needed to resolve s.
+ ///
+ public class TagHelperDescriptorResolutionContext
+ {
+ ///
+ /// Instantiates a new instance of .
+ ///
+ /// s used to resolve
+ /// s.
+ public TagHelperDescriptorResolutionContext(
+ [NotNull] IEnumerable directiveDescriptors)
+ {
+ DirectiveDescriptors = new List(directiveDescriptors);
+ }
+
+ ///
+ /// s used to resolve s.
+ ///
+ public IList DirectiveDescriptors { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDirectiveDescriptor.cs b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDirectiveDescriptor.cs
new file mode 100644
index 0000000000..efb9148592
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDirectiveDescriptor.cs
@@ -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
+{
+ ///
+ /// Contains information needed to resolve s.
+ ///
+ public class TagHelperDirectiveDescriptor
+ {
+ ///
+ /// Instantiates a new instance of .
+ ///
+ /// A used to find tag helper s.
+ /// The of this directive.
+ public TagHelperDirectiveDescriptor([NotNull] string lookupText, TagHelperDirectiveType directiveType)
+ {
+ LookupText = lookupText;
+ DirectiveType = directiveType;
+ }
+
+ ///
+ /// A used to find tag helper s.
+ ///
+ public string LookupText { get; private set; }
+
+ ///
+ /// The of this directive.
+ ///
+ public TagHelperDirectiveType DirectiveType { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDirectiveType.cs b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDirectiveType.cs
new file mode 100644
index 0000000000..88eb9eb9e5
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor/TagHelpers/TagHelperDirectiveType.cs
@@ -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
+{
+ ///
+ /// The type of tag helper directive.
+ ///
+ public enum TagHelperDirectiveType
+ {
+ ///
+ /// An @addtaghelper directive.
+ ///
+ AddTagHelper,
+
+ ///
+ /// A @removetaghelper directive.
+ ///
+ RemoveTagHelper
+ }
+}
\ No newline at end of file