Skip to content

Commit

Permalink
Directive attributes part 1: Support parameters in bound attributes (d…
Browse files Browse the repository at this point in the history
…otnet/razor#597)

* Directive attributes part 1: Support parameters in bound attributes

* update

* Fix test

* feedback

* Updated design

* Do case sensitive comparison

* more

* Bug fix
\n\nCommit migrated from dotnet/razor@9bbf240

Commit migrated from dotnet/aspnetcore@5bad5de7ee95
  • Loading branch information
ajaybhargavb authored May 21, 2019
1 parent 1bd2225 commit 27bd36e
Show file tree
Hide file tree
Showing 60 changed files with 1,088 additions and 261 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ protected BoundAttributeDescriptor(string kind)

public IReadOnlyDictionary<string, string> Metadata { get; protected set; }

public virtual IReadOnlyList<BoundAttributeParameterDescriptor> BoundAttributeParameters { get; protected set; }

public bool HasErrors
{
get
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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
Expand All @@ -26,5 +27,11 @@ public abstract class BoundAttributeDescriptorBuilder
public abstract IDictionary<string, string> Metadata { get; }

public abstract RazorDiagnosticCollection Diagnostics { get; }

public virtual IReadOnlyList<BoundAttributeParameterDescriptorBuilder> BoundAttributeParameters { get; }

public virtual void BindAttributeParameter(Action<BoundAttributeParameterDescriptorBuilder> configure)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public static string GetPropertyName(this BoundAttributeDescriptorBuilder builde
throw new ArgumentNullException(nameof(builder));
}

if (builder.Metadata.ContainsKey(TagHelperMetadata.Common.PropertyName))
if (builder.Metadata.TryGetValue(TagHelperMetadata.Common.PropertyName, out var value))
{
return builder.Metadata[TagHelperMetadata.Common.PropertyName];
return value;
}

return null;
Expand All @@ -51,5 +51,35 @@ public static void AsDictionary(
builder.IndexerAttributeNamePrefix = attributeNamePrefix;
builder.IndexerValueTypeName = valueTypeName;
}

public static void SetPropertyName(this BoundAttributeParameterDescriptorBuilder builder, string propertyName)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

if (propertyName == null)
{
throw new ArgumentNullException(nameof(propertyName));
}

builder.Metadata[TagHelperMetadata.Common.PropertyName] = propertyName;
}

public static string GetPropertyName(this BoundAttributeParameterDescriptorBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

if (builder.Metadata.TryGetValue(TagHelperMetadata.Common.PropertyName, out var value))
{
return value;
}

return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Linq;

namespace Microsoft.AspNetCore.Razor.Language
{
Expand Down Expand Up @@ -49,5 +50,26 @@ internal static bool ExpectsBooleanValue(this BoundAttributeDescriptor attribute
var isIndexerNameMatch = TagHelperMatchingConventions.SatisfiesBoundAttributeIndexer(name, attribute);
return isIndexerNameMatch && attribute.IsIndexerBooleanProperty;
}

public static bool IsDefaultKind(this BoundAttributeParameterDescriptor parameter)
{
if (parameter == null)
{
throw new ArgumentNullException(nameof(parameter));
}

return string.Equals(parameter.Kind, TagHelperConventions.DefaultKind, StringComparison.Ordinal);
}

public static string GetPropertyName(this BoundAttributeParameterDescriptor parameter)
{
if (parameter == null)
{
throw new ArgumentNullException(nameof(parameter));
}

parameter.Metadata.TryGetValue(TagHelperMetadata.Common.PropertyName, out var propertyName);
return propertyName;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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;
using System.Linq;

namespace Microsoft.AspNetCore.Razor.Language
{
public abstract class BoundAttributeParameterDescriptor : IEquatable<BoundAttributeParameterDescriptor>
{
protected BoundAttributeParameterDescriptor(string kind)
{
Kind = kind;
}

public string Kind { get; }

public bool IsEnum { get; protected set; }

public bool IsStringProperty { get; protected set; }

public bool IsBooleanProperty { get; protected set; }

public string Name { get; protected set; }

public string TypeName { get; protected set; }

public string Documentation { get; protected set; }

public string DisplayName { get; protected set; }

public IReadOnlyList<RazorDiagnostic> Diagnostics { get; protected set; }

public IReadOnlyDictionary<string, string> Metadata { get; protected set; }

public bool HasErrors
{
get
{
var errors = Diagnostics.Any(diagnostic => diagnostic.Severity == RazorDiagnosticSeverity.Error);

return errors;
}
}

public override string ToString()
{
return DisplayName ?? base.ToString();
}

public bool Equals(BoundAttributeParameterDescriptor other)
{
return BoundAttributeParameterDescriptorComparer.Default.Equals(this, other);
}

public override bool Equals(object obj)
{
return Equals(obj as BoundAttributeParameterDescriptor);
}

public override int GetHashCode()
{
return BoundAttributeParameterDescriptorComparer.Default.GetHashCode(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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.Collections.Generic;

namespace Microsoft.AspNetCore.Razor.Language
{
public abstract class BoundAttributeParameterDescriptorBuilder
{
public abstract string Name { get; set; }

public abstract string TypeName { get; set; }

public abstract bool IsEnum { get; set; }

public abstract string Documentation { get; set; }

public abstract string DisplayName { get; set; }

public abstract IDictionary<string, string> Metadata { get; }

public abstract RazorDiagnosticCollection Diagnostics { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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;
using System.Linq;
using Microsoft.Extensions.Internal;

namespace Microsoft.AspNetCore.Razor.Language
{
internal class BoundAttributeParameterDescriptorComparer : IEqualityComparer<BoundAttributeParameterDescriptor>
{
/// <summary>
/// A default instance of the <see cref="BoundAttributeParameterDescriptorComparer"/>.
/// </summary>
public static readonly BoundAttributeParameterDescriptorComparer Default = new BoundAttributeParameterDescriptorComparer();

/// <summary>
/// A default instance of the <see cref="BoundAttributeParameterDescriptorComparer"/> that does case-sensitive comparison.
/// </summary>
internal static readonly BoundAttributeParameterDescriptorComparer CaseSensitive =
new BoundAttributeParameterDescriptorComparer(caseSensitive: true);

private readonly StringComparer _stringComparer;
private readonly StringComparison _stringComparison;

private BoundAttributeParameterDescriptorComparer(bool caseSensitive = false)
{
if (caseSensitive)
{
_stringComparer = StringComparer.Ordinal;
_stringComparison = StringComparison.Ordinal;
}
else
{
_stringComparer = StringComparer.OrdinalIgnoreCase;
_stringComparison = StringComparison.OrdinalIgnoreCase;
}
}

public virtual bool Equals(BoundAttributeParameterDescriptor descriptorX, BoundAttributeParameterDescriptor descriptorY)
{
if (object.ReferenceEquals(descriptorX, descriptorY))
{
return true;
}

if (descriptorX == null ^ descriptorY == null)
{
return false;
}

return
string.Equals(descriptorX.Kind, descriptorY.Kind, StringComparison.Ordinal) &&
descriptorX.IsEnum == descriptorY.IsEnum &&
string.Equals(descriptorX.Name, descriptorY.Name, _stringComparison) &&
string.Equals(descriptorX.TypeName, descriptorY.TypeName, StringComparison.Ordinal) &&
string.Equals(descriptorX.Documentation, descriptorY.Documentation, StringComparison.Ordinal) &&
string.Equals(descriptorX.DisplayName, descriptorY.DisplayName, StringComparison.Ordinal) &&
Enumerable.SequenceEqual(
descriptorX.Metadata.OrderBy(propertyX => propertyX.Key, StringComparer.Ordinal),
descriptorY.Metadata.OrderBy(propertyY => propertyY.Key, StringComparer.Ordinal));
}

public virtual int GetHashCode(BoundAttributeParameterDescriptor descriptor)
{
if (descriptor == null)
{
throw new ArgumentNullException(nameof(descriptor));
}

var hash = HashCodeCombiner.Start();
hash.Add(descriptor.Kind);
hash.Add(descriptor.Name, _stringComparer);

return hash.CombinedHash;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,20 @@
<data name="BindTagHelper_Element_Documentation" xml:space="preserve">
<value>Binds the provided expression to the '{0}' attribute and a change event delegate to the '{1}' attribute.</value>
</data>
<data name="BindTagHelper_Element_Event_Documentation" xml:space="preserve">
<value>Specifies the event handler name to attach for change notifications for the value provided by the '{0}' attribute.</value>
</data>
<data name="BindTagHelper_Element_Format_Documentation" xml:space="preserve">
<value>Specifies a format to convert the value specified by the '{0}' attribute. The format string can currently only be used with expressions of type &lt;code&gt;DateTime&lt;/code&gt;.</value>
</data>
<data name="BindTagHelper_Fallback_Documentation" xml:space="preserve">
<value>Binds the provided expression to an attribute and a change event, based on the naming of the bind attribute. For example: &lt;code&gt;bind-value-onchange="..."&lt;/code&gt; will assign the current value of the expression to the 'value' attribute, and assign a delegate that attempts to set the value to the 'onchange' attribute.</value>
<value>Binds the provided expression to an attribute and a change event, based on the naming of the bind attribute. For example: &lt;code&gt;bind-value="..."&lt;/code&gt; and &lt;code&gt;bind-value:event="onchange"&lt;/code&gt; will assign the current value of the expression to the 'value' attribute, and assign a delegate that attempts to set the value to the 'onchange' attribute.</value>
</data>
<data name="BindTagHelper_Fallback_Event_Documentation" xml:space="preserve">
<value>Specifies the event handler name to attach for change notifications for the value provided by the '{0}' attribute.</value>
</data>
<data name="BindTagHelper_Fallback_Format_Documentation" xml:space="preserve">
<value>Specifies a format to convert the value specified by the corresponding bind attribute. For example: &lt;code&gt;format-value="..."&lt;/code&gt; will apply a format string to the value specified in &lt;code&gt;bind-value-...&lt;/code&gt;. The format string can currently only be used with expressions of type &lt;code&gt;DateTime&lt;/code&gt;.</value>
<value>Specifies a format to convert the value specified by the corresponding bind attribute. For example: &lt;code&gt;bind-value:format="..."&lt;/code&gt; will apply a format string to the value specified in &lt;code&gt;bind-value="..."&lt;/code&gt;. The format string can currently only be used with expressions of type &lt;code&gt;DateTime&lt;/code&gt;.</value>
</data>
<data name="ChildContentParameterName_Documentation" xml:space="preserve">
<value>Specifies the parameter name for the '{0}' child content expression.</value>
Expand Down
Loading

0 comments on commit 27bd36e

Please sign in to comment.