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); }
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)}'."); }
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); }
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()); }
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)}'."); }
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); }
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); }
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()); }
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); }
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); }); }
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); }
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)); }
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); }
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); }
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)); }); }
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); }
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); }
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); }
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); }