diff --git a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CSharp/Visitors/CSharpDesignTimeHelpersVisitor.cs b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CSharp/Visitors/CSharpDesignTimeHelpersVisitor.cs
index ce56958acd..1b01f815f2 100644
--- a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CSharp/Visitors/CSharpDesignTimeHelpersVisitor.cs
+++ b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CSharp/Visitors/CSharpDesignTimeHelpersVisitor.cs
@@ -59,6 +59,16 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
}
protected override void Visit(AddTagHelperChunk chunk)
+ {
+ VisitAddOrRemoveTagHelperChunk(chunk.LookupText, chunk);
+ }
+
+ protected override void Visit(RemoveTagHelperChunk chunk)
+ {
+ VisitAddOrRemoveTagHelperChunk(chunk.LookupText, chunk);
+ }
+
+ private void VisitAddOrRemoveTagHelperChunk(string lookupText, Chunk chunk)
{
// We should always be in design time mode because of the calling AcceptTree method verification.
Debug.Assert(Context.Host.DesignTimeMode);
@@ -71,12 +81,12 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
Writer.WriteStartAssignment(TagHelperDirectiveSyntaxHelper);
- // The parsing mechanism for the AddTagHelperChunk (CSharpCodeParser.TagHelperDirective()) removes quotes
- // that surround the chunk.LookupText.
+ // The parsing mechanism for the add/remove TagHelper chunk (CSharpCodeParser.TagHelperDirective())
+ // removes quotes that surround the lookupText.
_csharpCodeVisitor.CreateExpressionCodeMapping(
string.Format(
CultureInfo.InvariantCulture,
- "\"{0}\"", chunk.LookupText),
+ "\"{0}\"", lookupText),
chunk);
Writer.WriteLine(";");
diff --git a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/ChunkVisitor.cs b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/ChunkVisitor.cs
index 22db1736ae..0ebd5279c6 100644
--- a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/ChunkVisitor.cs
+++ b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/ChunkVisitor.cs
@@ -61,6 +61,10 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
{
Visit((AddTagHelperChunk)chunk);
}
+ else if (chunk is RemoveTagHelperChunk)
+ {
+ Visit((RemoveTagHelperChunk)chunk);
+ }
else if(chunk is SetLayoutChunk)
{
Visit((SetLayoutChunk)chunk);
@@ -120,6 +124,7 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
protected abstract void Visit(StatementChunk chunk);
protected abstract void Visit(TagHelperChunk chunk);
protected abstract void Visit(AddTagHelperChunk chunk);
+ protected abstract void Visit(RemoveTagHelperChunk chunk);
protected abstract void Visit(UsingChunk chunk);
protected abstract void Visit(ChunkBlock chunk);
protected abstract void Visit(DynamicCodeAttributeChunk chunk);
diff --git a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CodeVisitor.cs b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CodeVisitor.cs
index 618524f252..08e7709e67 100644
--- a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CodeVisitor.cs
+++ b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CodeVisitor.cs
@@ -35,6 +35,9 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
protected override void Visit(AddTagHelperChunk chunk)
{
}
+ protected override void Visit(RemoveTagHelperChunk chunk)
+ {
+ }
protected override void Visit(LiteralCodeAttributeChunk chunk)
{
}
diff --git a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeTree/Chunks/TagHelpers/RemoveTagHelperChunk.cs b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeTree/Chunks/TagHelpers/RemoveTagHelperChunk.cs
new file mode 100644
index 0000000000..c17107dcd1
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeTree/Chunks/TagHelpers/RemoveTagHelperChunk.cs
@@ -0,0 +1,18 @@
+// 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.Generator.Compiler
+{
+ ///
+ /// A used to look up s that should be ignored
+ /// within the Razor page.
+ ///
+ public class RemoveTagHelperChunk : Chunk
+ {
+ ///
+ /// Text used to look up s that should be ignored within the Razor
+ /// page.
+ ///
+ public string LookupText { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeTree/CodeTreeBuilder.cs b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeTree/CodeTreeBuilder.cs
index 1003d0b2ce..5ac2422251 100644
--- a/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeTree/CodeTreeBuilder.cs
+++ b/src/Microsoft.AspNet.Razor/Generator/Compiler/CodeTree/CodeTreeBuilder.cs
@@ -45,6 +45,14 @@ namespace Microsoft.AspNet.Razor.Generator.Compiler
}, association, topLevel: true);
}
+ public void AddRemoveTagHelperChunk(string lookupText, SyntaxTreeNode association)
+ {
+ AddChunk(new RemoveTagHelperChunk
+ {
+ LookupText = lookupText
+ }, association, topLevel: true);
+ }
+
public void AddLiteralChunk(string literal, SyntaxTreeNode association)
{
// If the previous chunk was also a LiteralChunk, append the content of the current node to the previous one.
diff --git a/src/Microsoft.AspNet.Razor/Generator/TagHelpers/AddOrRemoveTagHelperCodeGenerator.cs b/src/Microsoft.AspNet.Razor/Generator/TagHelpers/AddOrRemoveTagHelperCodeGenerator.cs
new file mode 100644
index 0000000000..4e37e1a8a1
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor/Generator/TagHelpers/AddOrRemoveTagHelperCodeGenerator.cs
@@ -0,0 +1,60 @@
+// 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 Microsoft.AspNet.Razor.Parser.SyntaxTree;
+
+namespace Microsoft.AspNet.Razor.Generator
+{
+ ///
+ /// A responsible for generating s and
+ /// s.
+ ///
+ public class AddOrRemoveTagHelperCodeGenerator : SpanCodeGenerator
+ {
+ ///
+ /// Instantiates a new .
+ ///
+ ///
+ /// Text used to look up s that should be added or removed.
+ ///
+ public AddOrRemoveTagHelperCodeGenerator(bool removeTagHelperDescriptors, string lookupText)
+ {
+ RemoveTagHelperDescriptors = removeTagHelperDescriptors;
+ LookupText = lookupText;
+ }
+
+ ///
+ /// Gets the text used to look up s that should be added to or
+ /// removed from the Razor page.
+ ///
+ public string LookupText { get; }
+
+ ///
+ /// Whether we want to remove s from the Razor page.
+ ///
+ /// If true generates s,
+ /// s otherwise.
+ public bool RemoveTagHelperDescriptors { get; }
+
+ ///
+ /// Generates s if is
+ /// true, otherwise s are generated.
+ ///
+ ///
+ /// The responsible for this .
+ ///
+ /// A instance that contains information about
+ /// the current code generation process.
+ public override void GenerateCode(Span target, CodeGeneratorContext context)
+ {
+ if (RemoveTagHelperDescriptors)
+ {
+ context.CodeTreeBuilder.AddRemoveTagHelperChunk(LookupText, target);
+ }
+ else
+ {
+ context.CodeTreeBuilder.AddAddTagHelperChunk(LookupText, target);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/Generator/TagHelpers/AddTagHelperCodeGenerator.cs b/src/Microsoft.AspNet.Razor/Generator/TagHelpers/AddTagHelperCodeGenerator.cs
deleted file mode 100644
index 9f79630974..0000000000
--- a/src/Microsoft.AspNet.Razor/Generator/TagHelpers/AddTagHelperCodeGenerator.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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 Microsoft.AspNet.Razor.Parser.SyntaxTree;
-
-namespace Microsoft.AspNet.Razor.Generator
-{
- ///
- /// A responsible for generating s.
- ///
- public class AddTagHelperCodeGenerator : SpanCodeGenerator
- {
- ///
- /// Instantiates a new .
- ///
- ///
- /// Text used to look up s.
- ///
- public AddTagHelperCodeGenerator(string lookupText)
- {
- LookupText = lookupText;
- }
-
- ///
- /// Text used to look up s.
- ///
- public string LookupText { get; private set; }
-
- ///
- /// Generates a .
- ///
- ///
- /// The responsible for this .
- ///
- /// A instance that contains information about
- /// the current code generation process.
- public override void GenerateCode(Span target, CodeGeneratorContext context)
- {
- context.CodeTreeBuilder.AddAddTagHelperChunk(LookupText, target);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs b/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs
index db0d49678c..e5ea9684f1 100644
--- a/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs
+++ b/src/Microsoft.AspNet.Razor/Parser/CSharpCodeParser.Directives.cs
@@ -20,6 +20,7 @@ namespace Microsoft.AspNet.Razor.Parser
private void SetupDirectives()
{
MapDirectives(AddTagHelperDirective, SyntaxConstants.CSharp.AddTagHelperKeyword);
+ MapDirectives(RemoveTagHelperDirective, SyntaxConstants.CSharp.RemoveTagHelperKeyword);
MapDirectives(InheritsDirective, SyntaxConstants.CSharp.InheritsKeyword);
MapDirectives(FunctionsDirective, SyntaxConstants.CSharp.FunctionsKeyword);
MapDirectives(SectionDirective, SyntaxConstants.CSharp.SectionKeyword);
@@ -30,10 +31,12 @@ namespace Microsoft.AspNet.Razor.Parser
protected virtual void AddTagHelperDirective()
{
- TagHelperDirective(SyntaxConstants.CSharp.AddTagHelperKeyword, (lookupText) =>
- {
- return new AddTagHelperCodeGenerator(lookupText);
- });
+ TagHelperDirective(SyntaxConstants.CSharp.AddTagHelperKeyword, removeTagHelperDescriptors: false);
+ }
+
+ protected virtual void RemoveTagHelperDirective()
+ {
+ TagHelperDirective(SyntaxConstants.CSharp.RemoveTagHelperKeyword, removeTagHelperDescriptors: true);
}
protected virtual void LayoutDirective()
@@ -508,7 +511,7 @@ namespace Microsoft.AspNet.Razor.Parser
Output(SpanKind.Code);
}
- private void TagHelperDirective(string keyword, Func codeGeneratorBuilder)
+ private void TagHelperDirective(string keyword, bool removeTagHelperDescriptors)
{
AssertDirective(keyword);
@@ -550,7 +553,8 @@ namespace Microsoft.AspNet.Razor.Parser
// renders the C# to colorize the user provided value. We trim the quotes around the user's value
// so when we render the code we can project the users value into double quotes to not invoke C#
// IntelliSense.
- Span.CodeGenerator = codeGeneratorBuilder(rawValue.Trim('"'));
+ Span.CodeGenerator =
+ new AddOrRemoveTagHelperCodeGenerator(removeTagHelperDescriptors, rawValue.Trim('"'));
}
// We expect the directive to be surrounded in quotes.
diff --git a/src/Microsoft.AspNet.Razor/Parser/RazorParser.cs b/src/Microsoft.AspNet.Razor/Parser/RazorParser.cs
index 240acfc4b4..619d2da07f 100644
--- a/src/Microsoft.AspNet.Razor/Parser/RazorParser.cs
+++ b/src/Microsoft.AspNet.Razor/Parser/RazorParser.cs
@@ -210,8 +210,8 @@ namespace Microsoft.AspNet.Razor.Parser
///
protected virtual IEnumerable GetTagHelperDescriptors([NotNull] Block documentRoot)
{
- var tagHelperRegistrationVisitor = new TagHelperRegistrationVisitor(TagHelperDescriptorResolver);
- return tagHelperRegistrationVisitor.GetDescriptors(documentRoot);
+ var addOrRemoveTagHelperSpanVisitor = new AddOrRemoveTagHelperSpanVisitor(TagHelperDescriptorResolver);
+ return addOrRemoveTagHelperSpanVisitor.GetDescriptors(documentRoot);
}
private static IEnumerable GetDefaultRewriters(ParserBase markupParser)
diff --git a/src/Microsoft.AspNet.Razor/Parser/SyntaxConstants.cs b/src/Microsoft.AspNet.Razor/Parser/SyntaxConstants.cs
index e931fd0f5f..2160cd1090 100644
--- a/src/Microsoft.AspNet.Razor/Parser/SyntaxConstants.cs
+++ b/src/Microsoft.AspNet.Razor/Parser/SyntaxConstants.cs
@@ -19,6 +19,7 @@ namespace Microsoft.AspNet.Razor.Parser
{
public static readonly int UsingKeywordLength = 5;
public static readonly string AddTagHelperKeyword = "addtaghelper";
+ public static readonly string RemoveTagHelperKeyword = "removetaghelper";
public static readonly string InheritsKeyword = "inherits";
public static readonly string FunctionsKeyword = "functions";
public static readonly string SectionKeyword = "section";
diff --git a/src/Microsoft.AspNet.Razor/Parser/TagHelpers/AddOrRemoveTagHelperSpanVisitor.cs b/src/Microsoft.AspNet.Razor/Parser/TagHelpers/AddOrRemoveTagHelperSpanVisitor.cs
new file mode 100644
index 0000000000..fa5cc139bf
--- /dev/null
+++ b/src/Microsoft.AspNet.Razor/Parser/TagHelpers/AddOrRemoveTagHelperSpanVisitor.cs
@@ -0,0 +1,77 @@
+// 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;
+using System.Linq;
+using Microsoft.AspNet.Razor.Generator;
+using Microsoft.AspNet.Razor.Parser.SyntaxTree;
+using Microsoft.AspNet.Razor.TagHelpers;
+
+namespace Microsoft.AspNet.Razor.Parser.TagHelpers
+{
+ ///
+ /// A that generates s from
+ /// tag helper code generators in a Razor document.
+ ///
+ public class AddOrRemoveTagHelperSpanVisitor : ParserVisitor
+ {
+ private readonly ITagHelperDescriptorResolver _descriptorResolver;
+
+ private List _descriptors;
+
+ public AddOrRemoveTagHelperSpanVisitor(ITagHelperDescriptorResolver descriptorResolver)
+ {
+ _descriptorResolver = descriptorResolver;
+ }
+
+ public IEnumerable GetDescriptors([NotNull] Block root)
+ {
+ _descriptors = new List();
+
+ // This will recurse through the syntax tree.
+ VisitBlock(root);
+
+ return _descriptors;
+ }
+
+ public override void VisitSpan(Span span)
+ {
+ // We're only interested in spans with an AddOrRemoveTagHelperCodeGenerator.
+
+ if (span.CodeGenerator is AddOrRemoveTagHelperCodeGenerator)
+ {
+ var codeGenerator = (AddOrRemoveTagHelperCodeGenerator)span.CodeGenerator;
+
+ if (_descriptorResolver == null)
+ {
+ var directive = codeGenerator.RemoveTagHelperDescriptors ?
+ SyntaxConstants.CSharp.RemoveTagHelperKeyword :
+ SyntaxConstants.CSharp.AddTagHelperKeyword;
+
+ throw new InvalidOperationException(
+ RazorResources.FormatTagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver(
+ directive, typeof(ITagHelperDescriptorResolver).FullName, typeof(RazorParser).FullName));
+ }
+
+ // 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);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Razor/Parser/TagHelpers/TagHelperRegistrationVisitor.cs b/src/Microsoft.AspNet.Razor/Parser/TagHelpers/TagHelperRegistrationVisitor.cs
deleted file mode 100644
index 818852f666..0000000000
--- a/src/Microsoft.AspNet.Razor/Parser/TagHelpers/TagHelperRegistrationVisitor.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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;
-using Microsoft.AspNet.Razor.Generator;
-using Microsoft.AspNet.Razor.Parser.SyntaxTree;
-using Microsoft.AspNet.Razor.TagHelpers;
-
-namespace Microsoft.AspNet.Razor.Parser.TagHelpers
-{
- ///
- /// A that generates s from
- /// tag helper code generators in a Razor document.
- ///
- public class TagHelperRegistrationVisitor : ParserVisitor
- {
- private readonly ITagHelperDescriptorResolver _descriptorResolver;
-
- private List _descriptors;
-
- public TagHelperRegistrationVisitor(ITagHelperDescriptorResolver descriptorResolver)
- {
- _descriptorResolver = descriptorResolver;
- }
-
- public IEnumerable GetDescriptors([NotNull] Block root)
- {
- _descriptors = new List();
-
- // This will recurse through the syntax tree.
- VisitBlock(root);
-
- return _descriptors;
- }
-
- public override void VisitSpan(Span span)
- {
- // We're only interested in spans with an AddTagHelperCodeGenerator.
- if (span.CodeGenerator is AddTagHelperCodeGenerator)
- {
- if (_descriptorResolver == null)
- {
- throw new InvalidOperationException(
- RazorResources.FormatTagHelpers_CannotUseDirectiveWithNoTagHelperDescriptorResolver(
- SyntaxConstants.CSharp.AddTagHelperKeyword,
- nameof(ITagHelperDescriptorResolver),
- nameof(RazorParser)));
- }
-
- var addGenerator = (AddTagHelperCodeGenerator)span.CodeGenerator;
-
- // Look up all the descriptors associated with the "LookupText".
- var descriptors = _descriptorResolver.Resolve(addGenerator.LookupText);
-
- // Add all the found descriptors to our HashSet.
- _descriptors.AddRange(descriptors);
- }
- }
- }
-}
\ No newline at end of file