Example #1
0
        public void GenerateCode_WithPath()
        {
            // Arrange
            var path           = "/Views/Home/Index.cshtml";
            var projectItem    = new TestRazorProjectItem(path);
            var project        = new TestRazorProjectFileSystem(new[] { projectItem });
            var razorEngine    = RazorProjectEngine.Create().Engine;
            var templateEngine = new RazorTemplateEngine(razorEngine, project);

            // Act
            var cSharpDocument = templateEngine.GenerateCode(path);

            // Assert
            Assert.NotNull(cSharpDocument);
            Assert.NotEmpty(cSharpDocument.GeneratedCode);
            Assert.Empty(cSharpDocument.Diagnostics);
        }
Example #2
0
        public void Execute_ThrowsForMissingDependency_IRDocument()
        {
            // Arrange
            var phase = new DefaultRazorCSharpLoweringPhase();

            var engine = RazorProjectEngine.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)}'.");
        }
Example #3
0
        public void Process_AsksFileSystemForItems()
        {
            // Arrange
            var razorProjectItem = new TestRazorProjectItem("/some/path.cshtml");
            var testFileSystem   = new Mock <RazorProjectFileSystem>();

            testFileSystem.Setup(fileSystem => fileSystem.GetItem("/some/path.cshtml"))
            .Returns(razorProjectItem)
            .Verifiable();
            var projectEngine = RazorProjectEngine.Create(testFileSystem.Object);

            // Act
            projectEngine.Process("/some/path.cshtml");

            // Assert
            testFileSystem.Verify();
        }
        private static void AssertDefaultFeatures(RazorProjectEngine engine)
        {
            var features = engine.EngineFeatures.OrderBy(f => f.GetType().Name).ToArray();

            Assert.Collection(
                features,
                feature => Assert.IsType <AttributeDirectivePass>(feature),
                feature => Assert.IsType <ComponentBindLoweringPass>(feature),
                feature => Assert.IsType <ComponentChildContentDiagnosticPass>(feature),
                feature => Assert.IsType <ComponentComplexAttributeContentPass>(feature),
                feature => Assert.IsType <ComponentDocumentClassifierPass>(feature),
                feature => Assert.IsType <ComponentEventHandlerLoweringPass>(feature),
                feature => Assert.IsType <ComponentGenericTypePass>(feature),
                feature => Assert.IsType <ComponentInjectDirectivePass>(feature),
                feature => Assert.IsType <ComponentKeyLoweringPass>(feature),
                feature => Assert.IsType <ComponentLayoutDirectivePass>(feature),
                feature => Assert.IsType <ComponentLoweringPass>(feature),
                feature => Assert.IsType <ComponentMarkupBlockPass>(feature),
                feature => Assert.IsType <ComponentMarkupDiagnosticPass>(feature),
                feature => Assert.IsType <ComponentMarkupEncodingPass>(feature),
                feature => Assert.IsType <ComponentPageDirectivePass>(feature),
                feature => Assert.IsType <ComponentReferenceCaptureLoweringPass>(feature),
                feature => Assert.IsType <ComponentScriptTagPass>(feature),
                feature => Assert.IsType <ComponentSplatLoweringPass>(feature),
                feature => Assert.IsType <ComponentTemplateDiagnosticPass>(feature),
                feature => Assert.IsType <ComponentWhitespacePass>(feature),
                feature => Assert.IsType <DefaultDirectiveSyntaxTreePass>(feature),
                feature => Assert.IsType <DefaultDocumentClassifierPass>(feature),
                feature => Assert.IsType <DefaultDocumentClassifierPassFeature>(feature),
                feature => Assert.IsType <DefaultMetadataIdentifierFeature>(feature),
                feature => Assert.IsType <DefaultRazorCodeGenerationOptionsFeature>(feature),
                feature => Assert.IsType <DefaultRazorDirectiveFeature>(feature),
                feature => Assert.IsType <DefaultRazorParserOptionsFeature>(feature),
                feature => Assert.IsType <DefaultRazorTargetExtensionFeature>(feature),
                feature => Assert.IsType <DefaultTagHelperOptimizationPass>(feature),
                feature => Assert.IsType <DesignTimeDirectivePass>(feature),
                feature => Assert.IsType <DirectiveRemovalOptimizationPass>(feature),
                feature => Assert.IsType <EliminateMethodBodyPass>(feature),
                feature => Assert.IsType <FunctionsDirectivePass>(feature),
                feature => Assert.IsType <HtmlNodeOptimizationPass>(feature),
                feature => Assert.IsType <ImplementsDirectivePass>(feature),
                feature => Assert.IsType <InheritsDirectivePass>(feature),
                feature => Assert.IsType <MetadataAttributePass>(feature),
                feature => Assert.IsType <PreallocatedTagHelperAttributeOptimizationPass>(feature));
        }
        public void Execute_RewritesTagHelpers()
        {
            // Arrange
            var projectEngine = RazorProjectEngine.Create(builder =>
            {
                builder.AddTagHelpers(new[]
                {
                    CreateTagHelperDescriptor(
                        tagName: "form",
                        typeName: "TestFormTagHelper",
                        assemblyName: "TestAssembly"),
                    CreateTagHelperDescriptor(
                        tagName: "input",
                        typeName: "TestInputTagHelper",
                        assemblyName: "TestAssembly"),
                });
            });

            var phase = new DefaultRazorTagHelperBinderPhase()
            {
                Engine = projectEngine.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);
        }
Example #6
0
        public void Execute_AddsSyntaxTree()
        {
            // Arrange
            var phase  = new DefaultRazorParsingPhase();
            var engine = RazorProjectEngine.CreateEmpty(builder =>
            {
                builder.Phases.Add(phase);
                builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false, version: RazorLanguageVersion.Latest, fileKind: null));
            });

            var codeDocument = TestRazorCodeDocument.CreateEmpty();

            // Act
            phase.Execute(codeDocument);

            // Assert
            Assert.NotNull(codeDocument.GetSyntaxTree());
        }
Example #7
0
        public void Execute_ThrowsForMissingDependency_SyntaxTree()
        {
            // 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();

            // Act & Assert
            ExceptionAssert.Throws <InvalidOperationException>(
                () => phase.Execute(codeDocument),
                $"The '{nameof(DefaultRazorIntermediateNodeLoweringPhase)}' phase requires a '{nameof(RazorSyntaxTree)}' " +
                $"provided by the '{nameof(RazorCodeDocument)}'.");
        }
Example #8
0
        public void Execute_DirectiveWithError_PreservesDiagnosticsAndRemovesDirectiveNodeFromDocument()
        {
            // Arrange
            var content            = "@custom \"Hello\"";
            var expectedDiagnostic = RazorDiagnostic.Create(new RazorDiagnosticDescriptor("RZ9999", () => "Some diagnostic message.", RazorDiagnosticSeverity.Error), SourceSpan.Undefined);
            var sourceDocument     = TestRazorSourceDocument.Create(content);
            var codeDocument       = RazorCodeDocument.Create(sourceDocument);
            var defaultEngine      = RazorProjectEngine.Create(b =>
            {
                b.AddDirective(DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, d => d.AddStringToken()));
            }).Engine;
            var documentNode = Lower(codeDocument, defaultEngine);

            // Add the diagnostic to the directive node.
            var directiveNode = documentNode.FindDescendantNodes <DirectiveIntermediateNode>().Single();

            directiveNode.Diagnostics.Add(expectedDiagnostic);

            var pass = new DirectiveRemovalOptimizationPass()
            {
                Engine = defaultEngine,
            };

            // Act
            pass.Execute(codeDocument, documentNode);

            // Assert
            var diagnostic = Assert.Single(documentNode.Diagnostics);

            Assert.Equal(expectedDiagnostic, diagnostic);

            Children(documentNode,
                     node => Assert.IsType <NamespaceDeclarationIntermediateNode>(node));
            var @namespace = documentNode.Children[0];

            Children(@namespace,
                     node => Assert.IsType <ClassDeclarationIntermediateNode>(node));
            var @class = @namespace.Children[0];
            var method = SingleChild <MethodDeclarationIntermediateNode>(@class);

            Assert.Empty(method.Children);
        }
        public void Execute_RewritesTagHelpers()
        {
            // Arrange
            var projectEngine = RazorProjectEngine.Create(builder =>
            {
                builder.AddTagHelpers(new[]
                {
                    CreateTagHelperDescriptor(
                        tagName: "form",
                        typeName: "TestFormTagHelper",
                        assemblyName: "TestAssembly"),
                    CreateTagHelperDescriptor(
                        tagName: "input",
                        typeName: "TestInputTagHelper",
                        assemblyName: "TestAssembly"),
                });
            });

            var phase = new DefaultRazorTagHelperBinderPhase()
            {
                Engine = projectEngine.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();
            var descendantNodes = rewrittenTree.Root.DescendantNodes();

            Assert.Empty(rewrittenTree.Diagnostics);
            var tagHelperNodes = descendantNodes.Where(n => n is MarkupTagHelperElementSyntax tagHelper).Cast <MarkupTagHelperElementSyntax>().ToArray();

            Assert.Equal("form", tagHelperNodes[0].TagHelperInfo.TagName);
            Assert.Equal("input", tagHelperNodes[1].TagHelperInfo.TagName);
        }
        public void Execute_IgnoresDocumentsWithDocumentKind()
        {
            // Arrange
            var documentNode = new DocumentIntermediateNode()
            {
                DocumentKind = "ignore",
                Options      = RazorCodeGenerationOptions.CreateDefault(),
            };

            var pass = new DefaultDocumentClassifierPass();

            pass.Engine = RazorProjectEngine.Create().Engine;

            // Act
            pass.Execute(TestRazorCodeDocument.CreateEmpty(), documentNode);

            // Assert
            Assert.Equal("ignore", documentNode.DocumentKind);
            NoChildren(documentNode);
        }
Example #11
0
        public void CreateCodeDocument_ThrowsIfPathCannotBeFound()
        {
            // Arrange
            var projectItem    = new TestRazorProjectItem("/Views/Home/Index.cshtml");
            var project        = new TestRazorProjectFileSystem(new[] { projectItem });
            var razorEngine    = RazorProjectEngine.Create().Engine;
            var templateEngine = new RazorTemplateEngine(razorEngine, project)
            {
                Options =
                {
                    ImportsFileName = "MyImport.cshtml",
                }
            };

            // Act & Assert
            var ex = Assert.Throws <InvalidOperationException>(() => templateEngine.CreateCodeDocument("/DoesNotExist.cshtml"));

            // Assert
            Assert.Equal("The item '/DoesNotExist.cshtml' could not be found.", ex.Message);
        }
Example #12
0
        public void GetImports_CanQueryInformationOnNonExistentFileWithoutImports()
        {
            // Arrange
            var fileSystem     = new TestRazorProjectFileSystem();
            var razorEngine    = RazorProjectEngine.Create().Engine;
            var templateEngine = new RazorTemplateEngine(razorEngine, fileSystem)
            {
                Options =
                {
                    ImportsFileName = "MyImport.cshtml"
                }
            };
            var projectItemToQuery = fileSystem.GetItem("/Views/Home/Index.cshtml");

            // Act
            var imports = templateEngine.GetImports(projectItemToQuery);

            // Assert
            Assert.Empty(imports);
        }
        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 = RazorProjectEngine.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());
        }
