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
|
||||
{
|
||||
private static HashSet<char> InvalidNonWhitespaceNameCharacters = new HashSet<char>(new[]
|
||||
{
|
||||
'@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*'
|
||||
});
|
||||
|
||||
protected override void ExecuteCore(RazorCodeDocument codeDocument)
|
||||
{
|
||||
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
|
||||
// should be processed.
|
||||
var visitor = new DirectiveVisitor();
|
||||
var descriptors = feature.GetDescriptors();
|
||||
var visitor = new DirectiveVisitor(descriptors);
|
||||
var imports = codeDocument.GetImportSyntaxTrees();
|
||||
if (imports != null)
|
||||
{
|
||||
|
|
@ -44,14 +40,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
visitor.VisitBlock(syntaxTree.Root);
|
||||
|
||||
var errorList = new List<RazorDiagnostic>();
|
||||
var descriptors = feature.GetDescriptors();
|
||||
|
||||
var directives = visitor.Directives;
|
||||
descriptors = ProcessDirectives(directives, descriptors);
|
||||
|
||||
var tagHelperPrefix = ProcessTagHelperPrefix(directives, codeDocument);
|
||||
var root = syntaxTree.Root;
|
||||
var tagHelperPrefix = visitor.TagHelperPrefix;
|
||||
descriptors = visitor.Matches.ToArray();
|
||||
|
||||
var context = TagHelperDocumentContext.Create(tagHelperPrefix, descriptors);
|
||||
codeDocument.SetTagHelperContext(context);
|
||||
|
|
@ -64,9 +54,11 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
var errorSink = new ErrorSink();
|
||||
var rewriter = new TagHelperParseTreeRewriter(tagHelperPrefix, descriptors);
|
||||
var root = syntaxTree.Root;
|
||||
root = rewriter.Rewrite(root, errorSink);
|
||||
|
||||
// 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(descriptors.SelectMany(d => d.GetAllDiagnostics()));
|
||||
|
|
@ -77,205 +69,27 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
codeDocument.SetSyntaxTree(newSyntaxTree);
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal string ProcessTagHelperPrefix(List<TagHelperDirectiveDescriptor> directives, RazorCodeDocument codeDocument)
|
||||
private static bool MatchesDirective(TagHelperDescriptor descriptor, string typePattern, string assemblyName)
|
||||
{
|
||||
// We only support a single prefix directive.
|
||||
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))
|
||||
if (!string.Equals(descriptor.AssemblyName, assemblyName, StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lookupInfo.TypePattern.EndsWith("*", StringComparison.Ordinal))
|
||||
if (typePattern.EndsWith("*", StringComparison.Ordinal))
|
||||
{
|
||||
if (lookupInfo.TypePattern.Length == 1)
|
||||
if (typePattern.Length == 1)
|
||||
{
|
||||
// TypePattern is "*".
|
||||
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 string.Equals(descriptor.Name, lookupInfo.TypePattern, StringComparison.Ordinal);
|
||||
return string.Equals(descriptor.Name, typePattern, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static int GetErrorLength(string directiveText)
|
||||
|
|
@ -295,81 +109,89 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
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 List<TagHelperDirectiveDescriptor> Directives { get; } = new List<TagHelperDirectiveDescriptor>();
|
||||
public HashSet<TagHelperDescriptor> Matches { get; } = new HashSet<TagHelperDescriptor>();
|
||||
|
||||
public override void VisitAddTagHelperSpan(AddTagHelperChunkGenerator chunkGenerator, Span span)
|
||||
{
|
||||
var directive = CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.AddTagHelper, chunkGenerator.Diagnostics);
|
||||
Directives.Add(directive);
|
||||
if (chunkGenerator.AssemblyName == null)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
var directive = CreateDirective(span, chunkGenerator.LookupText, TagHelperDirectiveType.RemoveTagHelper, chunkGenerator.Diagnostics);
|
||||
Directives.Add(directive);
|
||||
if (chunkGenerator.AssemblyName == null)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
var directive = CreateDirective(span, chunkGenerator.Prefix, TagHelperDirectiveType.TagHelperPrefix, chunkGenerator.Diagnostics);
|
||||
Directives.Add(directive);
|
||||
if (!string.IsNullOrEmpty(chunkGenerator.DirectiveText))
|
||||
{
|
||||
// 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(
|
||||
Span span,
|
||||
string directiveText,
|
||||
TagHelperDirectiveType directiveType,
|
||||
List<RazorDiagnostic> diagnostics)
|
||||
private bool AssemblyContainsTagHelpers(string assemblyName, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
directiveText = directiveText.Trim();
|
||||
if (directiveText.Length >= 2 &&
|
||||
directiveText.StartsWith("\"", StringComparison.Ordinal) &&
|
||||
directiveText.EndsWith("\"", StringComparison.Ordinal))
|
||||
for (var i = 0; i < tagHelpers.Count; i++)
|
||||
{
|
||||
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
|
||||
// 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;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,14 +10,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
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;
|
||||
DirectiveText = directiveText;
|
||||
AssemblyName = assemblyName;
|
||||
TypePattern = typePattern;
|
||||
Diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
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 override void Accept(ParserVisitor visitor, Span span)
|
||||
|
|
@ -31,7 +45,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var other = obj as AddTagHelperChunkGenerator;
|
||||
return base.Equals(other) &&
|
||||
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 />
|
||||
|
|
@ -40,6 +57,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(base.GetHashCode());
|
||||
combiner.Add(LookupText, StringComparer.Ordinal);
|
||||
combiner.Add(DirectiveText, StringComparer.Ordinal);
|
||||
combiner.Add(TypePattern, StringComparer.Ordinal);
|
||||
combiner.Add(AssemblyName, StringComparer.Ordinal);
|
||||
|
||||
return combiner.CombinedHash;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
internal class CSharpCodeParser : TokenizerBackedParser<CSharpTokenizer, CSharpSymbol, CSharpSymbolType>
|
||||
{
|
||||
private static HashSet<char> InvalidNonWhitespaceNameCharacters = new HashSet<char>(new[]
|
||||
{
|
||||
'@', '!', '<', '/', '?', '[', '>', ']', '=', '"', '\'', '*'
|
||||
});
|
||||
|
||||
private static readonly Func<CSharpSymbol, bool> IsValidStatementSpacingSymbol =
|
||||
IsSpacingToken(includeNewLines: true, includeComments: true);
|
||||
|
||||
|
|
@ -1905,22 +1910,158 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
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()
|
||||
{
|
||||
TagHelperDirective(
|
||||
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()
|
||||
{
|
||||
TagHelperDirective(
|
||||
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")]
|
||||
|
|
@ -2093,5 +2234,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
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
|
||||
{
|
||||
public RemoveTagHelperChunkGenerator(string lookupText, List<RazorDiagnostic> diagnostics)
|
||||
public RemoveTagHelperChunkGenerator(
|
||||
string lookupText,
|
||||
string directiveText,
|
||||
string typePattern,
|
||||
string assemblyName,
|
||||
List<RazorDiagnostic> diagnostics)
|
||||
{
|
||||
LookupText = lookupText;
|
||||
DirectiveText = directiveText;
|
||||
TypePattern = typePattern;
|
||||
AssemblyName = assemblyName;
|
||||
Diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
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 override void Accept(ParserVisitor visitor, Span span)
|
||||
|
|
@ -31,7 +45,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var other = obj as RemoveTagHelperChunkGenerator;
|
||||
return base.Equals(other) &&
|
||||
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 />
|
||||
|
|
@ -40,6 +57,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(base.GetHashCode());
|
||||
combiner.Add(LookupText, StringComparer.Ordinal);
|
||||
combiner.Add(DirectiveText, StringComparer.Ordinal);
|
||||
combiner.Add(TypePattern, StringComparer.Ordinal);
|
||||
combiner.Add(AssemblyName, StringComparer.Ordinal);
|
||||
|
||||
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
|
||||
{
|
||||
public TagHelperPrefixDirectiveChunkGenerator(string prefix, List<RazorDiagnostic> diagnostics)
|
||||
public TagHelperPrefixDirectiveChunkGenerator(string prefix, string directiveText, List<RazorDiagnostic> diagnostics)
|
||||
{
|
||||
Prefix = prefix;
|
||||
DirectiveText = directiveText;
|
||||
Diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
public string Prefix { get; }
|
||||
|
||||
public string DirectiveText { get; }
|
||||
|
||||
public List<RazorDiagnostic> Diagnostics { get; }
|
||||
|
||||
public override void Accept(ParserVisitor visitor, Span span)
|
||||
|
|
@ -31,7 +34,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var other = obj as TagHelperPrefixDirectiveChunkGenerator;
|
||||
return base.Equals(other) &&
|
||||
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 />
|
||||
|
|
@ -40,6 +44,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(base.GetHashCode());
|
||||
combiner.Add(Prefix, StringComparer.Ordinal);
|
||||
combiner.Add(DirectiveText, StringComparer.Ordinal);
|
||||
|
||||
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 + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"*, Foo\"")
|
||||
.AsAddTagHelper("\"*, Foo\"")));
|
||||
.AsAddTagHelper(
|
||||
"\"*, Foo\"",
|
||||
"*, Foo",
|
||||
"*",
|
||||
"Foo")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -370,7 +374,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"*, Foo\"")
|
||||
.AsAddTagHelper(
|
||||
"\"*, Foo\"",
|
||||
"\"*, Foo\"",
|
||||
"*, Foo",
|
||||
"*",
|
||||
"Foo",
|
||||
new RazorError(Resources.FormatDirectiveMustAppearAtStartOfLine("addTagHelper"), new SourceLocation(4, 0, 4), 12))),
|
||||
Factory.Code(Environment.NewLine).AsStatement(),
|
||||
Factory.MetaCode("}").Accepts(AcceptedCharactersInternal.None)));
|
||||
|
|
@ -1009,7 +1016,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"\"")
|
||||
.AsTagHelperPrefixDirective("\"\"")));
|
||||
.AsTagHelperPrefixDirective("\"\"", string.Empty)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1022,7 +1029,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo")
|
||||
.AsTagHelperPrefixDirective("Foo")));
|
||||
.AsTagHelperPrefixDirective("Foo", "Foo")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1035,7 +1042,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"Foo\"")
|
||||
.AsTagHelperPrefixDirective("\"Foo\"")));
|
||||
.AsTagHelperPrefixDirective("\"Foo\"", "Foo")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1054,7 +1061,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsTagHelperPrefixDirective(string.Empty, expectedError)
|
||||
.AsTagHelperPrefixDirective(string.Empty, string.Empty, expectedError)
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
|
|
@ -1069,6 +1076,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
||||
new RazorError(
|
||||
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)
|
||||
};
|
||||
|
||||
|
|
@ -1080,7 +1090,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"Foo")
|
||||
.AsTagHelperPrefixDirective("\"Foo", expectedErrors)));
|
||||
.AsTagHelperPrefixDirective("\"Foo", "\"Foo", expectedErrors)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1094,6 +1104,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
absoluteIndex: 23, lineIndex: 0, columnIndex: 23, length: 1),
|
||||
new RazorError(
|
||||
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)
|
||||
};
|
||||
|
||||
|
|
@ -1105,43 +1118,76 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
.MetaCode(SyntaxConstants.CSharp.TagHelperPrefixKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo \"")
|
||||
.AsTagHelperPrefixDirective("Foo \"", expectedErrors)));
|
||||
.AsTagHelperPrefixDirective("Foo \"", "Foo \"", expectedErrors)));
|
||||
}
|
||||
|
||||
[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 \"\"",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"\"")
|
||||
.AsRemoveTagHelper("\"\"")));
|
||||
.AsRemoveTagHelper(
|
||||
"\"\"",
|
||||
string.Empty,
|
||||
legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[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",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo")
|
||||
.AsRemoveTagHelper("Foo")));
|
||||
.AsRemoveTagHelper(
|
||||
"Foo",
|
||||
"Foo",
|
||||
legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[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\"",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"Foo\"")
|
||||
.AsRemoveTagHelper("\"Foo\"")));
|
||||
.AsRemoveTagHelper(
|
||||
"\"Foo\"",
|
||||
"Foo",
|
||||
legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1153,7 +1199,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo, Bar ")
|
||||
.AsRemoveTagHelper("Foo, Bar")
|
||||
.AsRemoveTagHelper(
|
||||
"Foo, Bar",
|
||||
"Foo, Bar",
|
||||
"Foo",
|
||||
"Bar")
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
|
|
@ -1161,9 +1211,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
public void RemoveTagHelperDirective_RequiresValue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedError = new RazorError(
|
||||
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.RemoveTagHelperKeyword),
|
||||
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 15);
|
||||
var expectedErrors = new[]
|
||||
{
|
||||
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
|
||||
ParseBlockTest("@removeTagHelper ",
|
||||
|
|
@ -1172,7 +1229,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsRemoveTagHelper(string.Empty, expectedError)
|
||||
.AsRemoveTagHelper(string.Empty, string.Empty, legacyErrors: expectedErrors)
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
|
|
@ -1187,7 +1244,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
||||
new RazorError(
|
||||
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
|
||||
|
|
@ -1197,7 +1258,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"Foo")
|
||||
.AsRemoveTagHelper("\"Foo", expectedErrors)));
|
||||
.AsRemoveTagHelper("\"Foo", "\"Foo", legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1211,7 +1272,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
absoluteIndex: 20, lineIndex: 0, columnIndex: 20, length: 1),
|
||||
new RazorError(
|
||||
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
|
||||
|
|
@ -1221,48 +1286,81 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.RemoveTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo\"")
|
||||
.AsRemoveTagHelper("Foo\"", expectedErrors)
|
||||
.AsRemoveTagHelper("Foo\"", "Foo\"", legacyErrors: expectedErrors)
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[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 \"\"",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"\"")
|
||||
.AsAddTagHelper("\"\"")));
|
||||
.AsAddTagHelper(
|
||||
"\"\"",
|
||||
string.Empty,
|
||||
legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[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",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo")
|
||||
.AsAddTagHelper("Foo")));
|
||||
.AsAddTagHelper(
|
||||
"Foo",
|
||||
"Foo",
|
||||
legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[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\"",
|
||||
new DirectiveBlock(
|
||||
Factory.CodeTransition(),
|
||||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"Foo\"")
|
||||
.AsAddTagHelper("\"Foo\"")));
|
||||
.AsAddTagHelper(
|
||||
"\"Foo\"",
|
||||
"Foo",
|
||||
legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddTagHelperDirectiveSupportsSpaces()
|
||||
public void AddTagHelperDirective_SupportsSpaces()
|
||||
{
|
||||
ParseBlockTest("@addTagHelper Foo, Bar ",
|
||||
new DirectiveBlock(
|
||||
|
|
@ -1270,16 +1368,28 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo, Bar ")
|
||||
.AsAddTagHelper("Foo, Bar")));
|
||||
.AsAddTagHelper(
|
||||
"Foo, Bar",
|
||||
"Foo, Bar",
|
||||
"Foo",
|
||||
"Bar")
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddTagHelperDirectiveRequiresValue()
|
||||
public void AddTagHelperDirective_RequiresValue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedError = new RazorError(
|
||||
LegacyResources.FormatParseError_DirectiveMustHaveValue(SyntaxConstants.CSharp.AddTagHelperKeyword),
|
||||
absoluteIndex: 1, lineIndex: 0, columnIndex: 1, length: 12);
|
||||
var expectedErrors = new[]
|
||||
{
|
||||
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
|
||||
ParseBlockTest("@addTagHelper ",
|
||||
|
|
@ -1288,7 +1398,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.EmptyCSharp()
|
||||
.AsAddTagHelper(string.Empty, expectedError)
|
||||
.AsAddTagHelper(string.Empty, string.Empty, legacyErrors: expectedErrors)
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
|
|
@ -1303,7 +1413,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
absoluteIndex: 14, lineIndex: 0, columnIndex: 14, length: 1),
|
||||
new RazorError(
|
||||
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
|
||||
|
|
@ -1313,7 +1427,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("\"Foo")
|
||||
.AsAddTagHelper("\"Foo", expectedErrors)));
|
||||
.AsAddTagHelper("\"Foo", "\"Foo", legacyErrors: expectedErrors)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1327,7 +1441,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
absoluteIndex: 17, lineIndex: 0, columnIndex: 17, length: 1),
|
||||
new RazorError(
|
||||
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
|
||||
|
|
@ -1337,7 +1455,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Factory.MetaCode(SyntaxConstants.CSharp.AddTagHelperKeyword + " ")
|
||||
.Accepts(AcceptedCharactersInternal.None),
|
||||
Factory.Code("Foo\"")
|
||||
.AsAddTagHelper("Foo\"", expectedErrors)
|
||||
.AsAddTagHelper("Foo\"", "Foo\"", legacyErrors: expectedErrors)
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline)));
|
||||
}
|
||||
|
||||
|
|
@ -1611,6 +1729,245 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
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(
|
||||
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,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,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: 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,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,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: 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(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(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,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(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.
|
||||
|
|
|
|||
|
|
@ -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,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,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: 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,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,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: 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(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(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,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(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.
|
||||
|
|
|
|||
|
|
@ -334,27 +334,37 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
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();
|
||||
return _self
|
||||
.With(new AddTagHelperChunkGenerator(lookupText, diagnostics))
|
||||
.With(new AddTagHelperChunkGenerator(lookupText, directiveText, typePattern, assemblyName, diagnostics))
|
||||
.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();
|
||||
return _self
|
||||
.With(new RemoveTagHelperChunkGenerator(lookupText, diagnostics))
|
||||
.With(new RemoveTagHelperChunkGenerator(lookupText, directiveText, typePattern, assemblyName, diagnostics))
|
||||
.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();
|
||||
return _self
|
||||
.With(new TagHelperPrefixDirectiveChunkGenerator(prefix, diagnostics))
|
||||
.With(new TagHelperPrefixDirectiveChunkGenerator(prefix, directiveText, diagnostics))
|
||||
.Accepts(AcceptedCharactersInternal.AnyExceptNewline);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue