public void Execute_ErrorsForRazorBlockFileScopedSinglyOccurringDirectives() { // Arrange var directive = DirectiveDescriptor.CreateRazorBlockDirective("custom", b => b.Usage = DirectiveUsage.FileScopedSinglyOccurring); var phase = new DefaultRazorIntermediateNodeLoweringPhase(); var engine = RazorProjectEngine.CreateEmpty(b => { b.Phases.Add(phase); b.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: false)); b.AddDirective(directive); }); var options = RazorParserOptions.Create(builder => builder.Directives.Add(directive)); var importSource = TestRazorSourceDocument.Create("@custom { }", filePath: "import.cshtml"); var codeDocument = TestRazorCodeDocument.Create("<p>NonDirective</p>"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource, options) }); var expectedDiagnostic = RazorDiagnosticFactory.CreateDirective_BlockDirectiveCannotBeImported("custom"); // Act phase.Execute(codeDocument); // Assert var documentNode = codeDocument.GetDocumentIntermediateNode(); var directives = documentNode.Children.OfType <DirectiveIntermediateNode>(); Assert.Empty(directives); var diagnostic = Assert.Single(documentNode.GetAllDiagnostics()); Assert.Equal(expectedDiagnostic, diagnostic); }
private IEnumerable <RazorDiagnostic> Validate() { if (string.IsNullOrWhiteSpace(Name)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedAttributeNameNullOrWhitespace(); yield return(diagnostic); } else { var name = Name; var isDirectiveAttribute = this.IsDirectiveAttribute(); if (isDirectiveAttribute && name.StartsWith("@", StringComparison.Ordinal)) { name = name.Substring(1); } else if (isDirectiveAttribute) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRequiredDirectiveAttributeName(GetDisplayName(), Name); yield return(diagnostic); } foreach (var character in name) { if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedAttributeName(Name, character); yield return(diagnostic); } } } }
private HashSet <RazorDiagnostic> Validate() { HashSet <RazorDiagnostic> diagnostics = null; if (string.IsNullOrWhiteSpace(Name)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRestrictedChildNullOrWhitespace(_parent.GetDisplayName()); diagnostics ??= new(); diagnostics.Add(diagnostic); } else if (Name != TagHelperMatchingConventions.ElementCatchAllName) { foreach (var character in Name) { if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRestrictedChild(_parent.GetDisplayName(), Name, character); diagnostics ??= new(); diagnostics.Add(diagnostic); } } } return(diagnostics); }
private HashSet <RazorDiagnostic> Validate() { HashSet <RazorDiagnostic> diagnostics = null; if (string.IsNullOrWhiteSpace(Name)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeParameterNullOrWhitespace(_parent.Name); diagnostics ??= new(); diagnostics.Add(diagnostic); } else { foreach (var character in Name) { if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeParameterName( _parent.Name, Name, character); diagnostics ??= new(); diagnostics.Add(diagnostic); } } } return(diagnostics); }
public void Execute_CombinesErrorsOnRewritingErrors() { // Arrange var engine = RazorEngine.Create(builder => { builder.AddTagHelpers(new[] { CreateTagHelperDescriptor( tagName: "form", typeName: "TestFormTagHelper", assemblyName: "TestAssembly"), CreateTagHelperDescriptor( tagName: "input", typeName: "TestInputTagHelper", assemblyName: "TestAssembly"), }); }); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = engine, }; var content = @" @addTagHelper *, TestAssembly <form> <input value='Hello' type='text' />"; var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); var initialError = RazorDiagnostic.Create( new RazorDiagnosticDescriptor("RZ9999", () => "Initial test error", RazorDiagnosticSeverity.Error), new SourceSpan(SourceLocation.Zero, contentLength: 1)); var expectedRewritingError = RazorDiagnosticFactory.CreateParsing_TagHelperFoundMalformedTagHelper( new SourceSpan(new SourceLocation(Environment.NewLine.Length * 2 + 30, 2, 1), contentLength: 4), "form"); var erroredOriginalTree = RazorSyntaxTree.Create(originalTree.Root, originalTree.Source, new[] { initialError }, originalTree.Options); codeDocument.SetSyntaxTree(erroredOriginalTree); // Act phase.Execute(codeDocument); // Assert var outputTree = codeDocument.GetSyntaxTree(); Assert.Empty(originalTree.Diagnostics); Assert.NotSame(erroredOriginalTree, outputTree); Assert.Equal(new[] { initialError, expectedRewritingError }, outputTree.Diagnostics); }
private void ImportDirectives(DocumentIntermediateNode document) { var visitor = new DirectiveVisitor(); visitor.VisitDocument(document); var seenDirectives = new HashSet <DirectiveDescriptor>(); for (var i = visitor.Directives.Count - 1; i >= 0; i--) { var reference = visitor.Directives[i]; var directive = (DirectiveIntermediateNode)reference.Node; var descriptor = directive.Directive; var seenDirective = !seenDirectives.Add(descriptor); if (!directive.IsImported()) { continue; } switch (descriptor.Kind) { case DirectiveKind.SingleLine: if (seenDirective && descriptor.Usage == DirectiveUsage.FileScopedSinglyOccurring) { // This directive has been overridden, it should be removed from the document. break; } continue; case DirectiveKind.RazorBlock: case DirectiveKind.CodeBlock: if (descriptor.Usage == DirectiveUsage.FileScopedSinglyOccurring) { // A block directive cannot be imported. document.Diagnostics.Add( RazorDiagnosticFactory.CreateDirective_BlockDirectiveCannotBeImported(descriptor.Directive)); } break; default: throw new InvalidOperationException(Resources.FormatUnexpectedDirectiveKind(typeof(DirectiveKind).FullName)); } // Overridden and invalid imported directives make it to here. They should be removed from the document. reference.Remove(); } }
private HashSet <RazorDiagnostic> Validate() { HashSet <RazorDiagnostic> diagnostics = null; if (string.IsNullOrWhiteSpace(TagName)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedTagNameNullOrWhitespace(); diagnostics ??= new(); diagnostics.Add(diagnostic); } else if (TagName != TagHelperMatchingConventions.ElementCatchAllName) { foreach (var character in TagName) { if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedTagName(TagName, character); diagnostics ??= new(); diagnostics.Add(diagnostic); } } } if (ParentTag != null) { if (string.IsNullOrWhiteSpace(ParentTag)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedParentTagNameNullOrWhitespace(); diagnostics ??= new(); diagnostics.Add(diagnostic); } else { foreach (var character in ParentTag) { if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedParentTagName(ParentTag, character); diagnostics ??= new(); diagnostics.Add(diagnostic); } } } } return(diagnostics); }
public override SyntaxNode Visit(SyntaxNode node) { try { return(base.Visit(node)); } catch (InsufficientExecutionStackException) { // We're very close to reaching the stack limit. Let's not go any deeper. // It's okay to not show nested section errors in deeply nested cases instead of crashing. _diagnostics.Add(RazorDiagnosticFactory.CreateRewriter_InsufficientStack(SourceSpan.Undefined)); return(node); } }
public override void VisitDirectiveBlock(DirectiveChunkGenerator chunkGenerator, Block block) { if (_nestedLevel > 0) { var directiveStart = block.Children.First(child => !child.IsBlock && ((Span)child).Kind == SpanKindInternal.Transition).Start; var errorLength = /* @ */ 1 + SectionDirective.Directive.Directive.Length; var error = RazorDiagnosticFactory.CreateParsing_SectionsCannotBeNested(new SourceSpan(directiveStart, errorLength)); chunkGenerator.Diagnostics.Add(error); } _nestedLevel++; VisitDefault(block); _nestedLevel--; }
public override SyntaxNode VisitRazorDirective(RazorDirectiveSyntax node) { if (_nestedLevel > 0) { var directiveStart = node.Transition.GetSourceLocation(_syntaxTree.Source); var errorLength = /* @ */ 1 + SectionDirective.Directive.Directive.Length; var error = RazorDiagnosticFactory.CreateParsing_SectionsCannotBeNested(new SourceSpan(directiveStart, errorLength)); node = node.AppendDiagnostic(error); } _nestedLevel++; var result = base.VisitRazorDirective(node); _nestedLevel--; return(result); }
private IEnumerable <RazorDiagnostic> Validate() { if (string.IsNullOrWhiteSpace(TagName)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedTagNameNullOrWhitespace(); yield return(diagnostic); } else if (TagName != TagHelperMatchingConventions.ElementCatchAllName) { foreach (var character in TagName) { if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedTagName(TagName, character); yield return(diagnostic); } } } if (ParentTag != null) { if (string.IsNullOrWhiteSpace(ParentTag)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedParentTagNameNullOrWhitespace(); yield return(diagnostic); } else { foreach (var character in ParentTag) { if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedParentTagName(ParentTag, character); yield return(diagnostic); } } } } }
private HashSet <RazorDiagnostic> Validate() { HashSet <RazorDiagnostic> diagnostics = null; if (string.IsNullOrWhiteSpace(Name)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedAttributeNameNullOrWhitespace(); diagnostics ??= new(); diagnostics.Add(diagnostic); } else { var name = new StringSegment(Name); var isDirectiveAttribute = this.IsDirectiveAttribute(); if (isDirectiveAttribute && name.StartsWith("@", StringComparison.Ordinal)) { name = name.Subsegment(1); } else if (isDirectiveAttribute) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRequiredDirectiveAttributeName(GetDisplayName(), Name); diagnostics ??= new(); diagnostics.Add(diagnostic); } for (var i = 0; i < name.Length; i++) { var character = name[i]; if (char.IsWhiteSpace(character) || HtmlConventions.IsInvalidNonWhitespaceHtmlCharacters(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedAttributeName(Name, character); diagnostics ??= new(); diagnostics.Add(diagnostic); } } } return(diagnostics); }
private IEnumerable <RazorDiagnostic> Validate() { if (string.IsNullOrWhiteSpace(Name)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedAttributeNameNullOrWhitespace(); yield return(diagnostic); } else { foreach (var character in Name) { if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidTargetedAttributeName(Name, character); yield return(diagnostic); } } } }
private IEnumerable <RazorDiagnostic> Validate() { if (string.IsNullOrWhiteSpace(Name)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRestrictedChildNullOrWhitespace(_parent.GetDisplayName()); yield return(diagnostic); } else if (Name != TagHelperMatchingConventions.ElementCatchAllName) { foreach (var character in Name) { if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidRestrictedChild(_parent.GetDisplayName(), Name, character); yield return(diagnostic); } } } }
public void Execute_CanHandleSingleLengthTagHelperPrefix() { // Arrange var engine = RazorEngine.Create(builder => { builder.AddTagHelpers(new TagHelperDescriptor[0]); }); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = engine, }; var expectedDiagnostics = new[] { RazorDiagnosticFactory.CreateParsing_UnterminatedStringLiteral( new SourceSpan(new SourceLocation(17 + Environment.NewLine.Length, 1, 17), contentLength: 1)), RazorDiagnosticFactory.CreateParsing_InvalidTagHelperPrefixValue( new SourceSpan(new SourceLocation(17 + Environment.NewLine.Length, 1, 17), contentLength: 1), "tagHelperPrefix", '\"', "\""), }; var content = @" @tagHelperPrefix """; var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); // Act phase.Execute(codeDocument); // Assert var rewrittenTree = codeDocument.GetSyntaxTree(); var directiveValue = rewrittenTree.Root.Children.OfType <Block>().First().Children.Last() as Span; var chunkGenerator = Assert.IsType <TagHelperPrefixDirectiveChunkGenerator>(directiveValue.ChunkGenerator); Assert.Equal(expectedDiagnostics, chunkGenerator.Diagnostics); }
public void Execute_CanHandleSingleLengthRemoveTagHelperDirective() { // Arrange var projectEngine = RazorProjectEngine.Create(builder => { builder.AddTagHelpers(new TagHelperDescriptor[0]); }); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = projectEngine.Engine, }; var expectedDiagnostics = new[] { RazorDiagnosticFactory.CreateParsing_UnterminatedStringLiteral( new SourceSpan(new SourceLocation(17 + Environment.NewLine.Length, 1, 17), contentLength: 1)), RazorDiagnosticFactory.CreateParsing_InvalidTagHelperLookupText( new SourceSpan(new SourceLocation(17 + Environment.NewLine.Length, 1, 17), contentLength: 1), "\"") }; var content = @" @removeTagHelper """; var sourceDocument = TestRazorSourceDocument.Create(content, filePath: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); // Act phase.Execute(codeDocument); // Assert var rewrittenTree = codeDocument.GetSyntaxTree(); var erroredNode = rewrittenTree.Root.DescendantNodes().First(n => n.GetSpanContext()?.ChunkGenerator is RemoveTagHelperChunkGenerator); var chunkGenerator = Assert.IsType <RemoveTagHelperChunkGenerator>(erroredNode.GetSpanContext().ChunkGenerator); Assert.Equal(expectedDiagnostics, chunkGenerator.Diagnostics); }
public override SyntaxNode VisitRazorDirective(RazorDirectiveSyntax node) { if (node.DirectiveDescriptor?.Directive != SectionDirective.Directive.Directive) { // We only want to track the nesting of section directives. return(base.VisitRazorDirective(node)); } _nestedLevel++; var result = (RazorDirectiveSyntax)base.VisitRazorDirective(node); if (_nestedLevel > 1) { var directiveStart = node.Transition.GetSourceLocation(_syntaxTree.Source); var errorLength = /* @ */ 1 + SectionDirective.Directive.Directive.Length; var error = RazorDiagnosticFactory.CreateParsing_SectionsCannotBeNested(new SourceSpan(directiveStart, errorLength)); result = result.AppendDiagnostic(error); } _nestedLevel--; return(result); }
private IEnumerable <RazorDiagnostic> Validate() { // data-* attributes are explicitly not implemented by user agents and are not intended for use on // the server; therefore it's invalid for TagHelpers to bind to them. const string DataDashPrefix = "data-"; if (string.IsNullOrWhiteSpace(Name)) { if (IndexerAttributeNamePrefix == null) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeNullOrWhitespace( _parent.GetDisplayName(), GetDisplayName()); yield return(diagnostic); } } else { if (Name.StartsWith(DataDashPrefix, StringComparison.OrdinalIgnoreCase)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeNameStartsWith( _parent.GetDisplayName(), GetDisplayName(), Name); yield return(diagnostic); } foreach (var character in Name) { if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeName( _parent.GetDisplayName(), GetDisplayName(), Name, character); yield return(diagnostic); } } } if (IndexerAttributeNamePrefix != null) { if (IndexerAttributeNamePrefix.StartsWith(DataDashPrefix, StringComparison.OrdinalIgnoreCase)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributePrefixStartsWith( _parent.GetDisplayName(), GetDisplayName(), IndexerAttributeNamePrefix); yield return(diagnostic); } else if (IndexerAttributeNamePrefix.Length > 0 && string.IsNullOrWhiteSpace(IndexerAttributeNamePrefix)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeNullOrWhitespace( _parent.GetDisplayName(), GetDisplayName()); yield return(diagnostic); } else { foreach (var character in IndexerAttributeNamePrefix) { if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributePrefix( _parent.GetDisplayName(), GetDisplayName(), IndexerAttributeNamePrefix, character); yield return(diagnostic); } } } } }
private IEnumerable <RazorDiagnostic> Validate() { // data-* attributes are explicitly not implemented by user agents and are not intended for use on // the server; therefore it's invalid for TagHelpers to bind to them. const string DataDashPrefix = "data-"; var isDirectiveAttribute = this.IsDirectiveAttribute(); if (string.IsNullOrWhiteSpace(Name)) { if (IndexerAttributeNamePrefix == null) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeNullOrWhitespace( _parent.GetDisplayName(), GetDisplayName()); yield return(diagnostic); } } else { if (Name.StartsWith(DataDashPrefix, StringComparison.OrdinalIgnoreCase)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeNameStartsWith( _parent.GetDisplayName(), GetDisplayName(), Name); yield return(diagnostic); } StringSegment name = Name; if (isDirectiveAttribute && name.StartsWith("@", StringComparison.Ordinal)) { name = name.Subsegment(1); } else if (isDirectiveAttribute) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundDirectiveAttributeName( _parent.GetDisplayName(), GetDisplayName(), Name); yield return(diagnostic); } for (var i = 0; i < name.Length; i++) { var character = name[i]; if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeName( _parent.GetDisplayName(), GetDisplayName(), name.Value, character); yield return(diagnostic); } } } if (IndexerAttributeNamePrefix != null) { if (IndexerAttributeNamePrefix.StartsWith(DataDashPrefix, StringComparison.OrdinalIgnoreCase)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributePrefixStartsWith( _parent.GetDisplayName(), GetDisplayName(), IndexerAttributeNamePrefix); yield return(diagnostic); } else if (IndexerAttributeNamePrefix.Length > 0 && string.IsNullOrWhiteSpace(IndexerAttributeNamePrefix)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributeNullOrWhitespace( _parent.GetDisplayName(), GetDisplayName()); yield return(diagnostic); } else { StringSegment indexerPrefix = IndexerAttributeNamePrefix; if (isDirectiveAttribute && indexerPrefix.StartsWith("@", StringComparison.Ordinal)) { indexerPrefix = indexerPrefix.Subsegment(1); } else if (isDirectiveAttribute) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundDirectiveAttributePrefix( _parent.GetDisplayName(), GetDisplayName(), indexerPrefix.Value); yield return(diagnostic); } for (var i = 0; i < indexerPrefix.Length; i++) { var character = indexerPrefix[i]; if (char.IsWhiteSpace(character) || HtmlConventions.InvalidNonWhitespaceHtmlCharacters.Contains(character)) { var diagnostic = RazorDiagnosticFactory.CreateTagHelper_InvalidBoundAttributePrefix( _parent.GetDisplayName(), GetDisplayName(), indexerPrefix.Value, character); yield return(diagnostic); } } } } }