Example #14
0
        public void ProcessDesignTime_SetsOptions_DesignTime()
        {
            // Arrange
            var projectItem = new TestRazorProjectItem("Index.cshtml");

            var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, TestRazorProjectFileSystem.Empty);

            // Act
            var codeDocument = projectEngine.ProcessDesignTime(projectItem);

            // Assert
            var parserOptions = codeDocument.GetParserOptions();

            Assert.True(parserOptions.DesignTime);

            var codeGenerationOptions = codeDocument.GetCodeGenerationOptions();

            Assert.True(codeGenerationOptions.DesignTime);
            Assert.True(codeGenerationOptions.SuppressChecksum);
            Assert.True(codeGenerationOptions.SuppressMetadataAttributes);
        }
Example #15
0
        public void CreateCodeDocument_WithFileSystemProject_ReturnsCorrectItems()
        {
            // Arrange
            var testFolder = Path.Combine(
                TestProject.GetProjectDirectory(typeof(DefaultRazorProjectFileSystemTest)),
                "TestFiles",
                "DefaultRazorProjectFileSystem");

            var project        = new DefaultRazorProjectFileSystem(testFolder);
            var razorEngine    = RazorProjectEngine.Create().Engine;
            var templateEngine = new RazorTemplateEngine(razorEngine, project)
            {
                Options =
                {
                    ImportsFileName = "_ViewImports.cshtml"
                }
            };

            // Act
            var codeDocument = templateEngine.CreateCodeDocument("/Views/Home/Index.cshtml");

            // Assert
            Assert.Collection(
                codeDocument.Imports,
                item =>
            {
                Assert.Equal(Path.Combine(testFolder, "_ViewImports.cshtml"), item.FilePath);
                Assert.Equal("_ViewImports.cshtml", item.RelativePath);
            },
                item =>
            {
                Assert.Equal(Path.Combine(testFolder, "Views", "_ViewImports.cshtml"), item.FilePath);
                Assert.Equal(Path.Combine("Views", "_ViewImports.cshtml"), item.RelativePath);
            },
                item =>
            {
                Assert.Equal(Path.Combine(testFolder, "Views", "Home", "_ViewImports.cshtml"), item.FilePath);
                Assert.Equal(Path.Combine("Views", "Home", "_ViewImports.cshtml"), item.RelativePath);
            });
        }
