Add @removetaghelper directive.
- Added parsing recognition of the @removetaghelper directive. - Added TagHelperDescriptor handling: @removetaghelper will cause the system to ignore TagHelpers that are added via @addtaghelper. - Added Chunk generation, this involved building a CodeGenerator (soon to be named ChunkGenerator) that pulled out the stringified @removetaghelper lookup text which it then uses to construct a RemoveTagHelperChunk. - Modified CodeVisitors to now understand RemoveTagHelperChunk's. - Added code generation, this involved creating a dummy string in order to give the @removetaghelper "..." coloring. #112
This commit is contained in:
parent
0dba621965
commit
30221f7ce0
|
|
@ -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(";");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="Chunk"/> used to look up <see cref="TagHelpers.TagHelperDescriptor"/>s that should be ignored
|
||||
/// within the Razor page.
|
||||
/// </summary>
|
||||
public class RemoveTagHelperChunk : Chunk
|
||||
{
|
||||
/// <summary>
|
||||
/// Text used to look up <see cref="TagHelpers.TagHelperDescriptor"/>s that should be ignored within the Razor
|
||||
/// page.
|
||||
/// </summary>
|
||||
public string LookupText { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="SpanCodeGenerator"/> responsible for generating <see cref="Compiler.AddTagHelperChunk"/>s and
|
||||
/// <see cref="Compiler.RemoveTagHelperChunk"/>s.
|
||||
/// </summary>
|
||||
public class AddOrRemoveTagHelperCodeGenerator : SpanCodeGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="AddOrRemoveTagHelperCodeGenerator"/>.
|
||||
/// </summary>
|
||||
/// <param name="lookupText">
|
||||
/// Text used to look up <see cref="TagHelpers.TagHelperDescriptor"/>s that should be added or removed.
|
||||
/// </param>
|
||||
public AddOrRemoveTagHelperCodeGenerator(bool removeTagHelperDescriptors, string lookupText)
|
||||
{
|
||||
RemoveTagHelperDescriptors = removeTagHelperDescriptors;
|
||||
LookupText = lookupText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the text used to look up <see cref="TagHelpers.TagHelperDescriptor"/>s that should be added to or
|
||||
/// removed from the Razor page.
|
||||
/// </summary>
|
||||
public string LookupText { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether we want to remove <see cref="TagHelpers.TagHelperDescriptor"/>s from the Razor page.
|
||||
/// </summary>
|
||||
/// <remarks>If <c>true</c> <see cref="GenerateCode"/> generates <see cref="Compiler.AddTagHelperChunk"/>s,
|
||||
/// <see cref="Compiler.RemoveTagHelperChunk"/>s otherwise.</remarks>
|
||||
public bool RemoveTagHelperDescriptors { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates <see cref="Compiler.AddTagHelperChunk"/>s if <see cref="RemoveTagHelperDescriptors"/> is
|
||||
/// <c>true</c>, otherwise <see cref="Compiler.RemoveTagHelperChunk"/>s are generated.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// The <see cref="Span"/> responsible for this <see cref="AddOrRemoveTagHelperCodeGenerator"/>.
|
||||
/// </param>
|
||||
/// <param name="context">A <see cref="CodeGeneratorContext"/> instance that contains information about
|
||||
/// the current code generation process.</param>
|
||||
public override void GenerateCode(Span target, CodeGeneratorContext context)
|
||||
{
|
||||
if (RemoveTagHelperDescriptors)
|
||||
{
|
||||
context.CodeTreeBuilder.AddRemoveTagHelperChunk(LookupText, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.CodeTreeBuilder.AddAddTagHelperChunk(LookupText, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="SpanCodeGenerator"/> responsible for generating <see cref="Compiler.AddTagHelperChunk"/>s.
|
||||
/// </summary>
|
||||
public class AddTagHelperCodeGenerator : SpanCodeGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="AddTagHelperCodeGenerator"/>.
|
||||
/// </summary>
|
||||
/// <param name="lookupText">
|
||||
/// Text used to look up <see cref="TagHelpers.TagHelperDescriptor"/>s.
|
||||
/// </param>
|
||||
public AddTagHelperCodeGenerator(string lookupText)
|
||||
{
|
||||
LookupText = lookupText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Text used to look up <see cref="TagHelpers.TagHelperDescriptor"/>s.
|
||||
/// </summary>
|
||||
public string LookupText { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates a <see cref="Compiler.AddTagHelperChunk"/>.
|
||||
/// </summary>
|
||||
/// <param name="target">
|
||||
/// The <see cref="Span"/> responsible for this <see cref="AddTagHelperCodeGenerator"/>.
|
||||
/// </param>
|
||||
/// <param name="context">A <see cref="CodeGeneratorContext"/> instance that contains information about
|
||||
/// the current code generation process.</param>
|
||||
public override void GenerateCode(Span target, CodeGeneratorContext context)
|
||||
{
|
||||
context.CodeTreeBuilder.AddAddTagHelperChunk(LookupText, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<string, SpanCodeGenerator> 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.
|
||||
|
|
|
|||
|
|
@ -210,8 +210,8 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
/// <returns></returns>
|
||||
protected virtual IEnumerable<TagHelperDescriptor> 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<ISyntaxTreeRewriter> GetDefaultRewriters(ParserBase markupParser)
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ParserVisitor"/> that generates <see cref="TagHelperDescriptor"/>s from
|
||||
/// tag helper code generators in a Razor document.
|
||||
/// </summary>
|
||||
public class AddOrRemoveTagHelperSpanVisitor : ParserVisitor
|
||||
{
|
||||
private readonly ITagHelperDescriptorResolver _descriptorResolver;
|
||||
|
||||
private List<TagHelperDescriptor> _descriptors;
|
||||
|
||||
public AddOrRemoveTagHelperSpanVisitor(ITagHelperDescriptorResolver descriptorResolver)
|
||||
{
|
||||
_descriptorResolver = descriptorResolver;
|
||||
}
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> GetDescriptors([NotNull] Block root)
|
||||
{
|
||||
_descriptors = new List<TagHelperDescriptor>();
|
||||
|
||||
// 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<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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ParserVisitor"/> that generates <see cref="TagHelperDescriptor"/>s from
|
||||
/// tag helper code generators in a Razor document.
|
||||
/// </summary>
|
||||
public class TagHelperRegistrationVisitor : ParserVisitor
|
||||
{
|
||||
private readonly ITagHelperDescriptorResolver _descriptorResolver;
|
||||
|
||||
private List<TagHelperDescriptor> _descriptors;
|
||||
|
||||
public TagHelperRegistrationVisitor(ITagHelperDescriptorResolver descriptorResolver)
|
||||
{
|
||||
_descriptorResolver = descriptorResolver;
|
||||
}
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> GetDescriptors([NotNull] Block root)
|
||||
{
|
||||
_descriptors = new List<TagHelperDescriptor>();
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue