Add attribute only bindings and fix dotnet/aspnetcore-tooling#6373
Adds a new API for WTE to call given a TagHelperBinding to determine if
the binding should colorize/classify only the attributes of the HTML
element in source code. This is driven by a new metadata item that the
Components 'directive attributes' all set. There's no way for a user to
access this feature via tag helpers currently, but it could be added
easily in the future.
Also fixing dotnet/aspnetcore-tooling#6376 while I'm in there. 👍
\n\nCommit migrated from df449beea9
This commit is contained in:
parent
148bc99cce
commit
40633dde21
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
foreach (var descriptor in bindingResult.Descriptors)
|
||||
{
|
||||
var boundRules = bindingResult.GetBoundRules(descriptor);
|
||||
var boundRules = bindingResult.Mappings[descriptor];
|
||||
var nonDefaultRule = boundRules.FirstOrDefault(rule => rule.TagStructure != TagStructure.Unspecified);
|
||||
|
||||
if (nonDefaultRule?.TagStructure == TagStructure.WithoutEndTag)
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
foreach (var descriptor in tagHelperBinding.Descriptors)
|
||||
{
|
||||
var boundRules = tagHelperBinding.GetBoundRules(descriptor);
|
||||
var boundRules = tagHelperBinding.Mappings[descriptor];
|
||||
var invalidRule = boundRules.FirstOrDefault(rule => rule.TagStructure == TagStructure.WithoutEndTag);
|
||||
|
||||
if (invalidRule != null)
|
||||
|
|
@ -456,7 +456,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
TagStructure? baseStructure = null;
|
||||
foreach (var descriptor in bindingResult.Descriptors)
|
||||
{
|
||||
var boundRules = bindingResult.GetBoundRules(descriptor);
|
||||
var boundRules = bindingResult.Mappings[descriptor];
|
||||
foreach (var rule in boundRules)
|
||||
{
|
||||
if (rule.TagStructure != TagStructure.Unspecified)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
public sealed class TagHelperBinding
|
||||
{
|
||||
private IReadOnlyDictionary<TagHelperDescriptor, IReadOnlyList<TagMatchingRuleDescriptor>> _mappings;
|
||||
|
||||
internal TagHelperBinding(
|
||||
string tagName,
|
||||
IReadOnlyList<KeyValuePair<string, string>> attributes,
|
||||
|
|
@ -19,12 +18,42 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
TagName = tagName;
|
||||
Attributes = attributes;
|
||||
ParentTagName = parentTagName;
|
||||
Mappings = mappings;
|
||||
TagHelperPrefix = tagHelperPrefix;
|
||||
|
||||
_mappings = mappings;
|
||||
}
|
||||
|
||||
public IEnumerable<TagHelperDescriptor> Descriptors => _mappings.Keys;
|
||||
public IEnumerable<TagHelperDescriptor> Descriptors => Mappings.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that indicates whether the the binding matched on attributes only.
|
||||
/// </summary>
|
||||
/// <returns><c>false</c> if the entire element should be classified as a tag helper.</returns>
|
||||
/// <remarks>
|
||||
/// If this returns <c>true</c>, use <c>TagHelperFactsService.GetBoundTagHelperAttributes</c> to find the
|
||||
/// set of attributes that should be considered part of the match.
|
||||
/// </remarks>
|
||||
public bool IsAttributeMatch
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var descriptor in Mappings.Keys)
|
||||
{
|
||||
if (!descriptor.Metadata.TryGetValue(TagHelperMetadata.Common.ClassifyAttributesOnly, out var value) ||
|
||||
!string.Equals(value, bool.TrueString, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// All the matching tag helpers want to be classified with **attributes only**.
|
||||
//
|
||||
// Ex: (components)
|
||||
//
|
||||
// <button onclick="..." />
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public string TagName { get; }
|
||||
|
||||
|
|
@ -32,11 +61,18 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
public IReadOnlyList<KeyValuePair<string, string>> Attributes { get; }
|
||||
|
||||
public IReadOnlyDictionary<TagHelperDescriptor, IReadOnlyList<TagMatchingRuleDescriptor>> Mappings { get; }
|
||||
|
||||
public string TagHelperPrefix { get; }
|
||||
|
||||
public IReadOnlyList<TagMatchingRuleDescriptor> GetBoundRules(TagHelperDescriptor descriptor)
|
||||
{
|
||||
return _mappings[descriptor];
|
||||
if (descriptor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(descriptor));
|
||||
}
|
||||
|
||||
return Mappings[descriptor];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
public static readonly string PropertyName = "Common.PropertyName";
|
||||
|
||||
public static readonly string TypeName = "Common.TypeName";
|
||||
|
||||
public static readonly string ClassifyAttributesOnly = "Common.ClassifyAttributesOnly";
|
||||
}
|
||||
|
||||
public static class Runtime
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
builder.Documentation = ComponentResources.BindTagHelper_Fallback_Documentation;
|
||||
|
||||
builder.Metadata.Add(BlazorMetadata.SpecialKindKey, BlazorMetadata.Bind.TagHelperKind);
|
||||
builder.Metadata.Add(TagHelperMetadata.Common.ClassifyAttributesOnly, bool.TrueString);
|
||||
builder.Metadata[TagHelperMetadata.Runtime.Name] = BlazorMetadata.Bind.RuntimeName;
|
||||
builder.Metadata[BlazorMetadata.Bind.FallbackKey] = bool.TrueString;
|
||||
|
||||
|
|
@ -257,6 +258,7 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
entry.ChangeAttribute);
|
||||
|
||||
builder.Metadata.Add(BlazorMetadata.SpecialKindKey, BlazorMetadata.Bind.TagHelperKind);
|
||||
builder.Metadata.Add(TagHelperMetadata.Common.ClassifyAttributesOnly, bool.TrueString);
|
||||
builder.Metadata[TagHelperMetadata.Runtime.Name] = BlazorMetadata.Bind.RuntimeName;
|
||||
builder.Metadata[BlazorMetadata.Bind.ValueAttribute] = entry.ValueAttribute;
|
||||
builder.Metadata[BlazorMetadata.Bind.ChangeAttribute] = entry.ChangeAttribute;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
var eventHandlerData = GetEventHandlerData(compilation);
|
||||
|
||||
foreach (var tagHelper in CreateEventHandlerTagHelpers(eventHandlerData))
|
||||
|
|
@ -112,6 +111,7 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
|
||||
builder.Metadata.Add(BlazorMetadata.SpecialKindKey, BlazorMetadata.EventHandler.TagHelperKind);
|
||||
builder.Metadata.Add(BlazorMetadata.EventHandler.EventArgsType, entry.EventArgsType.ToDisplayString());
|
||||
builder.Metadata.Add(TagHelperMetadata.Common.ClassifyAttributesOnly, bool.TrueString);
|
||||
builder.Metadata[TagHelperMetadata.Runtime.Name] = BlazorMetadata.EventHandler.RuntimeName;
|
||||
|
||||
// WTE has a bug in 15.7p1 where a Tag Helper without a display-name that looks like
|
||||
|
|
|
|||
|
|
@ -21,6 +21,20 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var compilation = context.GetCompilation();
|
||||
if (compilation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var elementRef = compilation.GetTypeByMetadataName(ComponentsApi.ElementRef.FullTypeName);
|
||||
if (elementRef == null)
|
||||
{
|
||||
// If we can't find ElementRef, then just bail. We won't be able to compile the
|
||||
// generated code anyway.
|
||||
return;
|
||||
}
|
||||
|
||||
context.Results.Add(CreateRefTagHelper());
|
||||
}
|
||||
|
||||
|
|
@ -30,6 +44,7 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
builder.Documentation = ComponentResources.RefTagHelper_Documentation;
|
||||
|
||||
builder.Metadata.Add(BlazorMetadata.SpecialKindKey, BlazorMetadata.Ref.TagHelperKind);
|
||||
builder.Metadata.Add(TagHelperMetadata.Common.ClassifyAttributesOnly, bool.TrueString);
|
||||
builder.Metadata[TagHelperMetadata.Runtime.Name] = BlazorMetadata.Ref.RuntimeName;
|
||||
|
||||
// WTE has a bug in 15.7p1 where a Tag Helper without a display-name that looks like
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ namespace Test
|
|||
Assert.Empty(bind.Diagnostics);
|
||||
Assert.False(bind.HasErrors);
|
||||
Assert.Equal(BlazorMetadata.Bind.TagHelperKind, bind.Kind);
|
||||
Assert.Equal(bool.TrueString, bind.Metadata[TagHelperMetadata.Common.ClassifyAttributesOnly]);
|
||||
Assert.Equal(BlazorMetadata.Bind.RuntimeName, bind.Metadata[TagHelperMetadata.Runtime.Name]);
|
||||
Assert.False(bind.IsDefaultKind());
|
||||
Assert.False(bind.KindUsesDefaultTagHelperRuntime());
|
||||
|
|
@ -571,6 +572,7 @@ namespace Test
|
|||
Assert.Empty(bind.Diagnostics);
|
||||
Assert.False(bind.HasErrors);
|
||||
Assert.Equal(BlazorMetadata.Bind.TagHelperKind, bind.Kind);
|
||||
Assert.Equal(bool.TrueString, bind.Metadata[TagHelperMetadata.Common.ClassifyAttributesOnly]);
|
||||
Assert.Equal(BlazorMetadata.Bind.RuntimeName, bind.Metadata[TagHelperMetadata.Runtime.Name]);
|
||||
Assert.False(bind.IsDefaultKind());
|
||||
Assert.False(bind.KindUsesDefaultTagHelperRuntime());
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.AspNetCore.Razor.Language.Components;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Components
|
||||
namespace Microsoft.CodeAnalysis.Razor
|
||||
{
|
||||
public class EventHandlerTagHelperDescriptorProviderTest : BaseTagHelperDescriptorProviderTest
|
||||
{
|
||||
|
|
@ -52,6 +52,7 @@ namespace Test
|
|||
Assert.Empty(item.Diagnostics);
|
||||
Assert.False(item.HasErrors);
|
||||
Assert.Equal(BlazorMetadata.EventHandler.TagHelperKind, item.Kind);
|
||||
Assert.Equal(bool.TrueString, item.Metadata[TagHelperMetadata.Common.ClassifyAttributesOnly]);
|
||||
Assert.Equal(BlazorMetadata.EventHandler.RuntimeName, item.Metadata[TagHelperMetadata.Runtime.Name]);
|
||||
Assert.False(item.IsDefaultKind());
|
||||
Assert.False(item.KindUsesDefaultTagHelperRuntime());
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
{
|
||||
// Arrange
|
||||
var context = TagHelperDescriptorProviderContext.Create();
|
||||
context.SetCompilation(BaseCompilation);
|
||||
|
||||
var provider = new RefTagHelperDescriptorProvider();
|
||||
|
||||
// Act
|
||||
|
|
@ -29,6 +31,7 @@ namespace Microsoft.CodeAnalysis.Razor
|
|||
Assert.Empty(item.Diagnostics);
|
||||
Assert.False(item.HasErrors);
|
||||
Assert.Equal(BlazorMetadata.Ref.TagHelperKind, item.Kind);
|
||||
Assert.Equal(bool.TrueString, item.Metadata[TagHelperMetadata.Common.ClassifyAttributesOnly]);
|
||||
Assert.Equal(BlazorMetadata.Ref.RuntimeName, item.Metadata[TagHelperMetadata.Runtime.Name]);
|
||||
Assert.False(item.IsDefaultKind());
|
||||
Assert.False(item.KindUsesDefaultTagHelperRuntime());
|
||||
|
|
|
|||
Loading…
Reference in New Issue