Example #16
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_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);
        }
Example #18
0
        public void CreateCodeDocument_NullImportFileName_IncludesDefaultImportIfNotNull()
        {
            // Arrange
            var projectItem    = new TestRazorProjectItem("/Views/Home/Index.cshtml");
            var project        = new TestRazorProjectFileSystem(new[] { projectItem });
            var razorEngine    = RazorProjectEngine.Create().Engine;
            var defaultImport  = RazorSourceDocument.ReadFrom(new MemoryStream(), "Default.cshtml");
            var templateEngine = new RazorTemplateEngine(razorEngine, project)
            {
                Options =
                {
                    DefaultImports = defaultImport,
                }
            };

            // Act
            var codeDocument = templateEngine.CreateCodeDocument(projectItem);

            // Assert
            Assert.Collection(codeDocument.Imports,
                              import => Assert.Same(defaultImport, import));
        }
Example #19
0
        public void GetImportItems_WithPath_ReturnsAllImportsForFile()
        {
            // Arrange
            var expected       = new[] { "/Views/Home/MyImport.cshtml", "/Views/MyImport.cshtml", "/MyImport.cshtml" };
            var project        = new TestRazorProjectFileSystem();
            var razorEngine    = RazorProjectEngine.Create().Engine;
            var templateEngine = new RazorTemplateEngine(razorEngine, project)
            {
                Options =
                {
                    ImportsFileName = "MyImport.cshtml"
                }
            };

            // Act
            var imports = templateEngine.GetImportItems("/Views/Home/Index.cshtml");

            // Assert
            var paths = imports.Select(i => i.FilePath);

            Assert.Equal(expected, paths);
        }
        public void Process_GetsImportsFromFeature()
        {
            // Arrange
            var sourceDocument = TestRazorSourceDocument.Create();
            var testImport     = TestRazorSourceDocument.Create();
            var importFeature  = new Mock <IRazorImportFeature>();

            importFeature.Setup(feature => feature.GetImports(It.IsAny <string>()))
            .Returns(new[] { testImport });
            var projectEngine = RazorProjectEngine.Create(TestRazorProjectFileSystem.Empty, builder =>
            {
                builder.SetImportFeature(importFeature.Object);
            });

            // Act
            var codeDocument = projectEngine.Process(sourceDocument);

            // Assert
            var import = Assert.Single(codeDocument.Imports);

            Assert.Same(testImport, import);
        }
Example #21
0
        public void Execute_UsesConfigureParserFeatures()
        {
            // Arrange
            var phase  = new DefaultRazorParsingPhase();
            var engine = RazorProjectEngine.CreateEmpty((builder) =>
            {
                builder.Phases.Add(phase);
                builder.Features.Add(new DefaultRazorParserOptionsFeature(designTime: false, version: RazorLanguageVersion.Latest, fileKind: null));
                builder.Features.Add(new MyParserOptionsFeature());
            });

            var codeDocument = TestRazorCodeDocument.CreateEmpty();

            // Act
            phase.Execute(codeDocument);

            // Assert
            var syntaxTree = codeDocument.GetSyntaxTree();
            var directive  = Assert.Single(syntaxTree.Options.Directives);

            Assert.Equal("test", directive.Directive);
        }
        public void OnInitialized_OrdersPassesInAscendingOrder()
        {
            // Arrange & Act
            var phase = new DefaultRazorDocumentClassifierPhase();

            var first  = Mock.Of <IRazorDocumentClassifierPass>(p => p.Order == 15);
            var second = Mock.Of <IRazorDocumentClassifierPass>(p => p.Order == 17);

            var engine = RazorProjectEngine.CreateEmpty(b =>
            {
                b.Phases.Add(phase);

                b.Features.Add(second);
                b.Features.Add(first);
            });

            // Assert
            Assert.Collection(
                phase.Passes,
                p => Assert.Same(first, p),
                p => Assert.Same(second, p));
        }
        public void Execute_CanHandleSingleLengthTagHelperPrefix()
        {
            // 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_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);
        }
Example #24
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));
            });
        }
Example #25
0
        private DocumentIntermediateNode Lower(
            RazorCodeDocument codeDocument,
            Action <RazorProjectEngineBuilder> builder   = null,
            IEnumerable <TagHelperDescriptor> tagHelpers = null,
            bool designTime = false)
        {
            tagHelpers = tagHelpers ?? new TagHelperDescriptor[0];

            Action <RazorProjectEngineBuilder> configureEngine = b =>
            {
                builder?.Invoke(b);

                FunctionsDirective.Register(b);
                SectionDirective.Register(b);
                b.AddTagHelpers(tagHelpers);

                b.Features.Add(new DesignTimeOptionsFeature(designTime));
            };

            var projectEngine = RazorProjectEngine.Create(configureEngine);

            for (var i = 0; i < projectEngine.Phases.Count; i++)
            {
                var phase = projectEngine.Phases[i];
                phase.Execute(codeDocument);

                if (phase is IRazorIntermediateNodeLoweringPhase)
                {
                    break;
                }
            }

            var documentNode = codeDocument.GetDocumentIntermediateNode();

            Assert.NotNull(documentNode);

            return(documentNode);
        }
Example #26
0
        public void ProcessDesignTime_WithImportsAndTagHelpers_SetsOnCodeDocument()
        {
            // Arrange
            var projectItem        = new TestRazorProjectItem("Index.cshtml");
            var importItem         = new TestRazorProjectItem("_import.cshtml");
            var expectedImports    = new[] { RazorSourceDocument.ReadFrom(importItem) };
            var expectedTagHelpers = new[]
            {
                TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build(),
                TagHelperDescriptorBuilder.Create("Test2TagHelper", "TestAssembly").Build(),
            };

            var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, TestRazorProjectFileSystem.Empty);

            // Act
            var codeDocument = projectEngine.ProcessDesignTime(RazorSourceDocument.ReadFrom(projectItem), expectedImports, expectedTagHelpers);

            // Assert
            var tagHelpers = codeDocument.GetTagHelpers();

            Assert.Same(expectedTagHelpers, tagHelpers);
            Assert.Equal(expectedImports, codeDocument.Imports);
        }
        public void Execute_NoopsWhenNoTagHelperFeature()
        {
            // Arrange
            var projectEngine = RazorProjectEngine.Create();
            var phase         = new DefaultRazorTagHelperBinderPhase()
            {
                Engine = projectEngine.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);
        }
Example #28
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));
        }
        public void Execute_CreatesClassStructure()
        {
            // Arrange
            var documentNode = new DocumentIntermediateNode()
            {
                Options = RazorCodeGenerationOptions.CreateDefault(),
            };

            var pass = new DefaultDocumentClassifierPass();

            pass.Engine = RazorProjectEngine.Create().Engine;

            // Act
            pass.Execute(TestRazorCodeDocument.CreateEmpty(), documentNode);

            // Assert
            Assert.Equal("default", documentNode.DocumentKind);

            var @namespace = SingleChild <NamespaceDeclarationIntermediateNode>(documentNode);
            var @class     = SingleChild <ClassDeclarationIntermediateNode>(@namespace);
            var method     = SingleChild <MethodDeclarationIntermediateNode>(@class);

            NoChildren(method);
        }
Example #30
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);
        }