public void Execute_DirectiveWithQuotes_RewritesTagHelpers_TagHelperMatchesElementTwice() { // Arrange var descriptor = CreateTagHelperDescriptor( tagName: "form", typeName: "TestFormTagHelper", assemblyName: "TestAssembly", ruleBuilders: new Action <TagMatchingRuleDescriptorBuilder>[] { ruleBuilder => ruleBuilder .RequireAttributeDescriptor(attribute => attribute .Name("a") .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.FullMatch)), ruleBuilder => ruleBuilder .RequireAttributeDescriptor(attribute => attribute .Name("b") .NameComparisonMode(RequiredAttributeDescriptor.NameComparisonMode.FullMatch)), }); var engine = RazorEngine.Create(builder => { builder.AddTagHelpers(new[] { descriptor }); }); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = engine, }; var content = @" @addTagHelper ""*, TestAssembly"" <form a=""hi"" b=""there""> </form>"; var sourceDocument = TestRazorSourceDocument.Create(content); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); // Act phase.Execute(codeDocument); // Assert var rewrittenTree = codeDocument.GetSyntaxTree(); Assert.Empty(rewrittenTree.Diagnostics); Assert.Equal(3, rewrittenTree.Root.Children.Count); var formTagHelper = Assert.IsType <TagHelperBlock>(rewrittenTree.Root.Children[2]); Assert.Equal("form", formTagHelper.TagName); Assert.Equal(2, formTagHelper.Binding.GetBoundRules(descriptor).Count()); }
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, fileName: null); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); var initialError = RazorDiagnostic.Create(new RazorError("Initial test error", SourceLocation.Zero, length: 1)); var expectedRewritingError = RazorDiagnostic.Create( new RazorError( LegacyResources.FormatTagHelpersParseTreeRewriter_FoundMalformedTagHelper("form"), new SourceLocation(Environment.NewLine.Length * 2 + 30, 2, 1), length: 4)); 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); }
public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree) { if (FileKinds.IsComponent(codeDocument.GetFileKind())) { // Nothing to do here. return(syntaxTree); } var sectionVerifier = new NestedSectionVerifier(syntaxTree); return(sectionVerifier.Verify()); }
public static void Verify(RazorSyntaxTree syntaxTree, bool ensureFullFidelity = true) { var verifier = new Verifier(syntaxTree.Source); verifier.Visit(syntaxTree.Root); if (ensureFullFidelity) { var syntaxTreeString = syntaxTree.Root.ToFullString(); var builder = new StringBuilder(syntaxTree.Source.Length); for (var i = 0; i < syntaxTree.Source.Length; i++) { builder.Append(syntaxTree.Source[i]); } var sourceString = builder.ToString(); // Make sure the syntax tree contains all of the text in the document. Assert.Equal(sourceString, syntaxTreeString); // Ensure all source is locatable for (var i = 0; i < syntaxTree.Source.Length; i++) { var span = new SourceSpan(i, 0); var location = new SourceChange(span, string.Empty); var owner = syntaxTree.Root.LocateOwner(location); if (owner is null) { var snippetStartIndex = Math.Max(0, i - 10); var snippetStartLength = i - snippetStartIndex; var snippetStart = new char[snippetStartLength]; syntaxTree.Source.CopyTo(snippetStartIndex, snippetStart, 0, snippetStartLength); var snippetEndIndex = Math.Min(syntaxTree.Source.Length - 1, i + 10); var snippetEndLength = snippetEndIndex - i; var snippetEnd = new char[snippetEndLength]; syntaxTree.Source.CopyTo(i, snippetEnd, 0, snippetEndLength); var snippet = new char[snippetStart.Length + snippetEnd.Length + 1]; snippetStart.CopyTo(snippet, 0); snippet[snippetStart.Length] = '|'; snippetEnd.CopyTo(snippet, snippetStart.Length + 1); var snippetString = new string(snippet); throw new XunitException( $@"Could not locate Syntax Node owner at position '{i}': {snippetString}"); } } } }
public void SetRazorSyntaxTree_SetsSyntaxTree() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); var expected = RazorSyntaxTree.Parse(codeDocument.Source); // Act codeDocument.SetSyntaxTree(expected); // Assert Assert.Same(expected, codeDocument.Items[typeof(RazorSyntaxTree)]); }
public void Execute_TagHelpersFromCodeDocumentAndFeature_PrefersCodeDocument() { // Arrange var featureTagHelpers = new[] { CreateTagHelperDescriptor( tagName: "input", typeName: "TestInputTagHelper", assemblyName: "TestAssembly"), }; var projectEngine = RazorProjectEngine.Create(builder => builder.AddTagHelpers(featureTagHelpers)); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = projectEngine.Engine, }; var sourceDocument = CreateTestSourceDocument(); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); var codeDocumentTagHelpers = new[] { CreateTagHelperDescriptor( tagName: "form", typeName: "TestFormTagHelper", assemblyName: "TestAssembly"), }; codeDocument.SetTagHelpers(codeDocumentTagHelpers); // Act phase.Execute(codeDocument); // Assert var rewrittenTree = codeDocument.GetSyntaxTree(); Assert.Empty(rewrittenTree.Diagnostics); Assert.Equal(3, rewrittenTree.Root.Children.Count); var formTagHelper = Assert.IsType <TagHelperBlock>(rewrittenTree.Root.Children[2]); Assert.Equal("form", formTagHelper.TagName); Assert.Collection( formTagHelper.Children, node => Assert.IsNotType <TagHelperBlock>(node), node => Assert.IsNotType <TagHelperBlock>(node), node => Assert.IsNotType <TagHelperBlock>(node)); }
public void GetRazorSyntaxTree_ReturnsSyntaxTree() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); var expected = RazorSyntaxTree.Parse(codeDocument.Source); codeDocument.Items[typeof(RazorSyntaxTree)] = expected; // Act var actual = codeDocument.GetSyntaxTree(); // Assert Assert.Same(expected, actual); }
public void GetAndSetImportSyntaxTrees_ReturnsSyntaxTrees() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); var expected = new[] { RazorSyntaxTree.Parse(codeDocument.Source), }; codeDocument.SetImportSyntaxTrees(expected); // Act var actual = codeDocument.GetImportSyntaxTrees(); // Assert Assert.Same(expected, actual); }
public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree) { if (codeDocument == null) { throw new ArgumentNullException(nameof(codeDocument)); } if (syntaxTree == null) { throw new ArgumentNullException(nameof(syntaxTree)); } var sectionVerifier = new NestedSectionVerifier(syntaxTree); return(sectionVerifier.Verify()); }
public void Execute_TagHelpersFromCodeDocumentAndFeature_PrefersCodeDocument() { // Arrange var featureTagHelpers = new[] { CreateTagHelperDescriptor( tagName: "input", typeName: "TestInputTagHelper", assemblyName: "TestAssembly"), }; var projectEngine = RazorProjectEngine.Create(builder => builder.AddTagHelpers(featureTagHelpers)); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = projectEngine.Engine, }; var sourceDocument = CreateTestSourceDocument(); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); var codeDocumentTagHelpers = new[] { CreateTagHelperDescriptor( tagName: "form", typeName: "TestFormTagHelper", assemblyName: "TestAssembly"), }; codeDocument.SetTagHelpers(codeDocumentTagHelpers); // Act phase.Execute(codeDocument); // Assert var rewrittenTree = codeDocument.GetSyntaxTree(); var descendantNodes = rewrittenTree.Root.DescendantNodes(); Assert.Empty(rewrittenTree.Diagnostics); var tagHelperNodes = descendantNodes.Where(n => n is MarkupTagHelperElementSyntax tagHelper).Cast <MarkupTagHelperElementSyntax>().ToArray(); var formTagHelper = Assert.Single(tagHelperNodes); Assert.Equal("form", formTagHelper.TagHelperInfo.TagName); }
public void Execute_ThrowsForMissingDependency_IRDocument() { // Arrange var phase = new DefaultRazorCSharpLoweringPhase(); var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase)); var codeDocument = TestRazorCodeDocument.CreateEmpty(); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source)); // Act & Assert ExceptionAssert.Throws <InvalidOperationException>( () => phase.Execute(codeDocument), $"The '{nameof(DefaultRazorCSharpLoweringPhase)}' phase requires a '{nameof(DocumentIntermediateNode)}' " + $"provided by the '{nameof(RazorCodeDocument)}'."); }
public void Execute_CanHandleSingleLengthRemoveTagHelperDirective() { // Arrange var engine = RazorEngine.Create(builder => { builder.AddTagHelpers(new TagHelperDescriptor[0]); }); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = engine, }; var expectedDiagnostics = new[] { RazorDiagnostic.Create( new RazorError( LegacyResources.ParseError_Unterminated_String_Literal, new SourceLocation(17 + Environment.NewLine.Length, 1, 17), length: 1)), RazorDiagnostic.Create( new RazorError( Resources.FormatInvalidTagHelperLookupText("\""), new SourceLocation(17 + Environment.NewLine.Length, 1, 17), length: 1)) }; var content = @" @removeTagHelper """; var sourceDocument = TestRazorSourceDocument.Create(content, fileName: 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 <RemoveTagHelperChunkGenerator>(directiveValue.ChunkGenerator); Assert.Equal(expectedDiagnostics, chunkGenerator.Diagnostics); }
public void Execute_RewritesTagHelpers() { // 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 sourceDocument = CreateTestSourceDocument(); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); // Act phase.Execute(codeDocument); // Assert var rewrittenTree = codeDocument.GetSyntaxTree(); Assert.Empty(rewrittenTree.Diagnostics); Assert.Equal(3, rewrittenTree.Root.Children.Count); var formTagHelper = Assert.IsType <TagHelperBlock>(rewrittenTree.Root.Children[2]); Assert.Equal("form", formTagHelper.TagName); Assert.Equal(3, formTagHelper.Children.Count); var inputTagHelper = Assert.IsType <TagHelperBlock>(formTagHelper.Children[1]); Assert.Equal("input", inputTagHelper.TagName); }
public void Execute_RewritesWhitespace() { // Assert var content = Environment.NewLine + " @true"; var sourceDocument = TestRazorSourceDocument.Create(content); var originalTree = RazorSyntaxTree.Parse(sourceDocument); var pass = new HtmlNodeOptimizationPass(); var codeDocument = RazorCodeDocument.Create(sourceDocument); // Act var outputTree = pass.Execute(codeDocument, originalTree); // Assert Assert.Equal(4, outputTree.Root.Children.Count); var whitespace = Assert.IsType <Span>(outputTree.Root.Children[1]); Assert.True(whitespace.Content.All(char.IsWhiteSpace)); }
public void TryComputeNamespace_OverrideImportsNamespaceDirective() { // Arrange var sourceDocument = TestRazorSourceDocument.Create( content: "@namespace My.Custom.OverrideNS", filePath: "C:\\Hello\\Components\\Test.cshtml", relativePath: "\\Components\\Test.cshtml"); var codeDocument = TestRazorCodeDocument.Create(sourceDocument, Array.Empty <RazorSourceDocument>()); codeDocument.SetFileKind(FileKinds.Component); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(sourceDocument, RazorParserOptions.Create(options => { options.Directives.Add(NamespaceDirective.Directive); }))); var importSourceDocument = TestRazorSourceDocument.Create( content: "@namespace My.Custom.NS", filePath: "C:\\Hello\\_Imports.razor", relativePath: "\\_Imports.razor"); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSourceDocument, RazorParserOptions.Create(options => { options.Directives.Add(NamespaceDirective.Directive); })) }); var documentNode = new DocumentIntermediateNode() { Options = RazorCodeGenerationOptions.Create(c => { c.RootNamespace = "Hello.World"; }) }; codeDocument.SetDocumentIntermediateNode(documentNode); // Act codeDocument.TryComputeNamespace(fallbackToRootNamespace: true, out var @namespace); // Assert Assert.Equal("My.Custom.OverrideNS", @namespace); }
public static bool TryGetLastNamespaceDirective( RazorSyntaxTree syntaxTree, out string namespaceDirectiveContent, out SourceSpan namespaceDirectiveSpan) { var visitor = new NamespaceVisitor(syntaxTree.Source); visitor.Visit(syntaxTree.Root); if (string.IsNullOrEmpty(visitor.LastNamespaceContent)) { namespaceDirectiveContent = null; namespaceDirectiveSpan = SourceSpan.Undefined; return(false); } namespaceDirectiveContent = visitor.LastNamespaceContent; namespaceDirectiveSpan = visitor.LastNamespaceLocation; return(true); }
public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree) { if (codeDocument == null) { throw new ArgumentNullException(nameof(codeDocument)); } if (syntaxTree == null) { throw new ArgumentNullException(nameof(syntaxTree)); } var whitespaceRewriter = new WhitespaceRewriter(); var rewritten = whitespaceRewriter.Visit(syntaxTree.Root); var rewrittenSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Source, syntaxTree.Diagnostics, syntaxTree.Options); return(rewrittenSyntaxTree); }
public void Execute_CollapsesConditionalAttributes() { // Assert var content = "<input value='hello world' />"; var sourceDocument = TestRazorSourceDocument.Create(content); var originalTree = RazorSyntaxTree.Parse(sourceDocument); var pass = new HtmlNodeOptimizationPass(); var codeDocument = RazorCodeDocument.Create(sourceDocument); // Act var outputTree = pass.Execute(codeDocument, originalTree); // Assert var tag = Assert.Single(outputTree.Root.Children); var tagBlock = Assert.IsType <Block>(tag); Assert.Equal(BlockKindInternal.Tag, tagBlock.Type); Assert.Equal(3, tagBlock.Children.Count); Assert.IsType <Span>(tagBlock.Children[1]); }
public static void Verify(RazorSyntaxTree syntaxTree, bool ensureFullFidelity = true) { var verifier = new Verifier(syntaxTree.Source); verifier.Visit(syntaxTree.Root); if (ensureFullFidelity) { var syntaxTreeString = syntaxTree.Root.ToFullString(); var builder = new StringBuilder(syntaxTree.Source.Length); for (var i = 0; i < syntaxTree.Source.Length; i++) { builder.Append(syntaxTree.Source[i]); } var sourceString = builder.ToString(); // Make sure the syntax tree contains all of the text in the document. Assert.Equal(sourceString, syntaxTreeString); } }
public void Execute_ExecutesPhasesInOrder() { // Arrange var codeDocument = TestRazorCodeDocument.CreateEmpty(); // We're going to set up mocks to simulate a sequence of passes. We don't care about // what's in the trees, we're just going to look at the identity via strict mocks. var originalSyntaxTree = RazorSyntaxTree.Parse(codeDocument.Source); var firstPassSyntaxTree = RazorSyntaxTree.Parse(codeDocument.Source); var secondPassSyntaxTree = RazorSyntaxTree.Parse(codeDocument.Source); codeDocument.SetSyntaxTree(originalSyntaxTree); var firstPass = new Mock <IRazorSyntaxTreePass>(MockBehavior.Strict); firstPass.SetupGet(m => m.Order).Returns(0); firstPass.SetupProperty(m => m.Engine); firstPass.Setup(m => m.Execute(codeDocument, originalSyntaxTree)).Returns(firstPassSyntaxTree); var secondPass = new Mock <IRazorSyntaxTreePass>(MockBehavior.Strict); secondPass.SetupGet(m => m.Order).Returns(1); secondPass.SetupProperty(m => m.Engine); secondPass.Setup(m => m.Execute(codeDocument, firstPassSyntaxTree)).Returns(secondPassSyntaxTree); var phase = new DefaultRazorSyntaxTreePhase(); var engine = RazorEngine.CreateEmpty(b => { b.Phases.Add(phase); b.Features.Add(firstPass.Object); b.Features.Add(secondPass.Object); }); // Act phase.Execute(codeDocument); // Assert Assert.Same(secondPassSyntaxTree, codeDocument.GetSyntaxTree()); }
public void Execute_RewritesWhitespace() { // Assert var content = Environment.NewLine + " @true"; var sourceDocument = TestRazorSourceDocument.Create(content); var originalTree = RazorSyntaxTree.Parse(sourceDocument); var pass = new HtmlNodeOptimizationPass(); var codeDocument = RazorCodeDocument.Create(sourceDocument); // Act var outputTree = pass.Execute(codeDocument, originalTree); // Assert var document = Assert.IsType <RazorDocumentSyntax>(outputTree.Root); var block = Assert.IsType <MarkupBlockSyntax>(document.Document); Assert.Equal(4, block.Children.Count); var whitespace = Assert.IsType <MarkupTextLiteralSyntax>(block.Children[1]); Assert.True(whitespace.GetContent().All(char.IsWhiteSpace)); }
public void Execute_EmptyTagHelperDescriptorsFromCodeDocument_DoesNotFallbackToTagHelperFeature() { // Arrange var tagHelpers = new[] { CreateTagHelperDescriptor( tagName: "form", typeName: "TestFormTagHelper", assemblyName: "TestAssembly"), CreateTagHelperDescriptor( tagName: "input", typeName: "TestInputTagHelper", assemblyName: "TestAssembly"), }; var projectEngine = RazorProjectEngine.Create(builder => builder.AddTagHelpers(tagHelpers)); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = projectEngine.Engine, }; var sourceDocument = CreateTestSourceDocument(); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); codeDocument.SetTagHelpers(tagHelpers: Array.Empty <TagHelperDescriptor>()); // Act phase.Execute(codeDocument); // Assert var rewrittenTree = codeDocument.GetSyntaxTree(); Assert.Empty(rewrittenTree.Diagnostics); Assert.Equal(7, rewrittenTree.Root.Children.Count); var rewrittenNodes = rewrittenTree.Root.Children.OfType <TagHelperBlock>(); Assert.Empty(rewrittenNodes); }
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 void Execute_CollatesSyntaxDiagnosticsFromImportDocuments() { // Arrange var phase = new DefaultRazorIntermediateNodeLoweringPhase(); var engine = RazorProjectEngine.CreateEmpty(b => { b.Phases.Add(phase); b.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: false)); }); var codeDocument = TestRazorCodeDocument.CreateEmpty(); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("@ ")), RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("<p @(")), }); var options = RazorCodeGenerationOptions.CreateDefault(); // Act phase.Execute(codeDocument); // Assert var documentNode = codeDocument.GetDocumentIntermediateNode(); Assert.Collection(documentNode.Diagnostics, diagnostic => { Assert.Equal(@"A space or line break was encountered after the ""@"" character. Only valid identifiers, keywords, comments, ""("" and ""{"" are valid at the start of a code block and they must occur immediately following ""@"" with no space in between.", diagnostic.GetMessage(CultureInfo.CurrentCulture)); }, diagnostic => { Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.", diagnostic.GetMessage(CultureInfo.CurrentCulture)); }); }
public void Execute_NoopsWhenNoTagHelperFeature() { // Arrange var engine = RazorEngine.Create(); var phase = new DefaultRazorTagHelperBinderPhase() { Engine = engine, }; var sourceDocument = CreateTestSourceDocument(); var codeDocument = RazorCodeDocument.Create(sourceDocument); var originalTree = RazorSyntaxTree.Parse(sourceDocument); codeDocument.SetSyntaxTree(originalTree); // Act phase.Execute(codeDocument); // Assert var outputTree = codeDocument.GetSyntaxTree(); Assert.Empty(outputTree.Diagnostics); Assert.Same(originalTree, outputTree); }
public void Execute_CollatesSyntaxDiagnosticsFromSourceDocument() { // Arrange var phase = new DefaultRazorIntermediateNodeLoweringPhase(); var engine = RazorProjectEngine.CreateEmpty(b => { b.Phases.Add(phase); b.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: false)); }); var codeDocument = TestRazorCodeDocument.Create("<p class=@("); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source)); // Act phase.Execute(codeDocument); // Assert var documentNode = codeDocument.GetDocumentIntermediateNode(); var diagnostic = Assert.Single(documentNode.Diagnostics); Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.", diagnostic.GetMessage(CultureInfo.CurrentCulture)); }
public void Execute_AutomaticallyOverridesImportedSingleLineSinglyOccurringDirective_MultipleImports() { // Arrange var directive = DirectiveDescriptor.CreateSingleLineDirective( "custom", builder => { builder.AddStringToken(); builder.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 importSource1 = TestRazorSourceDocument.Create("@custom \"hello\"", filePath: "import1.cshtml"); var importSource2 = TestRazorSourceDocument.Create("@custom \"world\"", filePath: "import2.cshtml"); var codeDocument = TestRazorCodeDocument.Create("<p>NonDirective</p>"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource1, options), RazorSyntaxTree.Parse(importSource2, options) }); // Act phase.Execute(codeDocument); // Assert var documentNode = codeDocument.GetDocumentIntermediateNode(); var customDirectives = documentNode.FindDirectiveReferences(directive); var customDirective = (DirectiveIntermediateNode)Assert.Single(customDirectives).Node; var stringToken = Assert.Single(customDirective.Tokens); Assert.Equal("\"world\"", stringToken.Content); }
public void Execute_ThrowsForMissingDependency_CodeTarget() { // Arrange var phase = new DefaultRazorCSharpLoweringPhase(); var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase)); var codeDocument = TestRazorCodeDocument.CreateEmpty(); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source)); var irDocument = new DocumentIntermediateNode() { DocumentKind = "test", }; codeDocument.SetDocumentIntermediateNode(irDocument); // Act & Assert ExceptionAssert.Throws <InvalidOperationException>( () => phase.Execute(codeDocument), $"The document of kind 'test' does not have a '{nameof(CodeTarget)}'. " + $"The document classifier must set a value for '{nameof(DocumentIntermediateNode.Target)}'."); }
public void Execute_DoesNotImportNonFileScopedSinglyOccurringDirectives_Block() { // Arrange var codeBlockDirective = DirectiveDescriptor.CreateCodeBlockDirective("code", b => b.AddStringToken()); var razorBlockDirective = DirectiveDescriptor.CreateRazorBlockDirective("razor", b => b.AddStringToken()); var phase = new DefaultRazorIntermediateNodeLoweringPhase(); var engine = RazorProjectEngine.CreateEmpty(b => { b.Phases.Add(phase); b.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: false)); b.AddDirective(codeBlockDirective); b.AddDirective(razorBlockDirective); }); var options = RazorParserOptions.Create(builder => { builder.Directives.Add(codeBlockDirective); builder.Directives.Add(razorBlockDirective); }); var importSource = TestRazorSourceDocument.Create( @"@code ""code block"" { } @razor ""razor block"" { }", filePath: "testImports.cshtml"); var codeDocument = TestRazorCodeDocument.Create("<p>NonDirective</p>"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource, options) }); // Act phase.Execute(codeDocument); // Assert var documentNode = codeDocument.GetDocumentIntermediateNode(); var directives = documentNode.Children.OfType <DirectiveIntermediateNode>(); Assert.Empty(directives); }