Moved TagHelper directive validation and parsing from TagHelperBinder to
CSharpCodeParser
This commit is contained in:
parent
9b6420dbfc
commit
fa6fde2b20
|
|
@ -10,11 +10,6 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
{
|
{
|
||||||
internal class DefaultRazorTagHelperBinderPhase : RazorEnginePhaseBase, IRazorTagHelperBinderPhase
|
internal class DefaultRazorTagHelperBinderPhase : RazorEnginePhaseBase, IRazorTagHelperBinderPhase
|
||||||
{
|
{
|
||||||
private static HashSet<char> InvalidNonWhitespaceNameCharacters = new HashSet<char>(new[]
|
|
||||||
{
|
|
||||||
'@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*'
|
|
||||||
});
|
|
||||||
|
|
||||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||||
{
|
{
|
||||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||||
|
|
@ -31,7 +26,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
//
|
//
|
||||||
// The imports come logically before the main razor file and are in the order they
|
// The imports come logically before the main razor file and are in the order they
|
||||||
// should be processed.
|
// should be processed.
|
||||||
var visitor = new DirectiveVisitor();
|
var descriptors = feature.GetDescriptors();
|
||||||
|
var visitor = new DirectiveVisitor(descriptors);
|
||||||
var imports = codeDocument.GetImportSyntaxTrees();
|
var imports = codeDocument.GetImportSyntaxTrees();
|
||||||
if (imports != null)
|
if (imports != null)
|
||||||
{
|
{
|
||||||
|
|
@ -44,14 +40,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
|
|
||||||
visitor.VisitBlock(syntaxTree.Root);
|
visitor.VisitBlock(syntaxTree.Root);
|
||||||
|
|
||||||
var errorList = new List<RazorDiagnostic>();
|
var tagHelperPrefix = visitor.TagHelperPrefix;
|
||||||
var descriptors = feature.GetDescriptors();
|
descriptors = visitor.Matches.ToArray();
|
||||||
|
|
||||||
var directives = visitor.Directives;
|
|
||||||
descriptors = ProcessDirectives(directives, descriptors);
|
|
||||||
|
|
||||||
var tagHelperPrefix = ProcessTagHelperPrefix(directives, codeDocument);
|
|
||||||
var root = syntaxTree.Root;
|
|
||||||
|
|
||||||
var context = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
|
var context = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
|
||||||
codeDocument.SetTagHelperContext(context);
|
codeDocument.SetTagHelperContext(context);
|
||||||
|
|
@ -64,9 +54,11 @@ 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);
|
||||||
|
var root = syntaxTree.Root;
|
||||||
root = rewriter.Rewrite(root, errorSink);
|
root = rewriter.Rewrite(root, errorSink);
|
||||||
|
|
||||||
// Temporary code while we're still using legacy diagnostics in the SyntaxTree.
|
// Temporary code while we're still using legacy diagnostics in the SyntaxTree.
|
||||||
|
var errorList = new List<RazorDiagnostic>();
|
||||||
errorList.AddRange(errorSink.Errors.Select(error => RazorDiagnostic.Create(error)));
|
errorList.AddRange(errorSink.Errors.Select(error => RazorDiagnostic.Create(error)));
|
||||||
|
|
||||||
errorList.AddRange(descriptors.SelectMany(d => d.GetAllDiagnostics()));
|
errorList.AddRange(descriptors.SelectMany(d => d.GetAllDiagnostics()));
|
||||||
|
|
@ -77,205 +69,27 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
codeDocument.SetSyntaxTree(newSyntaxTree);
|
codeDocument.SetSyntaxTree(newSyntaxTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal for testing
|
private static bool MatchesDirective(TagHelperDescriptor descriptor, string typePattern, string assemblyName)
|
||||||
internal string ProcessTagHelperPrefix(List<TagHelperDirectiveDescriptor> directives, RazorCodeDocument codeDocument)
|
|
||||||
{
|
{
|
||||||
// We only support a single prefix directive.
|
if (!string.Equals(descriptor.AssemblyName, assemblyName, StringComparison.Ordinal))
|
||||||
TagHelperDirectiveDescriptor prefixDirective = null;
|
|
||||||
for (var i = 0; i < directives.Count; i++)
|
|
||||||
{
|
|
||||||
if (directives[i].DirectiveType == TagHelperDirectiveType.TagHelperPrefix)
|
|
||||||
{
|
|
||||||
// We only expect to see a single one of these per file, but that's enforced at another level.
|
|
||||||
prefixDirective = directives[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var prefix = prefixDirective?.DirectiveText;
|
|
||||||
if (prefix != null && !IsValidTagHelperPrefix(prefix, prefixDirective.Location, prefixDirective.Diagnostics))
|
|
||||||
{
|
|
||||||
prefix = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(prefix))
|
|
||||||
{
|
|
||||||
return prefixDirective.DirectiveText;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IReadOnlyList<TagHelperDescriptor> ProcessDirectives(
|
|
||||||
IReadOnlyList<TagHelperDirectiveDescriptor> directives,
|
|
||||||
IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
|
||||||
{
|
|
||||||
var matches = new HashSet<TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
|
|
||||||
|
|
||||||
for (var i = 0; i < directives.Count; i++)
|
|
||||||
{
|
|
||||||
var directive = directives[i];
|
|
||||||
|
|
||||||
ParsedDirective parsed;
|
|
||||||
switch (directive.DirectiveType)
|
|
||||||
{
|
|
||||||
case TagHelperDirectiveType.AddTagHelper:
|
|
||||||
|
|
||||||
parsed = ParseAddOrRemoveDirective(directive);
|
|
||||||
if (parsed == null)
|
|
||||||
{
|
|
||||||
// Skip this one, it's an error
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!AssemblyContainsTagHelpers(parsed.AssemblyName, tagHelpers))
|
|
||||||
{
|
|
||||||
// No tag helpers in the assembly.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var j = 0; j < tagHelpers.Count; j++)
|
|
||||||
{
|
|
||||||
var tagHelper = tagHelpers[j];
|
|
||||||
if (MatchesDirective(tagHelper, parsed))
|
|
||||||
{
|
|
||||||
matches.Add(tagHelper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TagHelperDirectiveType.RemoveTagHelper:
|
|
||||||
|
|
||||||
parsed = ParseAddOrRemoveDirective(directive);
|
|
||||||
if (parsed == null)
|
|
||||||
{
|
|
||||||
// Skip this one, it's an error
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!AssemblyContainsTagHelpers(parsed.AssemblyName, tagHelpers))
|
|
||||||
{
|
|
||||||
// No tag helpers in the assembly.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var j = 0; j < tagHelpers.Count; j++)
|
|
||||||
{
|
|
||||||
var tagHelper = tagHelpers[j];
|
|
||||||
if (MatchesDirective(tagHelper, parsed))
|
|
||||||
{
|
|
||||||
matches.Remove(tagHelper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matches.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool AssemblyContainsTagHelpers(string assemblyName, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < tagHelpers.Count; i++)
|
|
||||||
{
|
|
||||||
if (string.Equals(tagHelpers[i].AssemblyName, assemblyName, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal for testing
|
|
||||||
internal ParsedDirective ParseAddOrRemoveDirective(TagHelperDirectiveDescriptor directive)
|
|
||||||
{
|
|
||||||
var text = directive.DirectiveText;
|
|
||||||
var lookupStrings = text?.Split(new[] { ',' });
|
|
||||||
|
|
||||||
// Ensure that we have valid lookupStrings to work with. The valid format is "typeName, assemblyName"
|
|
||||||
if (lookupStrings == null ||
|
|
||||||
lookupStrings.Any(string.IsNullOrWhiteSpace) ||
|
|
||||||
lookupStrings.Length != 2)
|
|
||||||
{
|
|
||||||
directive.Diagnostics.Add(
|
|
||||||
RazorDiagnostic.Create(
|
|
||||||
new RazorError(
|
|
||||||
Resources.FormatInvalidTagHelperLookupText(text),
|
|
||||||
directive.Location,
|
|
||||||
Math.Max(text.Length, 1))));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var trimmedAssemblyName = lookupStrings[1].Trim();
|
|
||||||
|
|
||||||
// + 1 is for the comma separator in the lookup text.
|
|
||||||
var assemblyNameIndex =
|
|
||||||
lookupStrings[0].Length + 1 + lookupStrings[1].IndexOf(trimmedAssemblyName, StringComparison.Ordinal);
|
|
||||||
var assemblyNamePrefix = directive.DirectiveText.Substring(0, assemblyNameIndex);
|
|
||||||
var assemblyNameLocation = new SourceLocation(
|
|
||||||
directive.Location.FilePath,
|
|
||||||
directive.Location.AbsoluteIndex + assemblyNameIndex,
|
|
||||||
directive.Location.LineIndex,
|
|
||||||
directive.Location.CharacterIndex + assemblyNameIndex);
|
|
||||||
|
|
||||||
return new ParsedDirective
|
|
||||||
{
|
|
||||||
TypePattern = lookupStrings[0].Trim(),
|
|
||||||
AssemblyName = trimmedAssemblyName,
|
|
||||||
AssemblyNameLocation = assemblyNameLocation,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal for testing
|
|
||||||
internal bool IsValidTagHelperPrefix(
|
|
||||||
string prefix,
|
|
||||||
SourceLocation directiveLocation,
|
|
||||||
List<RazorDiagnostic> diagnostics)
|
|
||||||
{
|
|
||||||
foreach (var character in prefix)
|
|
||||||
{
|
|
||||||
// Prefixes are correlated with tag names, tag names cannot have whitespace.
|
|
||||||
if (char.IsWhiteSpace(character) || InvalidNonWhitespaceNameCharacters.Contains(character))
|
|
||||||
{
|
|
||||||
diagnostics.Add(
|
|
||||||
RazorDiagnostic.Create(
|
|
||||||
new RazorError(
|
|
||||||
Resources.FormatInvalidTagHelperPrefixValue(SyntaxConstants.CSharp.TagHelperPrefixKeyword, character, prefix),
|
|
||||||
directiveLocation,
|
|
||||||
prefix.Length)));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool MatchesDirective(TagHelperDescriptor descriptor, ParsedDirective lookupInfo)
|
|
||||||
{
|
|
||||||
if (!string.Equals(descriptor.AssemblyName, lookupInfo.AssemblyName, StringComparison.Ordinal))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookupInfo.TypePattern.EndsWith("*", StringComparison.Ordinal))
|
if (typePattern.EndsWith("*", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
if (lookupInfo.TypePattern.Length == 1)
|
if (typePattern.Length == 1)
|
||||||
{
|
{
|
||||||
// TypePattern is "*".
|
// TypePattern is "*".
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lookupTypeName = lookupInfo.TypePattern.Substring(0, lookupInfo.TypePattern.Length - 1);
|
var lookupTypeName = typePattern.Substring(0, typePattern.Length - 1);
|
||||||
|
|
||||||
return descriptor.Name.StartsWith(lookupTypeName, StringComparison.Ordinal);
|
return descriptor.Name.StartsWith(lookupTypeName, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Equals(descriptor.Name, lookupInfo.TypePattern, StringComparison.Ordinal);
|
return string.Equals(descriptor.Name, typePattern, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetErrorLength(string directiveText)
|
private static int GetErrorLength(string directiveText)
|
||||||
|
|
@ -295,81 +109,89 @@ namespace Microsoft.AspNetCore.Razor.Language
|
||||||
return combinedErrors;
|
return combinedErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ParsedDirective
|
// Internal for testing.
|
||||||
|
internal class DirectiveVisitor : ParserVisitor
|
||||||
{
|
{
|
||||||
public string AssemblyName { get; set; }
|
private IReadOnlyList<TagHelperDescriptor> _tagHelpers;
|
||||||
|
|
||||||
public string TypePattern { get; set; }
|
public DirectiveVisitor(IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||||
|
{
|
||||||
|
_tagHelpers = tagHelpers;
|
||||||
|
}
|
||||||
|
|
||||||
public SourceLocation AssemblyNameLocation { get; set; }
|
public string TagHelperPrefix { get; private set; }
|
||||||
}
|
|
||||||
|
|
||||||
private class DirectiveVisitor : ParserVisitor
|
public HashSet<TagHelperDescriptor> Matches { get; } = new HashSet<TagHelperDescriptor>();
|
||||||
{
|
|
||||||
public List<TagHelperDirectiveDescriptor> Directives { get; } = new List<TagHelperDirectiveDescriptor>();
|
|
||||||
|
|
||||||
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
|
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
|
||||||
{
|
{
|
||||||
var directive = CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.AddTagHelper, chunkGenerator.Diagnostics);
|
if (chunkGenerator.AssemblyName == null)
|
||||||
Directives.Add(directive);
|
{
|
||||||
|
// Skip this one, it's an error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AssemblyContainsTagHelpers(chunkGenerator.AssemblyName, _tagHelpers))
|
||||||
|
{
|
||||||
|
// No tag helpers in the assembly.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < _tagHelpers.Count; i++)
|
||||||
|
{
|
||||||
|
var tagHelper = _tagHelpers[i];
|
||||||
|
if (MatchesDirective(tagHelper, chunkGenerator.TypePattern, chunkGenerator.AssemblyName))
|
||||||
|
{
|
||||||
|
Matches.Add(tagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunkGenerator, Span span)
|
public override void VisitRemoveTagHelperSpan(RemoveTagHelperChunkGenerator chunkGenerator, Span span)
|
||||||
{
|
{
|
||||||
var directive = CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.RemoveTagHelper, chunkGenerator.Diagnostics);
|
if (chunkGenerator.AssemblyName == null)
|
||||||
Directives.Add(directive);
|
{
|
||||||
|
// Skip this one, it's an error
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!AssemblyContainsTagHelpers(chunkGenerator.AssemblyName, _tagHelpers))
|
||||||
|
{
|
||||||
|
// No tag helpers in the assembly.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < _tagHelpers.Count; i++)
|
||||||
|
{
|
||||||
|
var tagHelper = _tagHelpers[i];
|
||||||
|
if (MatchesDirective(tagHelper, chunkGenerator.TypePattern, chunkGenerator.AssemblyName))
|
||||||
|
{
|
||||||
|
Matches.Remove(tagHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void VisitTagHelperPrefixDirectiveSpan(TagHelperPrefixDirectiveChunkGenerator chunkGenerator, Span span)
|
public override void VisitTagHelperPrefixDirectiveSpan(TagHelperPrefixDirectiveChunkGenerator chunkGenerator, Span span)
|
||||||
{
|
{
|
||||||
var directive = CreateDirective(span, chunkGenerator.Prefix, TagHelperDirectiveType.TagHelperPrefix, chunkGenerator.Diagnostics);
|
if (!string.IsNullOrEmpty(chunkGenerator.DirectiveText))
|
||||||
Directives.Add(directive);
|
{
|
||||||
|
// We only expect to see a single one of these per file, but that's enforced at another level.
|
||||||
|
TagHelperPrefix = chunkGenerator.DirectiveText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TagHelperDirectiveDescriptor CreateDirective(
|
private bool AssemblyContainsTagHelpers(string assemblyName, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||||
Span span,
|
|
||||||
string directiveText,
|
|
||||||
TagHelperDirectiveType directiveType,
|
|
||||||
List<RazorDiagnostic> diagnostics)
|
|
||||||
{
|
{
|
||||||
directiveText = directiveText.Trim();
|
for (var i = 0; i < tagHelpers.Count; i++)
|
||||||
if (directiveText.Length >= 2 &&
|
|
||||||
directiveText.StartsWith("\"", StringComparison.Ordinal) &&
|
|
||||||
directiveText.EndsWith("\"", StringComparison.Ordinal))
|
|
||||||
{
|
{
|
||||||
directiveText = directiveText.Substring(1, directiveText.Length - 2);
|
if (string.Equals(tagHelpers[i].AssemblyName, assemblyName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the "string literal" form of a directive, we'll need to postprocess the location
|
return false;
|
||||||
// and content.
|
|
||||||
//
|
|
||||||
// Ex: @addTagHelper "*, Microsoft.AspNetCore.CoolLibrary"
|
|
||||||
// ^ ^
|
|
||||||
// Start End
|
|
||||||
var directiveStart = span.Start;
|
|
||||||
if (span.Symbols.Count == 1 && (span.Symbols[0] as CSharpSymbol)?.Type == CSharpSymbolType.StringLiteral)
|
|
||||||
{
|
|
||||||
var offset = span.Content.IndexOf(directiveText, StringComparison.Ordinal);
|
|
||||||
|
|
||||||
// This is safe because inside one of these directives all of the text needs to be on the
|
|
||||||
// same line.
|
|
||||||
var original = span.Start;
|
|
||||||
directiveStart = new SourceLocation(
|
|
||||||
original.FilePath,
|
|
||||||
original.AbsoluteIndex + offset,
|
|
||||||
original.LineIndex,
|
|
||||||
original.CharacterIndex + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
var directiveDescriptor = new TagHelperDirectiveDescriptor
|
|
||||||
{
|
|
||||||
DirectiveText = directiveText,
|
|
||||||
Location = directiveStart,
|
|
||||||
DirectiveType = directiveType,
|
|
||||||
Diagnostics = diagnostics,
|
|
||||||
};
|
|
||||||
|
|
||||||
return directiveDescriptor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
internal class AddTagHelperChunkGenerator : SpanChunkGenerator
|
internal class AddTagHelperChunkGenerator : SpanChunkGenerator
|
||||||
{
|
{
|
||||||
public AddTagHelperChunkGenerator(string lookupText, List<RazorDiagnostic> diagnostics)
|
public AddTagHelperChunkGenerator(
|
||||||
|
string lookupText,
|
||||||
|
string directiveText,
|
||||||
|
string typePattern,
|
||||||
|
string assemblyName,
|
||||||
|
List<RazorDiagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
LookupText = lookupText;
|
LookupText = lookupText;
|
||||||
|
DirectiveText = directiveText;
|
||||||
|
AssemblyName = assemblyName;
|
||||||
|
TypePattern = typePattern;
|
||||||
Diagnostics = diagnostics;
|
Diagnostics = diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string LookupText { get; }
|
public string LookupText { get; }
|
||||||
|
|
||||||
|
public string DirectiveText { get; set; }
|
||||||
|
|
||||||
|
public string TypePattern { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyName { get; set; }
|
||||||
|
|
||||||
public List<RazorDiagnostic> Diagnostics { get; }
|
public List<RazorDiagnostic> Diagnostics { get; }
|
||||||
|
|
||||||
public override void Accept(ParserVisitor visitor, Span span)
|
public override void Accept(ParserVisitor visitor, Span span)
|
||||||
|
|
@ -31,7 +45,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var other = obj as AddTagHelperChunkGenerator;
|
var other = obj as AddTagHelperChunkGenerator;
|
||||||
return base.Equals(other) &&
|
return base.Equals(other) &&
|
||||||
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
|
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
|
||||||
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal);
|
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(DirectiveText, other.DirectiveText, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(TypePattern, other.TypePattern, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(AssemblyName, other.AssemblyName, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -40,6 +57,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var combiner = HashCodeCombiner.Start();
|
var combiner = HashCodeCombiner.Start();
|
||||||
combiner.Add(base.GetHashCode());
|
combiner.Add(base.GetHashCode());
|
||||||
combiner.Add(LookupText, StringComparer.Ordinal);
|
combiner.Add(LookupText, StringComparer.Ordinal);
|
||||||
|
combiner.Add(DirectiveText, StringComparer.Ordinal);
|
||||||
|
combiner.Add(TypePattern, StringComparer.Ordinal);
|
||||||
|
combiner.Add(AssemblyName, StringComparer.Ordinal);
|
||||||
|
|
||||||
return combiner.CombinedHash;
|
return combiner.CombinedHash;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
internal class CSharpCodeParser : TokenizerBackedParser<CSharpTokenizer, CSharpSymbol, CSharpSymbolType>
|
internal class CSharpCodeParser : TokenizerBackedParser<CSharpTokenizer, CSharpSymbol, CSharpSymbolType>
|
||||||
{
|
{
|
||||||
|
private static HashSet<char> InvalidNonWhitespaceNameCharacters = new HashSet<char>(new[]
|
||||||
|
{
|
||||||
|
'@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*'
|
||||||
|
});
|
||||||
|
|
||||||
private static readonly Func<CSharpSymbol, bool> IsValidStatementSpacingSymbol =
|
private static readonly Func<CSharpSymbol, bool> IsValidStatementSpacingSymbol =
|
||||||
IsSpacingToken(includeNewLines: true, includeComments: true);
|
IsSpacingToken(includeNewLines: true, includeComments: true);
|
||||||
|
|
||||||
|
|
@ -1905,22 +1910,158 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
errors.Add(duplicateDiagnostic);
|
errors.Add(duplicateDiagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TagHelperPrefixDirectiveChunkGenerator(prefix, errors);
|
var parsedDirective = ParseDirective(prefix, Span.Start, TagHelperDirectiveType.TagHelperPrefix, errors);
|
||||||
|
|
||||||
|
return new TagHelperPrefixDirectiveChunkGenerator(
|
||||||
|
prefix,
|
||||||
|
parsedDirective.DirectiveText,
|
||||||
|
errors);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Internal for testing.
|
||||||
|
internal void ValidateTagHelperPrefix(
|
||||||
|
string prefix,
|
||||||
|
SourceLocation directiveLocation,
|
||||||
|
List<RazorDiagnostic> diagnostics)
|
||||||
|
{
|
||||||
|
foreach (var character in prefix)
|
||||||
|
{
|
||||||
|
// Prefixes are correlated with tag names, tag names cannot have whitespace.
|
||||||
|
if (char.IsWhiteSpace(character) || InvalidNonWhitespaceNameCharacters.Contains(character))
|
||||||
|
{
|
||||||
|
diagnostics.Add(
|
||||||
|
RazorDiagnostic.Create(
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperPrefixValue(SyntaxConstants.CSharp.TagHelperPrefixKeyword, character, prefix),
|
||||||
|
directiveLocation,
|
||||||
|
prefix.Length)));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParsedDirective ParseDirective(
|
||||||
|
string directiveText,
|
||||||
|
SourceLocation directiveLocation,
|
||||||
|
TagHelperDirectiveType directiveType,
|
||||||
|
List<RazorDiagnostic> errors)
|
||||||
|
{
|
||||||
|
var offset = 0;
|
||||||
|
directiveText = directiveText.Trim();
|
||||||
|
if (directiveText.Length >= 2 &&
|
||||||
|
directiveText.StartsWith("\"", StringComparison.Ordinal) &&
|
||||||
|
directiveText.EndsWith("\"", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
directiveText = directiveText.Substring(1, directiveText.Length - 2);
|
||||||
|
if (string.IsNullOrEmpty(directiveText))
|
||||||
|
{
|
||||||
|
offset = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is the "string literal" form of a directive, we'll need to postprocess the location
|
||||||
|
// and content.
|
||||||
|
//
|
||||||
|
// Ex: @addTagHelper "*, Microsoft.AspNetCore.CoolLibrary"
|
||||||
|
// ^ ^
|
||||||
|
// Start End
|
||||||
|
if (Span.Symbols.Count == 1 && (Span.Symbols[0] as CSharpSymbol)?.Type == CSharpSymbolType.StringLiteral)
|
||||||
|
{
|
||||||
|
offset += Span.Symbols[0].Content.IndexOf(directiveText, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
// This is safe because inside one of these directives all of the text needs to be on the
|
||||||
|
// same line.
|
||||||
|
var original = directiveLocation;
|
||||||
|
directiveLocation = new SourceLocation(
|
||||||
|
original.FilePath,
|
||||||
|
original.AbsoluteIndex + offset,
|
||||||
|
original.LineIndex,
|
||||||
|
original.CharacterIndex + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedDirective = new ParsedDirective()
|
||||||
|
{
|
||||||
|
DirectiveText = directiveText
|
||||||
|
};
|
||||||
|
|
||||||
|
if (directiveType == TagHelperDirectiveType.TagHelperPrefix)
|
||||||
|
{
|
||||||
|
ValidateTagHelperPrefix(parsedDirective.DirectiveText, directiveLocation, errors);
|
||||||
|
|
||||||
|
return parsedDirective;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseAddOrRemoveDirective(parsedDirective, directiveLocation, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal for testing.
|
||||||
|
internal ParsedDirective ParseAddOrRemoveDirective(ParsedDirective directive, SourceLocation directiveLocation, List<RazorDiagnostic> errors)
|
||||||
|
{
|
||||||
|
var text = directive.DirectiveText;
|
||||||
|
var lookupStrings = text?.Split(new[] { ',' });
|
||||||
|
|
||||||
|
// Ensure that we have valid lookupStrings to work with. The valid format is "typeName, assemblyName"
|
||||||
|
if (lookupStrings == null ||
|
||||||
|
lookupStrings.Any(string.IsNullOrWhiteSpace) ||
|
||||||
|
lookupStrings.Length != 2)
|
||||||
|
{
|
||||||
|
errors.Add(
|
||||||
|
RazorDiagnostic.Create(
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText(text),
|
||||||
|
directiveLocation,
|
||||||
|
Math.Max(text.Length, 1))));
|
||||||
|
|
||||||
|
return directive;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trimmedAssemblyName = lookupStrings[1].Trim();
|
||||||
|
|
||||||
|
// + 1 is for the comma separator in the lookup text.
|
||||||
|
var assemblyNameIndex =
|
||||||
|
lookupStrings[0].Length + 1 + lookupStrings[1].IndexOf(trimmedAssemblyName, StringComparison.Ordinal);
|
||||||
|
var assemblyNamePrefix = directive.DirectiveText.Substring(0, assemblyNameIndex);
|
||||||
|
|
||||||
|
directive.TypePattern = lookupStrings[0].Trim();
|
||||||
|
directive.AssemblyName = trimmedAssemblyName;
|
||||||
|
|
||||||
|
return directive;
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void AddTagHelperDirective()
|
protected virtual void AddTagHelperDirective()
|
||||||
{
|
{
|
||||||
TagHelperDirective(
|
TagHelperDirective(
|
||||||
SyntaxConstants.CSharp.AddTagHelperKeyword,
|
SyntaxConstants.CSharp.AddTagHelperKeyword,
|
||||||
(lookupText, errors) => new AddTagHelperChunkGenerator(lookupText, errors));
|
(lookupText, errors) =>
|
||||||
|
{
|
||||||
|
var parsedDirective = ParseDirective(lookupText, Span.Start, TagHelperDirectiveType.AddTagHelper, errors);
|
||||||
|
|
||||||
|
return new AddTagHelperChunkGenerator(
|
||||||
|
lookupText,
|
||||||
|
parsedDirective.DirectiveText,
|
||||||
|
parsedDirective.TypePattern,
|
||||||
|
parsedDirective.AssemblyName,
|
||||||
|
errors);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void RemoveTagHelperDirective()
|
protected virtual void RemoveTagHelperDirective()
|
||||||
{
|
{
|
||||||
TagHelperDirective(
|
TagHelperDirective(
|
||||||
SyntaxConstants.CSharp.RemoveTagHelperKeyword,
|
SyntaxConstants.CSharp.RemoveTagHelperKeyword,
|
||||||
(lookupText, errors) => new RemoveTagHelperChunkGenerator(lookupText, errors));
|
(lookupText, errors) =>
|
||||||
|
{
|
||||||
|
var parsedDirective = ParseDirective(lookupText, Span.Start, TagHelperDirectiveType.RemoveTagHelper, errors);
|
||||||
|
|
||||||
|
return new RemoveTagHelperChunkGenerator(
|
||||||
|
lookupText,
|
||||||
|
parsedDirective.DirectiveText,
|
||||||
|
parsedDirective.TypePattern,
|
||||||
|
parsedDirective.AssemblyName,
|
||||||
|
errors);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
|
|
@ -2093,5 +2234,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return sym.Content;
|
return sym.Content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class ParsedDirective
|
||||||
|
{
|
||||||
|
public string DirectiveText { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyName { get; set; }
|
||||||
|
|
||||||
|
public string TypePattern { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
internal class RemoveTagHelperChunkGenerator : SpanChunkGenerator
|
internal class RemoveTagHelperChunkGenerator : SpanChunkGenerator
|
||||||
{
|
{
|
||||||
public RemoveTagHelperChunkGenerator(string lookupText, List<RazorDiagnostic> diagnostics)
|
public RemoveTagHelperChunkGenerator(
|
||||||
|
string lookupText,
|
||||||
|
string directiveText,
|
||||||
|
string typePattern,
|
||||||
|
string assemblyName,
|
||||||
|
List<RazorDiagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
LookupText = lookupText;
|
LookupText = lookupText;
|
||||||
|
DirectiveText = directiveText;
|
||||||
|
TypePattern = typePattern;
|
||||||
|
AssemblyName = assemblyName;
|
||||||
Diagnostics = diagnostics;
|
Diagnostics = diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string LookupText { get; }
|
public string LookupText { get; }
|
||||||
|
|
||||||
|
public string DirectiveText { get; set; }
|
||||||
|
|
||||||
|
public string TypePattern { get; set; }
|
||||||
|
|
||||||
|
public string AssemblyName { get; set; }
|
||||||
|
|
||||||
public List<RazorDiagnostic> Diagnostics { get; }
|
public List<RazorDiagnostic> Diagnostics { get; }
|
||||||
|
|
||||||
public override void Accept(ParserVisitor visitor, Span span)
|
public override void Accept(ParserVisitor visitor, Span span)
|
||||||
|
|
@ -31,7 +45,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var other = obj as RemoveTagHelperChunkGenerator;
|
var other = obj as RemoveTagHelperChunkGenerator;
|
||||||
return base.Equals(other) &&
|
return base.Equals(other) &&
|
||||||
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
|
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
|
||||||
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal);
|
string.Equals(LookupText, other.LookupText, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(DirectiveText, other.DirectiveText, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(TypePattern, other.TypePattern, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(AssemblyName, other.AssemblyName, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -40,6 +57,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var combiner = HashCodeCombiner.Start();
|
var combiner = HashCodeCombiner.Start();
|
||||||
combiner.Add(base.GetHashCode());
|
combiner.Add(base.GetHashCode());
|
||||||
combiner.Add(LookupText, StringComparer.Ordinal);
|
combiner.Add(LookupText, StringComparer.Ordinal);
|
||||||
|
combiner.Add(DirectiveText, StringComparer.Ordinal);
|
||||||
|
combiner.Add(TypePattern, StringComparer.Ordinal);
|
||||||
|
combiner.Add(AssemblyName, StringComparer.Ordinal);
|
||||||
|
|
||||||
return combiner.CombinedHash;
|
return combiner.CombinedHash;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
// 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.Legacy
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Contains information needed to resolve <see cref="TagHelperDescriptor"/>s.
|
|
||||||
/// </summary>
|
|
||||||
internal class TagHelperDirectiveDescriptor
|
|
||||||
{
|
|
||||||
private string _directiveText;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A <see cref="string"/> used to find tag helper <see cref="System.Type"/>s.
|
|
||||||
/// </summary>
|
|
||||||
public string DirectiveText
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _directiveText;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
_directiveText = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="SourceLocation"/> of the directive.
|
|
||||||
/// </summary>
|
|
||||||
public SourceLocation Location { get; set; } = SourceLocation.Zero;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="TagHelperDirectiveType"/> of this directive.
|
|
||||||
/// </summary>
|
|
||||||
public TagHelperDirectiveType DirectiveType { get; set; }
|
|
||||||
|
|
||||||
public List<RazorDiagnostic> Diagnostics { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,14 +10,17 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
{
|
{
|
||||||
internal class TagHelperPrefixDirectiveChunkGenerator : SpanChunkGenerator
|
internal class TagHelperPrefixDirectiveChunkGenerator : SpanChunkGenerator
|
||||||
{
|
{
|
||||||
public TagHelperPrefixDirectiveChunkGenerator(string prefix, List<RazorDiagnostic> diagnostics)
|
public TagHelperPrefixDirectiveChunkGenerator(string prefix, string directiveText, List<RazorDiagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
Prefix = prefix;
|
Prefix = prefix;
|
||||||
|
DirectiveText = directiveText;
|
||||||
Diagnostics = diagnostics;
|
Diagnostics = diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Prefix { get; }
|
public string Prefix { get; }
|
||||||
|
|
||||||
|
public string DirectiveText { get; }
|
||||||
|
|
||||||
public List<RazorDiagnostic> Diagnostics { get; }
|
public List<RazorDiagnostic> Diagnostics { get; }
|
||||||
|
|
||||||
public override void Accept(ParserVisitor visitor, Span span)
|
public override void Accept(ParserVisitor visitor, Span span)
|
||||||
|
|
@ -31,7 +34,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var other = obj as TagHelperPrefixDirectiveChunkGenerator;
|
var other = obj as TagHelperPrefixDirectiveChunkGenerator;
|
||||||
return base.Equals(other) &&
|
return base.Equals(other) &&
|
||||||
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
|
Enumerable.SequenceEqual(Diagnostics, other.Diagnostics) &&
|
||||||
string.Equals(Prefix, other.Prefix, StringComparison.Ordinal);
|
string.Equals(Prefix, other.Prefix, StringComparison.Ordinal) &&
|
||||||
|
string.Equals(DirectiveText, other.DirectiveText, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -40,6 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
var combiner = HashCodeCombiner.Start();
|
var combiner = HashCodeCombiner.Start();
|
||||||
combiner.Add(base.GetHashCode());
|
combiner.Add(base.GetHashCode());
|
||||||
combiner.Add(Prefix, StringComparer.Ordinal);
|
combiner.Add(Prefix, StringComparer.Ordinal);
|
||||||
|
combiner.Add(DirectiveText, StringComparer.Ordinal);
|
||||||
|
|
||||||
return combiner.CombinedHash;
|
return combiner.CombinedHash;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -350,7 +350,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"*, Foo\"")
|
Factory.Code("\"*, Foo\"")
|
||||||
.AsAddTagHelper("\"*, Foo\"")));
|
.AsAddTagHelper(
|
||||||
|
"\"*, Foo\"",
|
||||||
|
"*, Foo",
|
||||||
|
"*",
|
||||||
|
"Foo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -370,7 +374,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"*, Foo\"")
|
Factory.Code("\"*, Foo\"")
|
||||||
.AsAddTagHelper(
|
.AsAddTagHelper(
|
||||||
"\"*, Foo\"",
|
"\"*, Foo\"",
|
||||||
|
"*, Foo",
|
||||||
|
"*",
|
||||||
|
"Foo",
|
||||||
new RazorError(Resources.FormatDirectiveMustAppearAtStartOfLine("addTagHelper"), new SourceLocation(4, 0, 4), 12))),
|
new RazorError(Resources.FormatDirectiveMustAppearAtStartOfLine("addTagHelper"), new SourceLocation(4, 0, 4), 12))),
|
||||||
Factory.Code(Environment.NewLine).AsStatement(),
|
Factory.Code(Environment.NewLine).AsStatement(),
|
||||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)));
|
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)));
|
||||||
|
|
@ -1009,7 +1016,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"\"")
|
Factory.Code("\"\"")
|
||||||
.AsTagHelperPrefixDirective("\"\"")));
|
.AsTagHelperPrefixDirective("\"\"", string.Empty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1022,7 +1029,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo")
|
Factory.Code("Foo")
|
||||||
.AsTagHelperPrefixDirective("Foo")));
|
.AsTagHelperPrefixDirective("Foo", "Foo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1035,7 +1042,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"Foo\"")
|
Factory.Code("\"Foo\"")
|
||||||
.AsTagHelperPrefixDirective("\"Foo\"")));
|
.AsTagHelperPrefixDirective("\"Foo\"", "Foo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1054,7 +1061,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.EmptyCSharp()
|
Factory.EmptyCSharp()
|
||||||
.AsTagHelperPrefixDirective(string.Empty, expectedError)
|
.AsTagHelperPrefixDirective(string.Empty, string.Empty, expectedError)
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1069,6 +1076,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
||||||
new RazorError(
|
new RazorError(
|
||||||
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.TagHelperPrefixKeyword),
|
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.TagHelperPrefixKeyword),
|
||||||
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperPrefixValue(SyntaxConstants.CSharp.TagHelperPrefixKeyword, '"', "\"Foo"),
|
||||||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1080,7 +1090,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"Foo")
|
Factory.Code("\"Foo")
|
||||||
.AsTagHelperPrefixDirective("\"Foo", expectedErrors)));
|
.AsTagHelperPrefixDirective("\"Foo", "\"Foo", expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1094,6 +1104,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
absoluteIndex: 23, lineIndex: 0, columnIndex: 23, length: 1),
|
absoluteIndex: 23, lineIndex: 0, columnIndex: 23, length: 1),
|
||||||
new RazorError(
|
new RazorError(
|
||||||
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.TagHelperPrefixKeyword),
|
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.TagHelperPrefixKeyword),
|
||||||
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 7),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperPrefixValue(SyntaxConstants.CSharp.TagHelperPrefixKeyword, ' ', "Foo \""),
|
||||||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 7)
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 7)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1105,43 +1118,76 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo \"")
|
Factory.Code("Foo \"")
|
||||||
.AsTagHelperPrefixDirective("Foo \"", expectedErrors)));
|
.AsTagHelperPrefixDirective("Foo \"", "Foo \"", expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RemoveTagHelperDirective_NoValue_Succeeds()
|
public void RemoveTagHelperDirective_NoValue_Invalid()
|
||||||
{
|
{
|
||||||
|
var expectedErrors = new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText(string.Empty),
|
||||||
|
new SourceLocation(18, 0, 18),
|
||||||
|
length: 1)
|
||||||
|
};
|
||||||
|
|
||||||
ParseBlockTest("@removeTagHelper \"\"",
|
ParseBlockTest("@removeTagHelper \"\"",
|
||||||
new DirectiveBlock(
|
new DirectiveBlock(
|
||||||
Factory.CodeTransition(),
|
Factory.CodeTransition(),
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"\"")
|
Factory.Code("\"\"")
|
||||||
.AsRemoveTagHelper("\"\"")));
|
.AsRemoveTagHelper(
|
||||||
|
"\"\"",
|
||||||
|
string.Empty,
|
||||||
|
legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RemoveTagHelperDirective_Succeeds()
|
public void RemoveTagHelperDirective_InvalidLookupText_AddsError()
|
||||||
{
|
{
|
||||||
|
var expectedErrors = new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("Foo"),
|
||||||
|
new SourceLocation(17, 0, 17),
|
||||||
|
length: 3)
|
||||||
|
};
|
||||||
|
|
||||||
ParseBlockTest("@removeTagHelper Foo",
|
ParseBlockTest("@removeTagHelper Foo",
|
||||||
new DirectiveBlock(
|
new DirectiveBlock(
|
||||||
Factory.CodeTransition(),
|
Factory.CodeTransition(),
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo")
|
Factory.Code("Foo")
|
||||||
.AsRemoveTagHelper("Foo")));
|
.AsRemoveTagHelper(
|
||||||
|
"Foo",
|
||||||
|
"Foo",
|
||||||
|
legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RemoveTagHelperDirective_WithQuotes_Succeeds()
|
public void RemoveTagHelperDirective_WithQuotes_InvalidLookupText_AddsError()
|
||||||
{
|
{
|
||||||
|
var expectedErrors = new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("Foo"),
|
||||||
|
new SourceLocation(18, 0, 18),
|
||||||
|
length: 3)
|
||||||
|
};
|
||||||
|
|
||||||
ParseBlockTest("@removeTagHelper \"Foo\"",
|
ParseBlockTest("@removeTagHelper \"Foo\"",
|
||||||
new DirectiveBlock(
|
new DirectiveBlock(
|
||||||
Factory.CodeTransition(),
|
Factory.CodeTransition(),
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"Foo\"")
|
Factory.Code("\"Foo\"")
|
||||||
.AsRemoveTagHelper("\"Foo\"")));
|
.AsRemoveTagHelper(
|
||||||
|
"\"Foo\"",
|
||||||
|
"Foo",
|
||||||
|
legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1153,7 +1199,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo, Bar ")
|
Factory.Code("Foo, Bar ")
|
||||||
.AsRemoveTagHelper("Foo, Bar")
|
.AsRemoveTagHelper(
|
||||||
|
"Foo, Bar",
|
||||||
|
"Foo, Bar",
|
||||||
|
"Foo",
|
||||||
|
"Bar")
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1161,9 +1211,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
public void RemoveTagHelperDirective_RequiresValue()
|
public void RemoveTagHelperDirective_RequiresValue()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedError = new RazorError(
|
var expectedErrors = new[]
|
||||||
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
|
{
|
||||||
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15);
|
new RazorError(
|
||||||
|
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
|
||||||
|
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText(string.Empty),
|
||||||
|
new SourceLocation(17, 0, 17),
|
||||||
|
length: 1),
|
||||||
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
ParseBlockTest("@removeTagHelper ",
|
ParseBlockTest("@removeTagHelper ",
|
||||||
|
|
@ -1172,7 +1229,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.EmptyCSharp()
|
Factory.EmptyCSharp()
|
||||||
.AsRemoveTagHelper(string.Empty, expectedError)
|
.AsRemoveTagHelper(string.Empty, string.Empty, legacyErrors: expectedErrors)
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1187,7 +1244,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
||||||
new RazorError(
|
new RazorError(
|
||||||
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
|
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
|
||||||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("\"Foo"),
|
||||||
|
new SourceLocation(17, 0, 17),
|
||||||
|
length: 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
|
|
@ -1197,7 +1258,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"Foo")
|
Factory.Code("\"Foo")
|
||||||
.AsRemoveTagHelper("\"Foo", expectedErrors)));
|
.AsRemoveTagHelper("\"Foo", "\"Foo", legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1211,7 +1272,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
absoluteIndex: 20, lineIndex: 0, columnIndex: 20, length: 1),
|
absoluteIndex: 20, lineIndex: 0, columnIndex: 20, length: 1),
|
||||||
new RazorError(
|
new RazorError(
|
||||||
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
|
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
|
||||||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4)
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 4),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("Foo\""),
|
||||||
|
new SourceLocation(17, 0, 17),
|
||||||
|
length: 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
|
|
@ -1221,48 +1286,81 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo\"")
|
Factory.Code("Foo\"")
|
||||||
.AsRemoveTagHelper("Foo\"", expectedErrors)
|
.AsRemoveTagHelper("Foo\"", "Foo\"", legacyErrors: expectedErrors)
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddTagHelperDirective_NoValue_Succeeds()
|
public void AddTagHelperDirective_NoValue_Invalid()
|
||||||
{
|
{
|
||||||
|
var expectedErrors = new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText(string.Empty),
|
||||||
|
new SourceLocation(15, 0, 15),
|
||||||
|
length: 1)
|
||||||
|
};
|
||||||
|
|
||||||
ParseBlockTest("@addTagHelper \"\"",
|
ParseBlockTest("@addTagHelper \"\"",
|
||||||
new DirectiveBlock(
|
new DirectiveBlock(
|
||||||
Factory.CodeTransition(),
|
Factory.CodeTransition(),
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"\"")
|
Factory.Code("\"\"")
|
||||||
.AsAddTagHelper("\"\"")));
|
.AsAddTagHelper(
|
||||||
|
"\"\"",
|
||||||
|
string.Empty,
|
||||||
|
legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddTagHelperDirective_Succeeds()
|
public void AddTagHelperDirective_InvalidLookupText_AddsError()
|
||||||
{
|
{
|
||||||
|
var expectedErrors = new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("Foo"),
|
||||||
|
new SourceLocation(14, 0, 14),
|
||||||
|
length: 3)
|
||||||
|
};
|
||||||
|
|
||||||
ParseBlockTest("@addTagHelper Foo",
|
ParseBlockTest("@addTagHelper Foo",
|
||||||
new DirectiveBlock(
|
new DirectiveBlock(
|
||||||
Factory.CodeTransition(),
|
Factory.CodeTransition(),
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo")
|
Factory.Code("Foo")
|
||||||
.AsAddTagHelper("Foo")));
|
.AsAddTagHelper(
|
||||||
|
"Foo",
|
||||||
|
"Foo",
|
||||||
|
legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddTagHelperDirective_WithQuotes_Succeeds()
|
public void AddTagHelperDirective_WithQuotes_InvalidLookupText_AddsError()
|
||||||
{
|
{
|
||||||
|
var expectedErrors = new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("Foo"),
|
||||||
|
new SourceLocation(15, 0, 15),
|
||||||
|
length: 3)
|
||||||
|
};
|
||||||
|
|
||||||
ParseBlockTest("@addTagHelper \"Foo\"",
|
ParseBlockTest("@addTagHelper \"Foo\"",
|
||||||
new DirectiveBlock(
|
new DirectiveBlock(
|
||||||
Factory.CodeTransition(),
|
Factory.CodeTransition(),
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"Foo\"")
|
Factory.Code("\"Foo\"")
|
||||||
.AsAddTagHelper("\"Foo\"")));
|
.AsAddTagHelper(
|
||||||
|
"\"Foo\"",
|
||||||
|
"Foo",
|
||||||
|
legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddTagHelperDirectiveSupportsSpaces()
|
public void AddTagHelperDirective_SupportsSpaces()
|
||||||
{
|
{
|
||||||
ParseBlockTest("@addTagHelper Foo, Bar ",
|
ParseBlockTest("@addTagHelper Foo, Bar ",
|
||||||
new DirectiveBlock(
|
new DirectiveBlock(
|
||||||
|
|
@ -1270,16 +1368,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo, Bar ")
|
Factory.Code("Foo, Bar ")
|
||||||
.AsAddTagHelper("Foo, Bar")));
|
.AsAddTagHelper(
|
||||||
|
"Foo, Bar",
|
||||||
|
"Foo, Bar",
|
||||||
|
"Foo",
|
||||||
|
"Bar")
|
||||||
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddTagHelperDirectiveRequiresValue()
|
public void AddTagHelperDirective_RequiresValue()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedError = new RazorError(
|
var expectedErrors = new[]
|
||||||
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.AddTagHelperKeyword),
|
{
|
||||||
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 12);
|
new RazorError(
|
||||||
|
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.AddTagHelperKeyword),
|
||||||
|
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 12),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText(string.Empty),
|
||||||
|
new SourceLocation(14, 0, 14),
|
||||||
|
length: 1),
|
||||||
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
ParseBlockTest("@addTagHelper ",
|
ParseBlockTest("@addTagHelper ",
|
||||||
|
|
@ -1288,7 +1398,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.EmptyCSharp()
|
Factory.EmptyCSharp()
|
||||||
.AsAddTagHelper(string.Empty, expectedError)
|
.AsAddTagHelper(string.Empty, string.Empty, legacyErrors: expectedErrors)
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1303,7 +1413,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 1),
|
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 1),
|
||||||
new RazorError(
|
new RazorError(
|
||||||
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.AddTagHelperKeyword),
|
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.AddTagHelperKeyword),
|
||||||
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4)
|
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("\"Foo"),
|
||||||
|
new SourceLocation(14, 0, 14),
|
||||||
|
length: 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
|
|
@ -1313,7 +1427,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("\"Foo")
|
Factory.Code("\"Foo")
|
||||||
.AsAddTagHelper("\"Foo", expectedErrors)));
|
.AsAddTagHelper("\"Foo", "\"Foo", legacyErrors: expectedErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1327,7 +1441,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
||||||
new RazorError(
|
new RazorError(
|
||||||
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.AddTagHelperKeyword),
|
LegacyResources.FormatParseError_IncompleteQuotesAroundDirective(SyntaxConstants.CSharp.AddTagHelperKeyword),
|
||||||
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4)
|
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 4),
|
||||||
|
new RazorError(
|
||||||
|
Resources.FormatInvalidTagHelperLookupText("Foo\""),
|
||||||
|
new SourceLocation(14, 0, 14),
|
||||||
|
length: 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
|
|
@ -1337,7 +1455,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||||
.Accepts(AcceptedCharactersInternal.None),
|
.Accepts(AcceptedCharactersInternal.None),
|
||||||
Factory.Code("Foo\"")
|
Factory.Code("Foo\"")
|
||||||
.AsAddTagHelper("Foo\"", expectedErrors)
|
.AsAddTagHelper("Foo\"", "Foo\"", legacyErrors: expectedErrors)
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1611,6 +1729,245 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
Factory.MetaCode("namespace").Accepts(AcceptedCharactersInternal.None)));
|
Factory.MetaCode("namespace").Accepts(AcceptedCharactersInternal.None)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TheoryData InvalidTagHelperPrefixData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var directiveLocation = new SourceLocation(1, 2, 3);
|
||||||
|
|
||||||
|
var invalidTagHelperPrefixValueError =
|
||||||
|
"Invalid tag helper directive '{0}' value. '{1}' is not allowed in prefix '{2}'.";
|
||||||
|
|
||||||
|
return new TheoryData<string, SourceLocation, IEnumerable<RazorError>>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"th ",
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
' ',
|
||||||
|
"th "),
|
||||||
|
directiveLocation,
|
||||||
|
length: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"th\t",
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
'\t',
|
||||||
|
"th\t"),
|
||||||
|
directiveLocation,
|
||||||
|
length: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"th" + Environment.NewLine,
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
Environment.NewLine[0],
|
||||||
|
"th" + Environment.NewLine),
|
||||||
|
directiveLocation,
|
||||||
|
length: 2 + Environment.NewLine.Length)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" th ",
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
' ',
|
||||||
|
" th "),
|
||||||
|
directiveLocation,
|
||||||
|
length: 4)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@",
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
'@',
|
||||||
|
"@"),
|
||||||
|
directiveLocation,
|
||||||
|
length: 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t@h",
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
'@',
|
||||||
|
"t@h"),
|
||||||
|
directiveLocation,
|
||||||
|
length: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"!",
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
'!',
|
||||||
|
"!"),
|
||||||
|
directiveLocation,
|
||||||
|
length: 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"!th",
|
||||||
|
directiveLocation,
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new RazorError(
|
||||||
|
string.Format(
|
||||||
|
invalidTagHelperPrefixValueError,
|
||||||
|
SyntaxConstants.CSharp.TagHelperPrefixKeyword,
|
||||||
|
'!',
|
||||||
|
"!th"),
|
||||||
|
directiveLocation,
|
||||||
|
length: 3)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(InvalidTagHelperPrefixData))]
|
||||||
|
public void ValidateTagHelperPrefix_ValidatesPrefix(
|
||||||
|
string directiveText,
|
||||||
|
SourceLocation directiveLocation,
|
||||||
|
object expectedErrors)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedDiagnostics = ((IEnumerable<RazorError>)expectedErrors).Select(RazorDiagnostic.Create);
|
||||||
|
var source = TestRazorSourceDocument.Create();
|
||||||
|
var options = RazorParserOptions.CreateDefault();
|
||||||
|
var context = new ParserContext(source, options);
|
||||||
|
|
||||||
|
var parser = new CSharpCodeParser(context);
|
||||||
|
var diagnostics = new List<RazorDiagnostic>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
parser.ValidateTagHelperPrefix(directiveText, directiveLocation, diagnostics);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedDiagnostics, diagnostics);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("foo,assemblyName", 4)]
|
||||||
|
[InlineData("foo, assemblyName", 5)]
|
||||||
|
[InlineData(" foo, assemblyName", 8)]
|
||||||
|
[InlineData(" foo , assemblyName", 11)]
|
||||||
|
[InlineData("foo, assemblyName", 8)]
|
||||||
|
[InlineData(" foo , assemblyName ", 14)]
|
||||||
|
public void ParseAddOrRemoveDirective_CalculatesAssemblyLocationInLookupText(string text, int assemblyLocation)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var source = TestRazorSourceDocument.Create();
|
||||||
|
var options = RazorParserOptions.CreateDefault();
|
||||||
|
var context = new ParserContext(source, options);
|
||||||
|
|
||||||
|
var parser = new CSharpCodeParser(context);
|
||||||
|
|
||||||
|
var directive = new CSharpCodeParser.ParsedDirective()
|
||||||
|
{
|
||||||
|
DirectiveText = text,
|
||||||
|
};
|
||||||
|
|
||||||
|
var diagnostics = new List<RazorDiagnostic>();
|
||||||
|
var expected = new SourceLocation(assemblyLocation, 0, assemblyLocation);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = parser.ParseAddOrRemoveDirective(directive, SourceLocation.Zero, diagnostics);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(diagnostics);
|
||||||
|
Assert.Equal("foo", result.TypePattern);
|
||||||
|
Assert.Equal("assemblyName", result.AssemblyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("", 1)]
|
||||||
|
[InlineData("*,", 2)]
|
||||||
|
[InlineData("?,", 2)]
|
||||||
|
[InlineData(",", 1)]
|
||||||
|
[InlineData(",,,", 3)]
|
||||||
|
[InlineData("First, ", 7)]
|
||||||
|
[InlineData("First , ", 8)]
|
||||||
|
[InlineData(" ,Second", 8)]
|
||||||
|
[InlineData(" , Second", 9)]
|
||||||
|
[InlineData("SomeType,", 9)]
|
||||||
|
[InlineData("SomeAssembly", 12)]
|
||||||
|
[InlineData("First,Second,Third", 18)]
|
||||||
|
public void ParseAddOrRemoveDirective_CreatesErrorIfInvalidLookupText_DoesNotThrow(string directiveText, int errorLength)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var source = TestRazorSourceDocument.Create();
|
||||||
|
var options = RazorParserOptions.CreateDefault();
|
||||||
|
var context = new ParserContext(source, options);
|
||||||
|
|
||||||
|
var parser = new CSharpCodeParser(context);
|
||||||
|
|
||||||
|
var expectedErrorMessage = string.Format(
|
||||||
|
"Invalid tag helper directive look up text '{0}'. The correct look up text " +
|
||||||
|
"format is: \"name, assemblyName\".",
|
||||||
|
directiveText);
|
||||||
|
|
||||||
|
var directive = new CSharpCodeParser.ParsedDirective()
|
||||||
|
{
|
||||||
|
DirectiveText = directiveText
|
||||||
|
};
|
||||||
|
|
||||||
|
var diagnostics = new List<RazorDiagnostic>();
|
||||||
|
var expectedError = RazorDiagnostic.Create(
|
||||||
|
new RazorError(
|
||||||
|
expectedErrorMessage,
|
||||||
|
new SourceLocation(1, 2, 3),
|
||||||
|
errorLength));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = parser.ParseAddOrRemoveDirective(directive, new SourceLocation(1, 2, 3), diagnostics);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(directive, result);
|
||||||
|
|
||||||
|
var error = Assert.Single(diagnostics);
|
||||||
|
Assert.Equal(expectedError, error);
|
||||||
|
}
|
||||||
|
|
||||||
internal virtual void ParseCodeBlockTest(
|
internal virtual void ParseCodeBlockTest(
|
||||||
string document,
|
string document,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,14): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,15): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(5,15): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(5,15): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(5,15): Error RZ9999: Invalid tag helper directive look up text '"'. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,17): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,18): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(9,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(9,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(9,18): Error RZ9999: Invalid tag helper directive look up text '"'. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(11,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(11,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,18): Error RZ9999: Invalid tag helper directive 'tagHelperPrefix' value. '"' is not allowed in prefix '"'.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(15,10): Error RZ9999: The 'inherits' directive expects a type name.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(15,10): Error RZ9999: The 'inherits' directive expects a type name.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,1): Error RZ9999: The 'inherits' directive may only occur once per document.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,1): Error RZ9999: The 'inherits' directive may only occur once per document.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,11): Error RZ9999: The 'inherits' directive expects a type name.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,11): Error RZ9999: The 'inherits' directive expects a type name.
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(3,14): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,2): Error RZ9999: Directive 'addTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(4,15): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(5,15): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(5,15): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(5,15): Error RZ9999: Invalid tag helper directive look up text '"'. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(7,17): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,2): Error RZ9999: Directive 'removeTagHelper' must have a value.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(8,18): Error RZ9999: Invalid tag helper directive look up text ''. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(9,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(9,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(9,18): Error RZ9999: Invalid tag helper directive look up text '"'. The correct look up text format is: "name, assemblyName".
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(11,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(11,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,2): Error RZ9999: Directive 'tagHelperPrefix' must have a value.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(12,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,18): Error RZ9999: Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,1): Error RZ2001: The 'tagHelperPrefix' directive may only occur once per document.
|
||||||
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(13,18): Error RZ9999: Invalid tag helper directive 'tagHelperPrefix' value. '"' is not allowed in prefix '"'.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(15,10): Error RZ9999: The 'inherits' directive expects a type name.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(15,10): Error RZ9999: The 'inherits' directive expects a type name.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,1): Error RZ9999: The 'inherits' directive may only occur once per document.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,1): Error RZ9999: The 'inherits' directive may only occur once per document.
|
||||||
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,11): Error RZ9999: The 'inherits' directive expects a type name.
|
TestFiles/IntegrationTests/CodeGenerationIntegrationTest/IncompleteDirectives.cshtml(16,11): Error RZ9999: The 'inherits' directive expects a type name.
|
||||||
|
|
|
||||||
|
|
@ -334,27 +334,37 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
return _self.With(SpanChunkGenerator.Null);
|
return _self.With(SpanChunkGenerator.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpanConstructor AsAddTagHelper(string lookupText, params RazorError[] legacyErrors)
|
public SpanConstructor AsAddTagHelper(
|
||||||
|
string lookupText,
|
||||||
|
string directiveText,
|
||||||
|
string typePattern = null,
|
||||||
|
string assemblyName = null,
|
||||||
|
params RazorError[] legacyErrors)
|
||||||
{
|
{
|
||||||
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
|
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
|
||||||
return _self
|
return _self
|
||||||
.With(new AddTagHelperChunkGenerator(lookupText, diagnostics))
|
.With(new AddTagHelperChunkGenerator(lookupText, directiveText, typePattern, assemblyName, diagnostics))
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpanConstructor AsRemoveTagHelper(string lookupText, params RazorError[] legacyErrors)
|
public SpanConstructor AsRemoveTagHelper(
|
||||||
|
string lookupText,
|
||||||
|
string directiveText,
|
||||||
|
string typePattern = null,
|
||||||
|
string assemblyName = null,
|
||||||
|
params RazorError[] legacyErrors)
|
||||||
{
|
{
|
||||||
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
|
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
|
||||||
return _self
|
return _self
|
||||||
.With(new RemoveTagHelperChunkGenerator(lookupText, diagnostics))
|
.With(new RemoveTagHelperChunkGenerator(lookupText, directiveText, typePattern, assemblyName, diagnostics))
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpanConstructor AsTagHelperPrefixDirective(string prefix, params RazorError[] legacyErrors)
|
public SpanConstructor AsTagHelperPrefixDirective(string prefix, string directiveText, params RazorError[] legacyErrors)
|
||||||
{
|
{
|
||||||
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
|
var diagnostics = legacyErrors.Select(error => RazorDiagnostic.Create(error)).ToList();
|
||||||
return _self
|
return _self
|
||||||
.With(new TagHelperPrefixDirectiveChunkGenerator(prefix, diagnostics))
|
.With(new TagHelperPrefixDirectiveChunkGenerator(prefix, directiveText, diagnostics))
|
||||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
|
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue