Added RazorParserFeatureFlags and added support for minimized bool tag
helper bound attributes - Fixes #1678, #431
This commit is contained in:
parent
edcf6857d1
commit
bd8e9ecc31
|
|
@ -21,10 +21,14 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
public bool IsIndexerStringProperty { get; protected set; }
|
public bool IsIndexerStringProperty { get; protected set; }
|
||||||
|
|
||||||
|
public bool IsIndexerBooleanProperty { get; protected set; }
|
||||||
|
|
||||||
public bool IsEnum { get; protected set; }
|
public bool IsEnum { get; protected set; }
|
||||||
|
|
||||||
public bool IsStringProperty { get; protected set; }
|
public bool IsStringProperty { get; protected set; }
|
||||||
|
|
||||||
|
public bool IsBooleanProperty { get; protected set; }
|
||||||
|
|
||||||
public string Name { get; protected set; }
|
public string Name { get; protected set; }
|
||||||
|
|
||||||
public string IndexerNamePrefix { get; protected set; }
|
public string IndexerNamePrefix { get; protected set; }
|
||||||
|
|
|
||||||
|
|
@ -27,5 +27,27 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
return string.Equals(attribute.Kind, TagHelperConventions.DefaultKind, StringComparison.Ordinal);
|
return string.Equals(attribute.Kind, TagHelperConventions.DefaultKind, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool ExpectsStringValue(this BoundAttributeDescriptor attribute, string name)
|
||||||
|
{
|
||||||
|
if (attribute.IsStringProperty)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isIndexerNameMatch = TagHelperMatchingConventions.SatisfiesBoundAttributeIndexer(name, attribute);
|
||||||
|
return isIndexerNameMatch && attribute.IsIndexerStringProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool ExpectsBooleanValue(this BoundAttributeDescriptor attribute, string name)
|
||||||
|
{
|
||||||
|
if (attribute.IsBooleanProperty)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isIndexerNameMatch = TagHelperMatchingConventions.SatisfiesBoundAttributeIndexer(name, attribute);
|
||||||
|
return isIndexerNameMatch && attribute.IsIndexerBooleanProperty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +35,9 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
IsIndexerStringProperty = indexerTypeName == typeof(string).FullName || indexerTypeName == "string";
|
IsIndexerStringProperty = indexerTypeName == typeof(string).FullName || indexerTypeName == "string";
|
||||||
IsStringProperty = typeName == typeof(string).FullName || typeName == "string";
|
IsStringProperty = typeName == typeof(string).FullName || typeName == "string";
|
||||||
|
|
||||||
|
IsIndexerBooleanProperty = indexerTypeName == typeof(bool).FullName || indexerTypeName == "bool";
|
||||||
|
IsBooleanProperty = typeName == typeof(bool).FullName || typeName == "bool";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
var imports = codeDocument.GetImportSyntaxTrees();
|
var imports = codeDocument.GetImportSyntaxTrees();
|
||||||
if (imports != null)
|
if (imports != null)
|
||||||
{
|
{
|
||||||
var importsVisitor = new ImportsVisitor(document, builder, namespaces);
|
var importsVisitor = new ImportsVisitor(document, builder, namespaces, syntaxTree.Options.FeatureFlags);
|
||||||
|
|
||||||
for (var j = 0; j < imports.Count; j++)
|
for (var j = 0; j < imports.Count; j++)
|
||||||
{
|
{
|
||||||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagHelperPrefix = tagHelperContext?.Prefix;
|
var tagHelperPrefix = tagHelperContext?.Prefix;
|
||||||
var visitor = new MainSourceVisitor(document, builder, namespaces, tagHelperPrefix)
|
var visitor = new MainSourceVisitor(document, builder, namespaces, tagHelperPrefix, syntaxTree.Options.FeatureFlags)
|
||||||
{
|
{
|
||||||
FilePath = syntaxTree.Source.FilePath,
|
FilePath = syntaxTree.Source.FilePath,
|
||||||
};
|
};
|
||||||
|
|
@ -151,12 +151,14 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
protected readonly IntermediateNodeBuilder _builder;
|
protected readonly IntermediateNodeBuilder _builder;
|
||||||
protected readonly DocumentIntermediateNode _document;
|
protected readonly DocumentIntermediateNode _document;
|
||||||
protected readonly Dictionary<string, SourceSpan?> _namespaces;
|
protected readonly Dictionary<string, SourceSpan?> _namespaces;
|
||||||
|
protected readonly RazorParserFeatureFlags _featureFlags;
|
||||||
|
|
||||||
public LoweringVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces)
|
public LoweringVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, RazorParserFeatureFlags featureFlags)
|
||||||
{
|
{
|
||||||
_document = document;
|
_document = document;
|
||||||
_builder = builder;
|
_builder = builder;
|
||||||
_namespaces = namespaces;
|
_namespaces = namespaces;
|
||||||
|
_featureFlags = featureFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FilePath { get; set; }
|
public string FilePath { get; set; }
|
||||||
|
|
@ -331,8 +333,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
protected SourceSpan? BuildSourceSpanFromNode(SyntaxTreeNode node)
|
protected SourceSpan? BuildSourceSpanFromNode(SyntaxTreeNode node)
|
||||||
{
|
{
|
||||||
var location = node.Start;
|
if (node == null || node.Start == SourceLocation.Undefined)
|
||||||
if (location == SourceLocation.Undefined)
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -351,8 +352,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
private readonly string _tagHelperPrefix;
|
private readonly string _tagHelperPrefix;
|
||||||
|
|
||||||
public MainSourceVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, string tagHelperPrefix)
|
public MainSourceVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, string tagHelperPrefix, RazorParserFeatureFlags featureFlags)
|
||||||
: base(document, builder, namespaces)
|
: base(document, builder, namespaces, featureFlags)
|
||||||
{
|
{
|
||||||
_tagHelperPrefix = tagHelperPrefix;
|
_tagHelperPrefix = tagHelperPrefix;
|
||||||
}
|
}
|
||||||
|
|
@ -670,10 +671,11 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
if (associatedDescriptors.Any() && renderedBoundAttributeNames.Add(attribute.Name))
|
if (associatedDescriptors.Any() && renderedBoundAttributeNames.Add(attribute.Name))
|
||||||
{
|
{
|
||||||
if (attributeValueNode == null)
|
var isMinimizedAttribute = attributeValueNode == null;
|
||||||
|
if (isMinimizedAttribute && !_featureFlags.AllowMinimizedBooleanTagHelperAttributes)
|
||||||
{
|
{
|
||||||
// Minimized attributes are not valid for bound attributes. TagHelperBlockRewriter has already
|
// Minimized attributes are not valid for non-boolean bound attributes. TagHelperBlockRewriter
|
||||||
// logged an error if it was a bound attribute; so we can skip.
|
// has already logged an error if it was a non-boolean bound attribute; so we can skip.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -684,6 +686,14 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
return TagHelperMatchingConventions.CanSatisfyBoundAttribute(attribute.Name, a);
|
return TagHelperMatchingConventions.CanSatisfyBoundAttribute(attribute.Name, a);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var expectsBooleanValue = associatedAttributeDescriptor.ExpectsBooleanValue(attribute.Name);
|
||||||
|
|
||||||
|
if (isMinimizedAttribute && !expectsBooleanValue)
|
||||||
|
{
|
||||||
|
// We do not allow minimized non-boolean bound attributes.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var setTagHelperProperty = new TagHelperPropertyIntermediateNode()
|
var setTagHelperProperty = new TagHelperPropertyIntermediateNode()
|
||||||
{
|
{
|
||||||
AttributeName = attribute.Name,
|
AttributeName = attribute.Name,
|
||||||
|
|
@ -695,7 +705,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
};
|
};
|
||||||
|
|
||||||
_builder.Push(setTagHelperProperty);
|
_builder.Push(setTagHelperProperty);
|
||||||
attributeValueNode.Accept(this);
|
attributeValueNode?.Accept(this);
|
||||||
_builder.Pop();
|
_builder.Pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -720,8 +730,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
private class ImportsVisitor : LoweringVisitor
|
private class ImportsVisitor : LoweringVisitor
|
||||||
{
|
{
|
||||||
public ImportsVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces)
|
public ImportsVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, Dictionary<string, SourceSpan?> namespaces, RazorParserFeatureFlags featureFlags)
|
||||||
: base(document, new ImportBuilder(builder), namespaces)
|
: base(document, new ImportBuilder(builder), namespaces, featureFlags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
internal class DefaultRazorParserOptions : RazorParserOptions
|
internal class DefaultRazorParserOptions : RazorParserOptions
|
||||||
{
|
{
|
||||||
public DefaultRazorParserOptions(DirectiveDescriptor[] directives, bool designTime, bool parseLeadingDirectives)
|
public DefaultRazorParserOptions(DirectiveDescriptor[] directives, bool designTime, bool parseLeadingDirectives, RazorLanguageVersion version)
|
||||||
{
|
{
|
||||||
if (directives == null)
|
if (directives == null)
|
||||||
{
|
{
|
||||||
|
|
@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
Directives = directives;
|
Directives = directives;
|
||||||
DesignTime = designTime;
|
DesignTime = designTime;
|
||||||
ParseLeadingDirectives = parseLeadingDirectives;
|
ParseLeadingDirectives = parseLeadingDirectives;
|
||||||
|
Version = version;
|
||||||
|
FeatureFlags = RazorParserFeatureFlags.Create(Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool DesignTime { get; }
|
public override bool DesignTime { get; }
|
||||||
|
|
@ -25,5 +27,9 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
public override IReadOnlyCollection<DirectiveDescriptor> Directives { get; }
|
public override IReadOnlyCollection<DirectiveDescriptor> Directives { get; }
|
||||||
|
|
||||||
public override bool ParseLeadingDirectives { get; }
|
public override bool ParseLeadingDirectives { get; }
|
||||||
|
|
||||||
|
public override RazorLanguageVersion Version { get; }
|
||||||
|
|
||||||
|
internal override RazorParserFeatureFlags FeatureFlags { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
|
@ -8,9 +9,10 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
internal class DefaultRazorParserOptionsBuilder : RazorParserOptionsBuilder
|
internal class DefaultRazorParserOptionsBuilder : RazorParserOptionsBuilder
|
||||||
{
|
{
|
||||||
public DefaultRazorParserOptionsBuilder(bool designTime)
|
public DefaultRazorParserOptionsBuilder(bool designTime, RazorLanguageVersion version)
|
||||||
{
|
{
|
||||||
DesignTime = designTime;
|
DesignTime = designTime;
|
||||||
|
Version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool DesignTime { get; }
|
public override bool DesignTime { get; }
|
||||||
|
|
@ -19,9 +21,11 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
public override bool ParseLeadingDirectives { get; set; }
|
public override bool ParseLeadingDirectives { get; set; }
|
||||||
|
|
||||||
|
public override RazorLanguageVersion Version { get; }
|
||||||
|
|
||||||
public override RazorParserOptions Build()
|
public override RazorParserOptions Build()
|
||||||
{
|
{
|
||||||
return new DefaultRazorParserOptions(Directives.ToArray(), DesignTime, ParseLeadingDirectives);
|
return new DefaultRazorParserOptions(Directives.ToArray(), DesignTime, ParseLeadingDirectives, Version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
internal class DefaultRazorParserOptionsFeature : RazorEngineFeatureBase, IRazorParserOptionsFeature
|
internal class DefaultRazorParserOptionsFeature : RazorEngineFeatureBase, IRazorParserOptionsFeature
|
||||||
{
|
{
|
||||||
private readonly bool _designTime;
|
private readonly bool _designTime;
|
||||||
|
private readonly RazorLanguageVersion _version;
|
||||||
private IConfigureRazorParserOptionsFeature[] _configureOptions;
|
private IConfigureRazorParserOptionsFeature[] _configureOptions;
|
||||||
|
|
||||||
public DefaultRazorParserOptionsFeature(bool designTime)
|
public DefaultRazorParserOptionsFeature(bool designTime, RazorLanguageVersion version)
|
||||||
{
|
{
|
||||||
_designTime = designTime;
|
_designTime = designTime;
|
||||||
|
_version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
|
|
@ -22,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
public RazorParserOptions GetOptions()
|
public RazorParserOptions GetOptions()
|
||||||
{
|
{
|
||||||
var builder = new DefaultRazorParserOptionsBuilder(_designTime);
|
var builder = new DefaultRazorParserOptionsBuilder(_designTime, _version);
|
||||||
for (var i = 0; i < _configureOptions.Length; i++)
|
for (var i = 0; i < _configureOptions.Length; i++)
|
||||||
{
|
{
|
||||||
_configureOptions[i].Configure(builder);
|
_configureOptions[i].Configure(builder);
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorSink = new ErrorSink();
|
var errorSink = new ErrorSink();
|
||||||
var rewriter = new TagHelperParseTreeRewriter(tagHelperPrefix, descriptors);
|
var rewriter = new TagHelperParseTreeRewriter(tagHelperPrefix, descriptors, syntaxTree.Options.FeatureFlags);
|
||||||
|
|
||||||
var root = syntaxTree.Root;
|
var root = syntaxTree.Root;
|
||||||
root = rewriter.Rewrite(root, errorSink);
|
root = rewriter.Rewrite(root, errorSink);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get there, this is the first time seeing this property so we need to evaluate the expression.
|
// If we get there, this is the first time seeing this property so we need to evaluate the expression.
|
||||||
if (node.BoundAttribute.IsStringProperty || (node.IsIndexerNameMatch && node.BoundAttribute.IsIndexerStringProperty))
|
if (node.BoundAttribute.ExpectsStringValue(node.AttributeName))
|
||||||
{
|
{
|
||||||
if (DesignTime)
|
if (DesignTime)
|
||||||
{
|
{
|
||||||
|
|
@ -407,7 +407,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
context.CodeWriter.WriteStartAssignment(GetPropertyAccessor(node));
|
context.CodeWriter.WriteStartAssignment(GetPropertyAccessor(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderTagHelperAttributeInline(context, node, node.Source);
|
if (node.Children.Count == 0 &&
|
||||||
|
node.AttributeStructure == AttributeStructure.Minimized &&
|
||||||
|
node.BoundAttribute.ExpectsBooleanValue(node.AttributeName))
|
||||||
|
{
|
||||||
|
// If this is a minimized boolean attribute, set the value to true.
|
||||||
|
context.CodeWriter.Write("true");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RenderTagHelperAttributeInline(context, node, node.Source);
|
||||||
|
}
|
||||||
|
|
||||||
context.CodeWriter.WriteLine(";");
|
context.CodeWriter.WriteLine(";");
|
||||||
}
|
}
|
||||||
|
|
@ -429,7 +439,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
.Write(".");
|
.Write(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderTagHelperAttributeInline(context, node, node.Source);
|
if (node.Children.Count == 0 &&
|
||||||
|
node.AttributeStructure == AttributeStructure.Minimized &&
|
||||||
|
node.BoundAttribute.ExpectsBooleanValue(node.AttributeName))
|
||||||
|
{
|
||||||
|
// If this is a minimized boolean attribute, set the value to true.
|
||||||
|
context.CodeWriter.Write("true");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RenderTagHelperAttributeInline(context, node, node.Source);
|
||||||
|
}
|
||||||
|
|
||||||
context.CodeWriter.WriteLine(";");
|
context.CodeWriter.WriteLine(";");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
public static TagHelperBlockBuilder Rewrite(
|
public static TagHelperBlockBuilder Rewrite(
|
||||||
string tagName,
|
string tagName,
|
||||||
bool validStructure,
|
bool validStructure,
|
||||||
|
RazorParserFeatureFlags featureFlags,
|
||||||
Block tag,
|
Block tag,
|
||||||
TagHelperBinding bindingResult,
|
TagHelperBinding bindingResult,
|
||||||
ErrorSink errorSink)
|
ErrorSink errorSink)
|
||||||
{
|
{
|
||||||
// There will always be at least one child for the '<'.
|
// There will always be at least one child for the '<'.
|
||||||
var start = tag.Children.First().Start;
|
var start = tag.Children.First().Start;
|
||||||
var attributes = GetTagAttributes(tagName, validStructure, tag, bindingResult, errorSink);
|
var attributes = GetTagAttributes(tagName, validStructure, tag, bindingResult, errorSink, featureFlags);
|
||||||
var tagMode = GetTagMode(tagName, tag, bindingResult, errorSink);
|
var tagMode = GetTagMode(tagName, tag, bindingResult, errorSink);
|
||||||
|
|
||||||
return new TagHelperBlockBuilder(tagName, tagMode, start, attributes, bindingResult);
|
return new TagHelperBlockBuilder(tagName, tagMode, start, attributes, bindingResult);
|
||||||
|
|
@ -33,7 +34,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
bool validStructure,
|
bool validStructure,
|
||||||
Block tagBlock,
|
Block tagBlock,
|
||||||
TagHelperBinding bindingResult,
|
TagHelperBinding bindingResult,
|
||||||
ErrorSink errorSink)
|
ErrorSink errorSink,
|
||||||
|
RazorParserFeatureFlags featureFlags)
|
||||||
{
|
{
|
||||||
var attributes = new List<TagHelperAttributeNode>();
|
var attributes = new List<TagHelperAttributeNode>();
|
||||||
|
|
||||||
|
|
@ -61,10 +63,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
SourceLocation? errorLocation = null;
|
SourceLocation? errorLocation = null;
|
||||||
|
|
||||||
// Check if it's a bound attribute that is minimized or if it's a bound non-string attribute that
|
// Check if it's a non-boolean bound attribute that is minimized or if it's a bound
|
||||||
// is null or whitespace.
|
// non-string attribute that has null or whitespace content.
|
||||||
if ((result.IsBoundAttribute && result.AttributeValueNode == null) ||
|
var isMinimized = result.AttributeValueNode == null;
|
||||||
(result.IsBoundNonStringAttribute &&
|
var isValidMinimizedAttribute = featureFlags.AllowMinimizedBooleanTagHelperAttributes && result.IsBoundBooleanAttribute;
|
||||||
|
if ((isMinimized &&
|
||||||
|
result.IsBoundAttribute &&
|
||||||
|
!isValidMinimizedAttribute) ||
|
||||||
|
(!isMinimized &&
|
||||||
|
result.IsBoundNonStringAttribute &&
|
||||||
IsNullOrWhitespaceAttributeValue(result.AttributeValueNode)))
|
IsNullOrWhitespaceAttributeValue(result.AttributeValueNode)))
|
||||||
{
|
{
|
||||||
errorLocation = GetAttributeNameStartLocation(child);
|
errorLocation = GetAttributeNameStartLocation(child);
|
||||||
|
|
@ -690,9 +697,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
var firstBoundAttribute = FindFirstBoundAttribute(name, descriptors);
|
var firstBoundAttribute = FindFirstBoundAttribute(name, descriptors);
|
||||||
var isBoundAttribute = firstBoundAttribute != null;
|
var isBoundAttribute = firstBoundAttribute != null;
|
||||||
var isBoundNonStringAttribute = isBoundAttribute &&
|
var isBoundNonStringAttribute = isBoundAttribute && !firstBoundAttribute.ExpectsStringValue(name);
|
||||||
!(firstBoundAttribute.IsStringProperty ||
|
var isBoundBooleanAttribute = isBoundAttribute && firstBoundAttribute.ExpectsBooleanValue(name);
|
||||||
(TagHelperMatchingConventions.SatisfiesBoundAttributeIndexer(name, firstBoundAttribute) && firstBoundAttribute.IsIndexerStringProperty));
|
|
||||||
var isMissingDictionaryKey = isBoundAttribute &&
|
var isMissingDictionaryKey = isBoundAttribute &&
|
||||||
firstBoundAttribute.IndexerNamePrefix != null &&
|
firstBoundAttribute.IndexerNamePrefix != null &&
|
||||||
name.Length == firstBoundAttribute.IndexerNamePrefix.Length;
|
name.Length == firstBoundAttribute.IndexerNamePrefix.Length;
|
||||||
|
|
@ -709,6 +715,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
AttributeName = name,
|
AttributeName = name,
|
||||||
IsBoundAttribute = isBoundAttribute,
|
IsBoundAttribute = isBoundAttribute,
|
||||||
IsBoundNonStringAttribute = isBoundNonStringAttribute,
|
IsBoundNonStringAttribute = isBoundNonStringAttribute,
|
||||||
|
IsBoundBooleanAttribute = isBoundBooleanAttribute,
|
||||||
IsMissingDictionaryKey = isMissingDictionaryKey,
|
IsMissingDictionaryKey = isMissingDictionaryKey,
|
||||||
IsDuplicateAttribute = isDuplicateAttribute
|
IsDuplicateAttribute = isDuplicateAttribute
|
||||||
};
|
};
|
||||||
|
|
@ -766,6 +773,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
public bool IsBoundNonStringAttribute { get; set; }
|
public bool IsBoundNonStringAttribute { get; set; }
|
||||||
|
|
||||||
|
public bool IsBoundBooleanAttribute { get; set; }
|
||||||
|
|
||||||
public bool IsMissingDictionaryKey { get; set; }
|
public bool IsMissingDictionaryKey { get; set; }
|
||||||
|
|
||||||
public bool IsDuplicateAttribute { get; set; }
|
public bool IsDuplicateAttribute { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
private readonly Stack<BlockBuilder> _blockStack;
|
private readonly Stack<BlockBuilder> _blockStack;
|
||||||
private TagHelperBlockTracker _currentTagHelperTracker;
|
private TagHelperBlockTracker _currentTagHelperTracker;
|
||||||
private BlockBuilder _currentBlock;
|
private BlockBuilder _currentBlock;
|
||||||
|
private RazorParserFeatureFlags _featureFlags;
|
||||||
|
|
||||||
public TagHelperParseTreeRewriter(string tagHelperPrefix, IEnumerable<TagHelperDescriptor> descriptors)
|
public TagHelperParseTreeRewriter(
|
||||||
|
string tagHelperPrefix,
|
||||||
|
IEnumerable<TagHelperDescriptor> descriptors,
|
||||||
|
RazorParserFeatureFlags featureFlags)
|
||||||
{
|
{
|
||||||
_tagHelperPrefix = tagHelperPrefix;
|
_tagHelperPrefix = tagHelperPrefix;
|
||||||
_tagHelperBinder = new TagHelperBinder(tagHelperPrefix, descriptors);
|
_tagHelperBinder = new TagHelperBinder(tagHelperPrefix, descriptors);
|
||||||
|
|
@ -53,6 +57,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
_blockStack = new Stack<BlockBuilder>();
|
_blockStack = new Stack<BlockBuilder>();
|
||||||
_attributeValueBuilder = new StringBuilder();
|
_attributeValueBuilder = new StringBuilder();
|
||||||
_htmlAttributeTracker = new List<KeyValuePair<string, string>>();
|
_htmlAttributeTracker = new List<KeyValuePair<string, string>>();
|
||||||
|
_featureFlags = featureFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TagBlockTracker CurrentTracker => _trackerStack.Count > 0 ? _trackerStack.Peek() : null;
|
private TagBlockTracker CurrentTracker => _trackerStack.Count > 0 ? _trackerStack.Peek() : null;
|
||||||
|
|
@ -225,6 +230,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var builder = TagHelperBlockRewriter.Rewrite(
|
var builder = TagHelperBlockRewriter.Rewrite(
|
||||||
tagName,
|
tagName,
|
||||||
validTagStructure,
|
validTagStructure,
|
||||||
|
_featureFlags,
|
||||||
tagBlock,
|
tagBlock,
|
||||||
tagHelperBinding,
|
tagHelperBinding,
|
||||||
errorSink);
|
errorSink);
|
||||||
|
|
|
||||||
|
|
@ -682,6 +682,20 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
internal static string FormatTagHelperPrefixDirective_Description()
|
internal static string FormatTagHelperPrefixDirective_Description()
|
||||||
=> GetString("TagHelperPrefixDirective_Description");
|
=> GetString("TagHelperPrefixDirective_Description");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provided value for razor language version is unsupported or invalid: '{0}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string InvalidRazorLanguageVersion
|
||||||
|
{
|
||||||
|
get => GetString("InvalidRazorLanguageVersion");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provided value for razor language version is unsupported or invalid: '{0}'.
|
||||||
|
/// </summary>
|
||||||
|
internal static string FormatInvalidRazorLanguageVersion(object p0)
|
||||||
|
=> string.Format(CultureInfo.CurrentCulture, GetString("InvalidRazorLanguageVersion"), p0);
|
||||||
|
|
||||||
private static string GetString(string name, params string[] formatterNames)
|
private static string GetString(string name, params string[] formatterNames)
|
||||||
{
|
{
|
||||||
var value = _resourceManager.GetString(name);
|
var value = _resourceManager.GetString(name);
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
internal static void AddRuntimeDefaults(IRazorEngineBuilder builder)
|
internal static void AddRuntimeDefaults(IRazorEngineBuilder builder)
|
||||||
{
|
{
|
||||||
// Configure options
|
// Configure options
|
||||||
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false));
|
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false, version: RazorParserOptions.LatestRazorLanguageVersion));
|
||||||
builder.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: false));
|
builder.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: false));
|
||||||
|
|
||||||
// Intermediate Node Passes
|
// Intermediate Node Passes
|
||||||
|
|
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
internal static void AddDesignTimeDefaults(IRazorEngineBuilder builder)
|
internal static void AddDesignTimeDefaults(IRazorEngineBuilder builder)
|
||||||
{
|
{
|
||||||
// Configure options
|
// Configure options
|
||||||
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: true));
|
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: true, version: RazorParserOptions.LatestRazorLanguageVersion));
|
||||||
builder.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: true));
|
builder.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: true));
|
||||||
builder.Features.Add(new SuppressChecksumOptionsFeature());
|
builder.Features.Add(new SuppressChecksumOptionsFeature());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
{
|
||||||
|
public enum RazorLanguageVersion
|
||||||
|
{
|
||||||
|
Version1_0 = 1,
|
||||||
|
|
||||||
|
Version1_1 = 2,
|
||||||
|
|
||||||
|
Version2_0 = 3,
|
||||||
|
|
||||||
|
Version2_1 = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class RazorLanguageVersionExtensions
|
||||||
|
{
|
||||||
|
internal static bool IsValid(this RazorLanguageVersion version)
|
||||||
|
{
|
||||||
|
switch (version)
|
||||||
|
{
|
||||||
|
case RazorLanguageVersion.Version1_0:
|
||||||
|
case RazorLanguageVersion.Version1_1:
|
||||||
|
case RazorLanguageVersion.Version2_0:
|
||||||
|
case RazorLanguageVersion.Version2_1:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
{
|
||||||
|
internal abstract class RazorParserFeatureFlags
|
||||||
|
{
|
||||||
|
public static RazorParserFeatureFlags Create(RazorLanguageVersion version)
|
||||||
|
{
|
||||||
|
if (!version.IsValid())
|
||||||
|
{
|
||||||
|
throw new ArgumentException(Resources.FormatInvalidRazorLanguageVersion(version.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
var allowMinimizedBooleanTagHelperAttributes = false;
|
||||||
|
|
||||||
|
if (version == RazorLanguageVersion.Version2_1)
|
||||||
|
{
|
||||||
|
allowMinimizedBooleanTagHelperAttributes = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DefaultRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||||
|
|
||||||
|
private class DefaultRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||||
|
{
|
||||||
|
public DefaultRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes)
|
||||||
|
{
|
||||||
|
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,9 +8,15 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
public abstract class RazorParserOptions
|
public abstract class RazorParserOptions
|
||||||
{
|
{
|
||||||
|
internal static readonly RazorLanguageVersion LatestRazorLanguageVersion = RazorLanguageVersion.Version2_1;
|
||||||
|
|
||||||
public static RazorParserOptions CreateDefault()
|
public static RazorParserOptions CreateDefault()
|
||||||
{
|
{
|
||||||
return new DefaultRazorParserOptions(Array.Empty<DirectiveDescriptor>(), designTime: false, parseLeadingDirectives: false);
|
return new DefaultRazorParserOptions(
|
||||||
|
Array.Empty<DirectiveDescriptor>(),
|
||||||
|
designTime: false,
|
||||||
|
parseLeadingDirectives: false,
|
||||||
|
version: LatestRazorLanguageVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RazorParserOptions Create(Action<RazorParserOptionsBuilder> configure)
|
public static RazorParserOptions Create(Action<RazorParserOptionsBuilder> configure)
|
||||||
|
|
@ -20,7 +26,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
throw new ArgumentNullException(nameof(configure));
|
throw new ArgumentNullException(nameof(configure));
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder = new DefaultRazorParserOptionsBuilder(designTime: false);
|
var builder = new DefaultRazorParserOptionsBuilder(designTime: false, version: LatestRazorLanguageVersion);
|
||||||
configure(builder);
|
configure(builder);
|
||||||
var options = builder.Build();
|
var options = builder.Build();
|
||||||
|
|
||||||
|
|
@ -34,7 +40,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
throw new ArgumentNullException(nameof(configure));
|
throw new ArgumentNullException(nameof(configure));
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder = new DefaultRazorParserOptionsBuilder(designTime: true);
|
var builder = new DefaultRazorParserOptionsBuilder(designTime: true, version: LatestRazorLanguageVersion);
|
||||||
configure(builder);
|
configure(builder);
|
||||||
var options = builder.Build();
|
var options = builder.Build();
|
||||||
|
|
||||||
|
|
@ -54,5 +60,9 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
/// In a future release this may be updated to include all leading directive content.
|
/// In a future release this may be updated to include all leading directive content.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public abstract bool ParseLeadingDirectives { get; }
|
public abstract bool ParseLeadingDirectives { get; }
|
||||||
|
|
||||||
|
public virtual RazorLanguageVersion Version { get; } = LatestRazorLanguageVersion;
|
||||||
|
|
||||||
|
internal virtual RazorParserFeatureFlags FeatureFlags { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
@ -13,6 +14,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
public abstract bool ParseLeadingDirectives { get; set; }
|
public abstract bool ParseLeadingDirectives { get; set; }
|
||||||
|
|
||||||
|
public virtual RazorLanguageVersion Version { get; }
|
||||||
|
|
||||||
public abstract RazorParserOptions Build();
|
public abstract RazorParserOptions Build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -261,4 +261,7 @@
|
||||||
<data name="TagHelperPrefixDirective_Description" xml:space="preserve">
|
<data name="TagHelperPrefixDirective_Description" xml:space="preserve">
|
||||||
<value>Specify a prefix that is required in an element name for it to be included in Tag Helper processing.</value>
|
<value>Specify a prefix that is required in an element name for it to be included in Tag Helper processing.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="InvalidRazorLanguageVersion" xml:space="preserve">
|
||||||
|
<value>Provided value for razor language version is unsupported or invalid: '{0}'.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -95,5 +95,185 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(isDefault);
|
Assert.False(isDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsStringValue_ReturnsTrue_ForStringProperty()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName(typeof(string).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsStringValue("test");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsStringValue_ReturnsFalse_ForNonStringProperty()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName(typeof(bool).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsStringValue("test");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsStringValue_ReturnsTrue_StringIndexerAndNameMatch()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName("System.Collection.Generic.IDictionary<string, string>")
|
||||||
|
.AsDictionary("prefix-test-", typeof(string).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsStringValue("prefix-test-key");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsStringValue_ReturnsFalse_StringIndexerAndNameMismatch()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName("System.Collection.Generic.IDictionary<string, string>")
|
||||||
|
.AsDictionary("prefix-test-", typeof(string).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsStringValue("test");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsBooleanValue_ReturnsTrue_ForBooleanProperty()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName(typeof(bool).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsBooleanValue("test");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsBooleanValue_ReturnsFalse_ForNonBooleanProperty()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName(typeof(int).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsBooleanValue("test");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsBooleanValue_ReturnsTrue_BooleanIndexerAndNameMatch()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName("System.Collection.Generic.IDictionary<string, bool>")
|
||||||
|
.AsDictionary("prefix-test-", typeof(bool).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsBooleanValue("prefix-test-key");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpectsBooleanValue_ReturnsFalse_BooleanIndexerAndNameMismatch()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "TestTagHelper", "Test");
|
||||||
|
tagHelperBuilder.TypeName("TestTagHelper");
|
||||||
|
|
||||||
|
var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);
|
||||||
|
builder
|
||||||
|
.Name("test")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName("System.Collection.Generic.IDictionary<string, bool>")
|
||||||
|
.AsDictionary("prefix-test-", typeof(bool).FullName);
|
||||||
|
|
||||||
|
var descriptor = builder.Build();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = descriptor.ExpectsBooleanValue("test");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
var engine = RazorEngine.CreateEmpty(builder =>
|
var engine = RazorEngine.CreateEmpty(builder =>
|
||||||
{
|
{
|
||||||
builder.Phases.Add(phase);
|
builder.Phases.Add(phase);
|
||||||
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false));
|
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false, version: RazorParserOptions.LatestRazorLanguageVersion));
|
||||||
});
|
});
|
||||||
|
|
||||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
var engine = RazorEngine.CreateEmpty((builder) =>
|
var engine = RazorEngine.CreateEmpty((builder) =>
|
||||||
{
|
{
|
||||||
builder.Phases.Add(phase);
|
builder.Phases.Add(phase);
|
||||||
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false));
|
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false, version: RazorParserOptions.LatestRazorLanguageVersion));
|
||||||
builder.Features.Add(new MyParserOptionsFeature());
|
builder.Features.Add(new MyParserOptionsFeature());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -58,9 +58,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
var engine = RazorEngine.CreateEmpty((builder) =>
|
var engine = RazorEngine.CreateEmpty((builder) =>
|
||||||
{
|
{
|
||||||
builder.Phases.Add(phase);
|
builder.Phases.Add(phase);
|
||||||
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false));
|
builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false, version: RazorParserOptions.LatestRazorLanguageVersion));
|
||||||
builder.Features.Add(new MyParserOptionsFeature());
|
builder.Features.Add(new MyParserOptionsFeature());
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var imports = new[]
|
var imports = new[]
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,43 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TagHelperDescriptor> MinimizedBooleanTagHelperDescriptors
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
CreateTagHelperDescriptor(
|
||||||
|
tagName: "span",
|
||||||
|
typeName: "SpanTagHelper",
|
||||||
|
assemblyName: "TestAssembly"),
|
||||||
|
CreateTagHelperDescriptor(
|
||||||
|
tagName: "div",
|
||||||
|
typeName: "DivTagHelper",
|
||||||
|
assemblyName: "TestAssembly"),
|
||||||
|
CreateTagHelperDescriptor(
|
||||||
|
tagName: "input",
|
||||||
|
typeName: "InputTagHelper",
|
||||||
|
assemblyName: "TestAssembly",
|
||||||
|
attributes: new Action<BoundAttributeDescriptorBuilder>[]
|
||||||
|
{
|
||||||
|
builder => builder
|
||||||
|
.Name("value")
|
||||||
|
.PropertyName("FooProp")
|
||||||
|
.TypeName("System.String"),
|
||||||
|
builder => builder
|
||||||
|
.Name("bound")
|
||||||
|
.PropertyName("BoundProp")
|
||||||
|
.TypeName("System.Boolean"),
|
||||||
|
builder => builder
|
||||||
|
.Name("age")
|
||||||
|
.PropertyName("AgeProp")
|
||||||
|
.TypeName("System.Int32"),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<TagHelperDescriptor> CssSelectorTagHelperDescriptors
|
public static IEnumerable<TagHelperDescriptor> CssSelectorTagHelperDescriptors
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -267,6 +304,22 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
||||||
.RequireAttributeDescriptor(attribute => attribute.Name("input-bound-required-string"))
|
.RequireAttributeDescriptor(attribute => attribute.Name("input-bound-required-string"))
|
||||||
.RequireAttributeDescriptor(attribute => attribute.Name("input-unbound-required")),
|
.RequireAttributeDescriptor(attribute => attribute.Name("input-unbound-required")),
|
||||||
}),
|
}),
|
||||||
|
CreateTagHelperDescriptor(
|
||||||
|
tagName: "div",
|
||||||
|
typeName: "DivTagHelper",
|
||||||
|
assemblyName: "TestAssembly",
|
||||||
|
attributes: new Action<BoundAttributeDescriptorBuilder>[]
|
||||||
|
{
|
||||||
|
builder => builder
|
||||||
|
.Name("boundbool")
|
||||||
|
.PropertyName("BoundBoolProp")
|
||||||
|
.TypeName(typeof(bool).FullName),
|
||||||
|
builder => builder
|
||||||
|
.Name("booldict")
|
||||||
|
.PropertyName("BoolDictProp")
|
||||||
|
.TypeName("System.Collections.Generic.IDictionary<string, bool>")
|
||||||
|
.AsDictionaryAttribute("booldict-prefix-", typeof(bool).FullName),
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,11 +118,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new[]
|
var descriptors = new[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("CatchAllTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("CatchAllTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("*")
|
.RequireTagName("*")
|
||||||
.RequireAttributeDescriptor(attribute => attribute.Name("bound")))
|
.RequireAttributeDescriptor(attribute => attribute.Name("bound")))
|
||||||
.BoundAttributeDescriptor(attribute =>
|
.BoundAttributeDescriptor(attribute =>
|
||||||
attribute
|
attribute
|
||||||
.Name("[item]")
|
.Name("[item]")
|
||||||
.PropertyName("ListItems")
|
.PropertyName("ListItems")
|
||||||
|
|
@ -222,7 +222,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("input")
|
.RequireTagName("input")
|
||||||
.RequireTagStructure(TagStructure.WithoutEndTag))
|
.RequireTagStructure(TagStructure.WithoutEndTag))
|
||||||
|
|
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("InputTagHelper1", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("InputTagHelper1", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("input")
|
.RequireTagName("input")
|
||||||
.RequireTagStructure(structure1))
|
.RequireTagStructure(structure1))
|
||||||
|
|
@ -2251,7 +2251,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("mythTagHelper", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("mythTagHelper", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("myth"))
|
.TagMatchingRuleDescriptor(rule => rule.RequireTagName("myth"))
|
||||||
.BoundAttributeDescriptor(attribute =>
|
.BoundAttributeDescriptor(attribute =>
|
||||||
attribute
|
attribute
|
||||||
.Name("bound")
|
.Name("bound")
|
||||||
.PropertyName("Bound")
|
.PropertyName("Bound")
|
||||||
|
|
@ -3901,7 +3901,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var descriptors = new TagHelperDescriptor[]
|
var descriptors = new TagHelperDescriptor[]
|
||||||
{
|
{
|
||||||
TagHelperDescriptorBuilder.Create("InputTagHelper1", "SomeAssembly")
|
TagHelperDescriptorBuilder.Create("InputTagHelper1", "SomeAssembly")
|
||||||
.TagMatchingRuleDescriptor(rule =>
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
rule
|
rule
|
||||||
.RequireTagName("input")
|
.RequireTagName("input")
|
||||||
.RequireAttributeDescriptor(attribute => attribute.Name("unbound-required")))
|
.RequireAttributeDescriptor(attribute => attribute.Name("unbound-required")))
|
||||||
|
|
@ -3959,5 +3959,107 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
EvaluateData(descriptors, documentContent, (MarkupBlock)expectedOutput, (RazorError[])expectedErrors);
|
EvaluateData(descriptors, documentContent, (MarkupBlock)expectedOutput, (RazorError[])expectedErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Rewrite_UnderstandsMinimizedBooleanBoundAttributes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var documentContent = "<input boundbool boundbooldict-key />";
|
||||||
|
var descriptors = new TagHelperDescriptor[]
|
||||||
|
{
|
||||||
|
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
||||||
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
|
rule
|
||||||
|
.RequireTagName("input"))
|
||||||
|
.BoundAttributeDescriptor(attribute =>
|
||||||
|
attribute
|
||||||
|
.Name("boundbool")
|
||||||
|
.PropertyName("BoundBoolProp")
|
||||||
|
.TypeName(typeof(bool).FullName))
|
||||||
|
.BoundAttributeDescriptor(attribute =>
|
||||||
|
attribute
|
||||||
|
.Name("boundbooldict")
|
||||||
|
.PropertyName("BoundBoolDictProp")
|
||||||
|
.TypeName("System.Collections.Generic.IDictionary<string, bool>")
|
||||||
|
.AsDictionary("boundbooldict-", typeof(bool).FullName))
|
||||||
|
.Build(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var expectedOutput = new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
TagMode.SelfClosing,
|
||||||
|
attributes: new List<TagHelperAttributeNode>()
|
||||||
|
{
|
||||||
|
new TagHelperAttributeNode("boundbool", null, AttributeStructure.Minimized),
|
||||||
|
new TagHelperAttributeNode("boundbooldict-key", null, AttributeStructure.Minimized),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
EvaluateData(descriptors, documentContent, expectedOutput, new RazorError[] { });
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Rewrite_FeatureDisabled_AddsErrorForMinimizedBooleanBoundAttributes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var documentContent = "<input boundbool boundbooldict-key />";
|
||||||
|
var descriptors = new TagHelperDescriptor[]
|
||||||
|
{
|
||||||
|
TagHelperDescriptorBuilder.Create("InputTagHelper", "SomeAssembly")
|
||||||
|
.TagMatchingRuleDescriptor(rule =>
|
||||||
|
rule
|
||||||
|
.RequireTagName("input"))
|
||||||
|
.BoundAttributeDescriptor(attribute =>
|
||||||
|
attribute
|
||||||
|
.Name("boundbool")
|
||||||
|
.PropertyName("BoundBoolProp")
|
||||||
|
.TypeName(typeof(bool).FullName))
|
||||||
|
.BoundAttributeDescriptor(attribute =>
|
||||||
|
attribute
|
||||||
|
.Name("boundbooldict")
|
||||||
|
.PropertyName("BoundBoolDictProp")
|
||||||
|
.TypeName("System.Collections.Generic.IDictionary<string, bool>")
|
||||||
|
.AsDictionary("boundbooldict-", typeof(bool).FullName))
|
||||||
|
.Build(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var featureFlags = new TestRazorParserFeatureFlags(allowMinimizedBooleanTagHelperAttributes: false);
|
||||||
|
|
||||||
|
var expectedOutput = new MarkupBlock(
|
||||||
|
new MarkupTagHelperBlock(
|
||||||
|
"input",
|
||||||
|
TagMode.SelfClosing,
|
||||||
|
attributes: new List<TagHelperAttributeNode>()
|
||||||
|
{
|
||||||
|
new TagHelperAttributeNode("boundbool", null, AttributeStructure.Minimized),
|
||||||
|
new TagHelperAttributeNode("boundbooldict-key", null, AttributeStructure.Minimized),
|
||||||
|
}));
|
||||||
|
|
||||||
|
var expectedErrors = new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
"Attribute 'boundbool' on tag helper element 'input' requires a value. Tag helper bound attributes of type 'System.Boolean' cannot be empty or contain only whitespace.",
|
||||||
|
new SourceLocation(7, 0, 7),
|
||||||
|
length: 9),
|
||||||
|
new RazorError(
|
||||||
|
"Attribute 'boundbooldict-key' on tag helper element 'input' requires a value. Tag helper bound attributes of type 'System.Boolean' cannot be empty or contain only whitespace.",
|
||||||
|
new SourceLocation(17, 0, 17),
|
||||||
|
length: 17),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
EvaluateData(descriptors, documentContent, expectedOutput, expectedErrors, featureFlags: featureFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestRazorParserFeatureFlags : RazorParserFeatureFlags
|
||||||
|
{
|
||||||
|
public TestRazorParserFeatureFlags(bool allowMinimizedBooleanTagHelperAttributes)
|
||||||
|
{
|
||||||
|
AllowMinimizedBooleanTagHelperAttributes = allowMinimizedBooleanTagHelperAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool AllowMinimizedBooleanTagHelperAttributes { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var errorSink = new ErrorSink();
|
var errorSink = new ErrorSink();
|
||||||
var parseResult = ParseDocument(documentContent);
|
var parseResult = ParseDocument(documentContent);
|
||||||
var document = parseResult.Root;
|
var document = parseResult.Root;
|
||||||
var parseTreeRewriter = new TagHelperParseTreeRewriter(null, Enumerable.Empty<TagHelperDescriptor>());
|
var parseTreeRewriter = new TagHelperParseTreeRewriter(null, Enumerable.Empty<TagHelperDescriptor>(), parseResult.Options.FeatureFlags);
|
||||||
|
|
||||||
// Assert - Guard
|
// Assert - Guard
|
||||||
var rootBlock = Assert.IsType<Block>(document);
|
var rootBlock = Assert.IsType<Block>(document);
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
string documentContent,
|
string documentContent,
|
||||||
MarkupBlock expectedOutput,
|
MarkupBlock expectedOutput,
|
||||||
IEnumerable<RazorError> expectedErrors,
|
IEnumerable<RazorError> expectedErrors,
|
||||||
string tagHelperPrefix = null)
|
string tagHelperPrefix = null,
|
||||||
|
RazorParserFeatureFlags featureFlags = null)
|
||||||
{
|
{
|
||||||
var syntaxTree = ParseDocument(documentContent);
|
var syntaxTree = ParseDocument(documentContent);
|
||||||
var errorSink = new ErrorSink();
|
var errorSink = new ErrorSink();
|
||||||
var parseTreeRewriter = new TagHelperParseTreeRewriter(tagHelperPrefix, descriptors);
|
var parseTreeRewriter = new TagHelperParseTreeRewriter(
|
||||||
|
tagHelperPrefix,
|
||||||
|
descriptors,
|
||||||
|
featureFlags ?? syntaxTree.Options.FeatureFlags);
|
||||||
|
|
||||||
var actualTree = parseTreeRewriter.Rewrite(syntaxTree.Root, errorSink);
|
var actualTree = parseTreeRewriter.Rewrite(syntaxTree.Root, errorSink);
|
||||||
|
|
||||||
var allErrors = syntaxTree.Diagnostics.Concat(errorSink.Errors.Select(error => RazorDiagnostic.Create(error)));
|
var allErrors = syntaxTree.Diagnostics.Concat(errorSink.Errors.Select(error => RazorDiagnostic.Create(error)));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
// 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 Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
{
|
||||||
|
public class RazorParserFeatureFlagsTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Create_LatestVersion_AllowsMinimizedBooleanTagHelperAttributes()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var context = RazorParserFeatureFlags.Create(RazorLanguageVersion.Version2_1);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(context.AllowMinimizedBooleanTagHelperAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Create_OlderVersion_DoesNotAllowMinimizedBooleanTagHelperAttributes()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var context = RazorParserFeatureFlags.Create(RazorLanguageVersion.Version1_1);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(context.AllowMinimizedBooleanTagHelperAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Create_UnknownVersion_Throws()
|
||||||
|
{
|
||||||
|
// Arrange, Act & Assert
|
||||||
|
var exception = Assert.Throws<ArgumentException>(
|
||||||
|
() => RazorParserFeatureFlags.Create(0));
|
||||||
|
|
||||||
|
Assert.Equal("Provided value for razor language version is unsupported or invalid: '0'.", exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,4 +15,6 @@
|
||||||
input-unbound-required="hello2"
|
input-unbound-required="hello2"
|
||||||
catchall-unbound-required
|
catchall-unbound-required
|
||||||
input-bound-required-string="world" />
|
input-bound-required-string="world" />
|
||||||
|
<div boundbool booldict-prefix-key></div>
|
||||||
|
<div>Tag helper with unmatched bound boolean attributes.</div>
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -7,6 +7,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
|
||||||
{
|
{
|
||||||
private global::TestNamespace.CatchAllTagHelper __TestNamespace_CatchAllTagHelper;
|
private global::TestNamespace.CatchAllTagHelper __TestNamespace_CatchAllTagHelper;
|
||||||
private global::TestNamespace.InputTagHelper __TestNamespace_InputTagHelper;
|
private global::TestNamespace.InputTagHelper __TestNamespace_InputTagHelper;
|
||||||
|
private global::DivTagHelper __DivTagHelper;
|
||||||
#pragma warning disable 219
|
#pragma warning disable 219
|
||||||
private void __RazorDirectiveTokenHelpers__() {
|
private void __RazorDirectiveTokenHelpers__() {
|
||||||
((System.Action)(() => {
|
((System.Action)(() => {
|
||||||
|
|
@ -32,6 +33,10 @@ global::System.Object __typeHelper = "*, TestAssembly";
|
||||||
__TestNamespace_InputTagHelper = CreateTagHelper<global::TestNamespace.InputTagHelper>();
|
__TestNamespace_InputTagHelper = CreateTagHelper<global::TestNamespace.InputTagHelper>();
|
||||||
__TestNamespace_CatchAllTagHelper = CreateTagHelper<global::TestNamespace.CatchAllTagHelper>();
|
__TestNamespace_CatchAllTagHelper = CreateTagHelper<global::TestNamespace.CatchAllTagHelper>();
|
||||||
__TestNamespace_InputTagHelper.BoundRequiredString = "world";
|
__TestNamespace_InputTagHelper.BoundRequiredString = "world";
|
||||||
|
__DivTagHelper = CreateTagHelper<global::DivTagHelper>();
|
||||||
|
__DivTagHelper.BoundBoolProp = true;
|
||||||
|
__DivTagHelper.BoolDictProp["key"] = true;
|
||||||
|
__DivTagHelper = CreateTagHelper<global::DivTagHelper>();
|
||||||
__TestNamespace_CatchAllTagHelper = CreateTagHelper<global::TestNamespace.CatchAllTagHelper>();
|
__TestNamespace_CatchAllTagHelper = CreateTagHelper<global::TestNamespace.CatchAllTagHelper>();
|
||||||
}
|
}
|
||||||
#pragma warning restore 1998
|
#pragma warning restore 1998
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ Document -
|
||||||
DefaultTagHelperRuntime -
|
DefaultTagHelperRuntime -
|
||||||
FieldDeclaration - - private - global::TestNamespace.CatchAllTagHelper - __TestNamespace_CatchAllTagHelper
|
FieldDeclaration - - private - global::TestNamespace.CatchAllTagHelper - __TestNamespace_CatchAllTagHelper
|
||||||
FieldDeclaration - - private - global::TestNamespace.InputTagHelper - __TestNamespace_InputTagHelper
|
FieldDeclaration - - private - global::TestNamespace.InputTagHelper - __TestNamespace_InputTagHelper
|
||||||
|
FieldDeclaration - - private - global::DivTagHelper - __DivTagHelper
|
||||||
DesignTimeDirective -
|
DesignTimeDirective -
|
||||||
DirectiveToken - (14:0,14 [17] MinimizedTagHelpers.cshtml) - "*, TestAssembly"
|
DirectiveToken - (14:0,14 [17] MinimizedTagHelpers.cshtml) - "*, TestAssembly"
|
||||||
CSharpCode -
|
CSharpCode -
|
||||||
|
|
@ -15,7 +16,7 @@ Document -
|
||||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||||
HtmlContent - (31:0,31 [4] MinimizedTagHelpers.cshtml)
|
HtmlContent - (31:0,31 [4] MinimizedTagHelpers.cshtml)
|
||||||
IntermediateToken - (31:0,31 [4] MinimizedTagHelpers.cshtml) - Html - \n\n
|
IntermediateToken - (31:0,31 [4] MinimizedTagHelpers.cshtml) - Html - \n\n
|
||||||
TagHelper - (35:2,0 [647] MinimizedTagHelpers.cshtml) - p - TagMode.StartTagAndEndTag
|
TagHelper - (35:2,0 [762] MinimizedTagHelpers.cshtml) - p - TagMode.StartTagAndEndTag
|
||||||
DefaultTagHelperBody -
|
DefaultTagHelperBody -
|
||||||
HtmlContent - (64:2,29 [34] MinimizedTagHelpers.cshtml)
|
HtmlContent - (64:2,29 [34] MinimizedTagHelpers.cshtml)
|
||||||
IntermediateToken - (64:2,29 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
IntermediateToken - (64:2,29 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
|
|
@ -84,8 +85,24 @@ Document -
|
||||||
HtmlContent - (667:16,40 [5] MinimizedTagHelpers.cshtml)
|
HtmlContent - (667:16,40 [5] MinimizedTagHelpers.cshtml)
|
||||||
IntermediateToken - (667:16,40 [5] MinimizedTagHelpers.cshtml) - Html - world
|
IntermediateToken - (667:16,40 [5] MinimizedTagHelpers.cshtml) - Html - world
|
||||||
DefaultTagHelperExecute -
|
DefaultTagHelperExecute -
|
||||||
HtmlContent - (676:16,49 [2] MinimizedTagHelpers.cshtml)
|
HtmlContent - (676:16,49 [6] MinimizedTagHelpers.cshtml)
|
||||||
IntermediateToken - (676:16,49 [2] MinimizedTagHelpers.cshtml) - Html - \n
|
IntermediateToken - (676:16,49 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
|
TagHelper - (682:17,4 [41] MinimizedTagHelpers.cshtml) - div - TagMode.StartTagAndEndTag
|
||||||
|
DefaultTagHelperBody -
|
||||||
|
DefaultTagHelperCreate - - DivTagHelper
|
||||||
|
DefaultTagHelperProperty - - boundbool - bool DivTagHelper.BoundBoolProp - HtmlAttributeValueStyle.Minimized
|
||||||
|
DefaultTagHelperProperty - - booldict-prefix-key - System.Collections.Generic.IDictionary<string, bool> DivTagHelper.BoolDictProp - HtmlAttributeValueStyle.Minimized
|
||||||
|
DefaultTagHelperExecute -
|
||||||
|
HtmlContent - (723:17,45 [6] MinimizedTagHelpers.cshtml)
|
||||||
|
IntermediateToken - (723:17,45 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
|
TagHelper - (729:18,4 [62] MinimizedTagHelpers.cshtml) - div - TagMode.StartTagAndEndTag
|
||||||
|
DefaultTagHelperBody -
|
||||||
|
HtmlContent - (734:18,9 [51] MinimizedTagHelpers.cshtml)
|
||||||
|
IntermediateToken - (734:18,9 [51] MinimizedTagHelpers.cshtml) - Html - Tag helper with unmatched bound boolean attributes.
|
||||||
|
DefaultTagHelperCreate - - DivTagHelper
|
||||||
|
DefaultTagHelperExecute -
|
||||||
|
HtmlContent - (791:18,66 [2] MinimizedTagHelpers.cshtml)
|
||||||
|
IntermediateToken - (791:18,66 [2] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
DefaultTagHelperCreate - - TestNamespace.CatchAllTagHelper
|
DefaultTagHelperCreate - - TestNamespace.CatchAllTagHelper
|
||||||
DefaultTagHelperHtmlAttribute - - catchall-unbound-required - HtmlAttributeValueStyle.Minimized
|
DefaultTagHelperHtmlAttribute - - catchall-unbound-required - HtmlAttributeValueStyle.Minimized
|
||||||
DefaultTagHelperExecute -
|
DefaultTagHelperExecute -
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
Source Location: (14:0,14 [17] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MinimizedTagHelpers.cshtml)
|
Source Location: (14:0,14 [17] TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MinimizedTagHelpers.cshtml)
|
||||||
|"*, TestAssembly"|
|
|"*, TestAssembly"|
|
||||||
Generated Location: (603:12,37 [17] )
|
Generated Location: (657:13,37 [17] )
|
||||||
|"*, TestAssembly"|
|
|"*, TestAssembly"|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MinimizedTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "cc93b363a32adf077cc406265e403db466e4ae7d"
|
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/MinimizedTagHelpers.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "ab8c9a5af38d07138a55ae82942b4a97fe3c9025"
|
||||||
// <auto-generated/>
|
// <auto-generated/>
|
||||||
#pragma warning disable 1591
|
#pragma warning disable 1591
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
|
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
|
||||||
|
|
@ -33,6 +33,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
|
||||||
}
|
}
|
||||||
private global::TestNamespace.CatchAllTagHelper __TestNamespace_CatchAllTagHelper;
|
private global::TestNamespace.CatchAllTagHelper __TestNamespace_CatchAllTagHelper;
|
||||||
private global::TestNamespace.InputTagHelper __TestNamespace_InputTagHelper;
|
private global::TestNamespace.InputTagHelper __TestNamespace_InputTagHelper;
|
||||||
|
private global::DivTagHelper __DivTagHelper;
|
||||||
#pragma warning disable 1998
|
#pragma warning disable 1998
|
||||||
public async System.Threading.Tasks.Task ExecuteAsync()
|
public async System.Threading.Tasks.Task ExecuteAsync()
|
||||||
{
|
{
|
||||||
|
|
@ -128,6 +129,41 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
|
||||||
}
|
}
|
||||||
Write(__tagHelperExecutionContext.Output);
|
Write(__tagHelperExecutionContext.Output);
|
||||||
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("div", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "test", async() => {
|
||||||
|
}
|
||||||
|
);
|
||||||
|
__DivTagHelper = CreateTagHelper<global::DivTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__DivTagHelper);
|
||||||
|
__DivTagHelper.BoundBoolProp = true;
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("boundbool", __DivTagHelper.BoundBoolProp, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.Minimized);
|
||||||
|
if (__DivTagHelper.BoolDictProp == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(InvalidTagHelperIndexerAssignment("booldict-prefix-key", "DivTagHelper", "BoolDictProp"));
|
||||||
|
}
|
||||||
|
__DivTagHelper.BoolDictProp["key"] = true;
|
||||||
|
__tagHelperExecutionContext.AddTagHelperAttribute("booldict-prefix-key", __DivTagHelper.BoolDictProp["key"], global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.Minimized);
|
||||||
|
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
if (!__tagHelperExecutionContext.Output.IsContentModified)
|
||||||
|
{
|
||||||
|
await __tagHelperExecutionContext.SetOutputContentAsync();
|
||||||
|
}
|
||||||
|
Write(__tagHelperExecutionContext.Output);
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
|
WriteLiteral("\r\n ");
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("div", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "test", async() => {
|
||||||
|
WriteLiteral("Tag helper with unmatched bound boolean attributes.");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
__DivTagHelper = CreateTagHelper<global::DivTagHelper>();
|
||||||
|
__tagHelperExecutionContext.Add(__DivTagHelper);
|
||||||
|
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext);
|
||||||
|
if (!__tagHelperExecutionContext.Output.IsContentModified)
|
||||||
|
{
|
||||||
|
await __tagHelperExecutionContext.SetOutputContentAsync();
|
||||||
|
}
|
||||||
|
Write(__tagHelperExecutionContext.Output);
|
||||||
|
__tagHelperExecutionContext = __tagHelperScopeManager.End();
|
||||||
WriteLiteral("\r\n");
|
WriteLiteral("\r\n");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@ Document -
|
||||||
DefaultTagHelperRuntime -
|
DefaultTagHelperRuntime -
|
||||||
FieldDeclaration - - private - global::TestNamespace.CatchAllTagHelper - __TestNamespace_CatchAllTagHelper
|
FieldDeclaration - - private - global::TestNamespace.CatchAllTagHelper - __TestNamespace_CatchAllTagHelper
|
||||||
FieldDeclaration - - private - global::TestNamespace.InputTagHelper - __TestNamespace_InputTagHelper
|
FieldDeclaration - - private - global::TestNamespace.InputTagHelper - __TestNamespace_InputTagHelper
|
||||||
|
FieldDeclaration - - private - global::DivTagHelper - __DivTagHelper
|
||||||
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
MethodDeclaration - - public async - System.Threading.Tasks.Task - ExecuteAsync
|
||||||
HtmlContent - (33:1,0 [2] MinimizedTagHelpers.cshtml)
|
HtmlContent - (33:1,0 [2] MinimizedTagHelpers.cshtml)
|
||||||
IntermediateToken - (33:1,0 [2] MinimizedTagHelpers.cshtml) - Html - \n
|
IntermediateToken - (33:1,0 [2] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
TagHelper - (35:2,0 [647] MinimizedTagHelpers.cshtml) - p - TagMode.StartTagAndEndTag
|
TagHelper - (35:2,0 [762] MinimizedTagHelpers.cshtml) - p - TagMode.StartTagAndEndTag
|
||||||
DefaultTagHelperBody -
|
DefaultTagHelperBody -
|
||||||
HtmlContent - (64:2,29 [34] MinimizedTagHelpers.cshtml)
|
HtmlContent - (64:2,29 [34] MinimizedTagHelpers.cshtml)
|
||||||
IntermediateToken - (64:2,29 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
IntermediateToken - (64:2,29 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
|
|
@ -63,8 +64,24 @@ Document -
|
||||||
DefaultTagHelperHtmlAttribute - - catchall-unbound-required - HtmlAttributeValueStyle.Minimized
|
DefaultTagHelperHtmlAttribute - - catchall-unbound-required - HtmlAttributeValueStyle.Minimized
|
||||||
PreallocatedTagHelperProperty - (667:16,40 [5] MinimizedTagHelpers.cshtml) - __tagHelperAttribute_6 - input-bound-required-string - BoundRequiredString
|
PreallocatedTagHelperProperty - (667:16,40 [5] MinimizedTagHelpers.cshtml) - __tagHelperAttribute_6 - input-bound-required-string - BoundRequiredString
|
||||||
DefaultTagHelperExecute -
|
DefaultTagHelperExecute -
|
||||||
HtmlContent - (676:16,49 [2] MinimizedTagHelpers.cshtml)
|
HtmlContent - (676:16,49 [6] MinimizedTagHelpers.cshtml)
|
||||||
IntermediateToken - (676:16,49 [2] MinimizedTagHelpers.cshtml) - Html - \n
|
IntermediateToken - (676:16,49 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
|
TagHelper - (682:17,4 [41] MinimizedTagHelpers.cshtml) - div - TagMode.StartTagAndEndTag
|
||||||
|
DefaultTagHelperBody -
|
||||||
|
DefaultTagHelperCreate - - DivTagHelper
|
||||||
|
DefaultTagHelperProperty - - boundbool - bool DivTagHelper.BoundBoolProp - HtmlAttributeValueStyle.Minimized
|
||||||
|
DefaultTagHelperProperty - - booldict-prefix-key - System.Collections.Generic.IDictionary<string, bool> DivTagHelper.BoolDictProp - HtmlAttributeValueStyle.Minimized
|
||||||
|
DefaultTagHelperExecute -
|
||||||
|
HtmlContent - (723:17,45 [6] MinimizedTagHelpers.cshtml)
|
||||||
|
IntermediateToken - (723:17,45 [6] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
|
TagHelper - (729:18,4 [62] MinimizedTagHelpers.cshtml) - div - TagMode.StartTagAndEndTag
|
||||||
|
DefaultTagHelperBody -
|
||||||
|
HtmlContent - (734:18,9 [51] MinimizedTagHelpers.cshtml)
|
||||||
|
IntermediateToken - (734:18,9 [51] MinimizedTagHelpers.cshtml) - Html - Tag helper with unmatched bound boolean attributes.
|
||||||
|
DefaultTagHelperCreate - - DivTagHelper
|
||||||
|
DefaultTagHelperExecute -
|
||||||
|
HtmlContent - (791:18,66 [2] MinimizedTagHelpers.cshtml)
|
||||||
|
IntermediateToken - (791:18,66 [2] MinimizedTagHelpers.cshtml) - Html - \n
|
||||||
DefaultTagHelperCreate - - TestNamespace.CatchAllTagHelper
|
DefaultTagHelperCreate - - TestNamespace.CatchAllTagHelper
|
||||||
DefaultTagHelperHtmlAttribute - - catchall-unbound-required - HtmlAttributeValueStyle.Minimized
|
DefaultTagHelperHtmlAttribute - - catchall-unbound-required - HtmlAttributeValueStyle.Minimized
|
||||||
DefaultTagHelperExecute -
|
DefaultTagHelperExecute -
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue