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());
        }
Пример #2
0
        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}");
                    }
                }
            }
        }
Пример #5
0
        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)]);
        }
Пример #6
0
        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));
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #11
0
        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)}'.");
        }
Пример #12
0
        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));
        }
Пример #15
0
        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);
            }
Пример #17
0
        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]);
        }
Пример #19
0
        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());
        }
Пример #21
0
        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));
        }
Пример #22
0
        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);
        }
Пример #25
0
        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);
        }
Пример #27
0
        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));
        }
Пример #28
0
        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);
        }
Пример #29
0
        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)}'.");
        }
Пример #30
0
        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);
        }