public void AddDirective_ExistingFeature_UsesFeature() { // Arrange var expected = new DefaultRazorDirectiveFeature(); var engine = RazorEngine.CreateEmpty(b => { b.Features.Add(expected); // Act b.AddDirective(DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine)); }); // Assert var actual = Assert.Single(engine.Features.OfType <IRazorDirectiveFeature>()); Assert.Same(expected, actual); var directive = Assert.Single(actual.Directives); Assert.Equal("test", directive.Directive); }
public void GetDirectiveCompletionItems_CodeBlockCommitCharacters() { // Arrange var customDirective = DirectiveDescriptor.CreateCodeBlockDirective("custom", builder => { builder.DisplayName = "code"; builder.Description = "My Custom Code Block Directive."; }); var syntaxTree = CreateSyntaxTree("@cod", customDirective); // Act var completionItems = DirectiveCompletionItemProvider.GetDirectiveCompletionItems(syntaxTree); // Assert Assert.Collection( completionItems, item => AssertRazorCompletionItem("code", customDirective, item, DirectiveCompletionItemProvider.BlockDirectiveCommitCharacters), item => AssertRazorCompletionItem(s_defaultDirectives[0], item), item => AssertRazorCompletionItem(s_defaultDirectives[1], item), item => AssertRazorCompletionItem(s_defaultDirectives[2], item)); }
public void NamespaceToken() { // Arrange var engine = CreateProjectEngine(builder => { builder.ConfigureDocumentClassifier(); builder.AddDirective(DirectiveDescriptor.CreateDirective("custom", DirectiveKind.SingleLine, b => b.AddNamespaceToken())); }); var projectItem = CreateProjectItemFromFile(); // Act var codeDocument = engine.ProcessDesignTime(projectItem); // Assert AssertDocumentNodeMatchesBaseline(codeDocument.GetDocumentIntermediateNode()); AssertCSharpDocumentMatchesBaseline(codeDocument.GetCSharpDocument()); AssertLinePragmas(codeDocument, designTime: true); AssertSourceMappingsMatchBaseline(codeDocument); }
public void GetDesiredIndentation_ReturnsNull_IfOwningSpanIsNone() { // Arrange var customDirective = DirectiveDescriptor.CreateSingleLineDirective("custom"); var source = new StringTextSnapshot($@" @custom "); var syntaxTree = GetSyntaxTree(source, new[] { customDirective }); var service = new DefaultRazorIndentationFactsService(); // Act var indentation = service.GetDesiredIndentation( syntaxTree, source, source.GetLineFromLineNumber(2), indentSize: 4, tabSize: 1); // Assert Assert.Null(indentation); }
public void GetDirectiveCompletionItems_UsesDisplayNamesWhenNotNull() { // Arrange var customDirective = DirectiveDescriptor.CreateSingleLineDirective("custom", builder => { builder.DisplayName = "different"; builder.Description = "My Custom Directive."; }); var syntaxTree = CreateSyntaxTree("@addTag", customDirective); // Act var completionItems = DefaultRazorCompletionFactsService.GetDirectiveCompletionItems(syntaxTree); // Assert Assert.Collection( completionItems, item => AssertRazorCompletionItem("different", customDirective, item), item => AssertRazorCompletionItem(DefaultDirectives[0], item), item => AssertRazorCompletionItem(DefaultDirectives[1], item), item => AssertRazorCompletionItem(DefaultDirectives[2], item)); }
public void GetDesiredIndentation_ReturnsNull_IfOwningSpanIsNone() { // Arrange var customDirective = DirectiveDescriptor.CreateSingleLineDirective("custom"); var source = $@" @custom "; var syntaxTree = GetSyntaxTree(source, new[] { customDirective }); var service = new DefaultRazorIndentationFactsService(); // Act var indentation = service.GetDesiredIndentation( syntaxTree, previousLineEndIndex: GetLineEndIndexForLine(source, 1), getLineContent: line => GetLineContent(source, line), indentSize: 4, tabSize: 1); // Assert Assert.Null(indentation); }
public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder, bool supportConstraints) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (Directive == null) { // Do nothing and assume the first registration wins. In real life this directive is only ever registered once. if (supportConstraints) { Directive = DirectiveDescriptor.CreateDirective( "typeparam", DirectiveKind.SingleLine, builder => { builder.AddMemberToken(ComponentResources.TypeParamDirective_Token_Name, ComponentResources.TypeParamDirective_Token_Description); builder.AddOptionalGenericTypeConstraintToken(ComponentResources.TypeParamDirective_Constraint_Name, ComponentResources.TypeParamDirective_Constraint_Description); builder.Usage = DirectiveUsage.FileScopedMultipleOccurring; builder.Description = ComponentResources.TypeParamDirective_Description; }); } else { Directive = DirectiveDescriptor.CreateDirective( "typeparam", DirectiveKind.SingleLine, builder => { builder.AddMemberToken(ComponentResources.TypeParamDirective_Token_Name, ComponentResources.TypeParamDirective_Token_Description); builder.Usage = DirectiveUsage.FileScopedMultipleOccurring; builder.Description = ComponentResources.TypeParamDirective_Description; }); } } builder.AddDirective(Directive, FileKinds.Component, FileKinds.ComponentImport); return(builder); }
public void GetDesiredIndentation_ReturnsCorrectIndentation_ForMarkupWithinDirectiveBlock() { // Arrange var customDirective = DirectiveDescriptor.CreateRazorBlockDirective("custom"); var source = $@"@custom {{ <div> }}"; var syntaxTree = GetSyntaxTree(source, new[] { customDirective }); var service = new DefaultRazorIndentationFactsService(); // Act var indentation = service.GetDesiredIndentation( syntaxTree, previousLineEndIndex: GetLineEndIndexForLine(source, 2), getLineContent: line => GetLineContent(source, line), indentSize: 4, tabSize: 4); // Assert Assert.Equal(4, indentation); }
public void GetDesiredIndentation_ReturnsCorrectIndentation_ForMarkupWithinDirectiveBlock() { // Arrange var customDirective = DirectiveDescriptor.CreateRazorBlockDirective("custom"); var source = new StringTextSnapshot($@"@custom {{ <div> }}"); var syntaxTree = GetSyntaxTree(source, new[] { customDirective }); var service = new DefaultRazorIndentationFactsService(); // Act var indentation = service.GetDesiredIndentation( syntaxTree, source, source.GetLineFromLineNumber(3), indentSize: 4, tabSize: 4); // Assert Assert.Equal(4, indentation); }
public void Lower_WithImports_IgnoresBlockDirective() { // Arrange var source = TestRazorSourceDocument.Create("<p>Hi!</p>"); var imports = new[] { TestRazorSourceDocument.Create("@block token { }"), }; var codeDocument = TestRazorCodeDocument.Create(source, imports); // Act var documentNode = Lower(codeDocument, b => { b.AddDirective(DirectiveDescriptor.CreateDirective("block", DirectiveKind.RazorBlock, d => d.AddMemberToken())); }); // Assert Children( documentNode, n => Html("<p>Hi!</p>", n)); }
internal DirectiveItemViewModel(DirectiveDescriptor directive) { _directive = directive; var builder = new StringBuilder(); builder.Append("@"); builder.Append(_directive.Directive); foreach (var token in _directive.Tokens) { builder.Append("("); builder.Append(token.Kind.ToString()); builder.Append(")"); } if (directive.Kind == DirectiveKind.CodeBlock || directive.Kind == DirectiveKind.RazorBlock) { builder.Append("{ ... }"); } DisplayText = builder.ToString(); }
public void DirectiveDescriptor_AllowsNullableTypes() { // Arrange var variants = new[] { "string?", "string?[]", "global::System.Int32?", "KeyValuePair<string, string>?", "KeyValuePair<string, string>?[]", "global::System.Collections.Generic.KeyValuePair<string, string>?[]", }; var directiveName = "custom"; var source = $"@{directiveName}"; var descriptor = DirectiveDescriptor.CreateDirective( directiveName, DirectiveKind.SingleLine, b => { b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); }); for (var i = 0; i < variants.Length; i++) { source += $" {variants[i]}"; } // Act & Assert ParseDocumentTest(source, new[] { descriptor }); }
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); }
public void Execute_AutomaticallyOverridesImportedSingleLineSinglyOccurringDirective_MultipleImports() { // Arrange var directive = DirectiveDescriptor.CreateSingleLineDirective( "custom", builder => { builder.AddStringToken(); builder.Usage = DirectiveUsage.FileScopedSinglyOccurring; }); var phase = new DefaultRazorIntermediateNodeLoweringPhase(); var engine = RazorProjectEngine.CreateEmpty(b => { b.Phases.Add(phase); b.Features.Add(new DefaultRazorCodeGenerationOptionsFeature(designTime: false)); b.AddDirective(directive); }); var options = RazorParserOptions.Create(builder => builder.Directives.Add(directive)); var importSource1 = TestRazorSourceDocument.Create("@custom \"hello\"", filePath: "import1.cshtml"); var importSource2 = TestRazorSourceDocument.Create("@custom \"world\"", filePath: "import2.cshtml"); var codeDocument = TestRazorCodeDocument.Create("<p>NonDirective</p>"); codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source, options)); codeDocument.SetImportSyntaxTrees(new[] { RazorSyntaxTree.Parse(importSource1, options), RazorSyntaxTree.Parse(importSource2, options) }); // Act phase.Execute(codeDocument); // Assert var documentNode = codeDocument.GetDocumentIntermediateNode(); var customDirectives = documentNode.FindDirectiveReferences(directive); var customDirective = (DirectiveIntermediateNode)Assert.Single(customDirectives).Node; var stringToken = Assert.Single(customDirective.Tokens); Assert.Equal("\"world\"", stringToken.Content); }
public void DirectiveDescriptor_AllowsTupleTypes() { // Arrange var variants = new[] { "(bool, int)", "(int aa, string bb)?", "( int? q , bool w )", "( int ? q, bool ?w ,(long ? [])) ?", "(List<(int, string)?> aa, string bb)", "(string ss, (int u, List<(string, int)> k, (Char c, bool b, List<int> l)), global::System.Int32[] a)", }; var directiveName = "custom"; var source = $"@{directiveName}"; var descriptor = DirectiveDescriptor.CreateDirective( directiveName, DirectiveKind.SingleLine, b => { b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); b.AddTypeToken(); }); for (var i = 0; i < variants.Length; i++) { source += $" {variants[i]}"; } // Act & Assert ParseDocumentTest(source, new[] { descriptor }); }
private static void AssertRazorCompletionItem(DirectiveDescriptor directive, RazorCompletionItem item) => AssertRazorCompletionItem(directive.Directive, directive, item);
private static IEnumerable <DirectiveDescriptor> GetDirectives() { var directives = new DirectiveDescriptor[] { DirectiveDescriptor.CreateDirective( "inject", DirectiveKind.SingleLine, builder => { builder .AddTypeToken() .AddMemberToken(); builder.Usage = DirectiveUsage.FileScopedMultipleOccurring; }), DirectiveDescriptor.CreateDirective( "model", DirectiveKind.SingleLine, builder => { builder.AddTypeToken(); builder.Usage = DirectiveUsage.FileScopedSinglyOccurring; }), DirectiveDescriptor.CreateDirective( "namespace", DirectiveKind.SingleLine, builder => { builder.AddNamespaceToken(); builder.Usage = DirectiveUsage.FileScopedSinglyOccurring; }), DirectiveDescriptor.CreateDirective( "page", DirectiveKind.SingleLine, builder => { builder.AddOptionalStringToken(); builder.Usage = DirectiveUsage.FileScopedSinglyOccurring; }), DirectiveDescriptor.CreateDirective( SyntaxConstants.CSharp.FunctionsKeyword, DirectiveKind.CodeBlock, builder => { }), DirectiveDescriptor.CreateDirective( SyntaxConstants.CSharp.InheritsKeyword, DirectiveKind.SingleLine, builder => { builder.AddTypeToken(); builder.Usage = DirectiveUsage.FileScopedSinglyOccurring; }), DirectiveDescriptor.CreateDirective( SyntaxConstants.CSharp.SectionKeyword, DirectiveKind.RazorBlock, builder => { builder.AddMemberToken(); }), }; return(directives); }
public void Configure(RazorParserOptionsBuilder options) { options.Directives.Add(DirectiveDescriptor.CreateDirective("test", DirectiveKind.SingleLine)); }
private static void AssertRazorCompletionItem(string completionDisplayText, DirectiveDescriptor directive, RazorCompletionItem item) { Assert.Equal(item.DisplayText, completionDisplayText); Assert.Equal(item.InsertText, directive.Directive); Assert.Equal(directive.Description, item.Description); }
/// <summary> /// Adds the specified <see cref="DirectiveDescriptor"/> for the provided file kind. /// </summary> /// <param name="builder">The <see cref="RazorProjectEngineBuilder"/>.</param> /// <param name="directive">The <see cref="DirectiveDescriptor"/> to add.</param> /// <param name="fileKinds">The file kinds, for which to register the directive. See <see cref="FileKinds"/>.</param> /// <returns>The <see cref="RazorProjectEngineBuilder"/>.</returns> public static RazorProjectEngineBuilder AddDirective(this RazorProjectEngineBuilder builder, DirectiveDescriptor directive, params string[] fileKinds) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (directive == null) { throw new ArgumentNullException(nameof(directive)); } if (fileKinds == null) { throw new ArgumentNullException(nameof(fileKinds)); } var directiveFeature = GetDirectiveFeature(builder); foreach (var fileKind in fileKinds) { if (!directiveFeature.DirectivesByFileKind.TryGetValue(fileKind, out var directives)) { directives = new List <DirectiveDescriptor>(); directiveFeature.DirectivesByFileKind.Add(fileKind, directives); } directives.Add(directive); } return(builder); }
public static IReadOnlyList <IntermediateNodeReference> FindDirectiveReferences(this DocumentIntermediateNode node, DirectiveDescriptor directive) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (directive == null) { throw new ArgumentNullException(nameof(directive)); } var visitor = new DirectiveVisitor(directive); visitor.Visit(node); return(visitor.Directives); }
private static Completion CreateDirectiveCompletion(DirectiveDescriptor directive) { return(new Completion(directive.DisplayName, directive.DisplayName, directive.Description, null, null)); }
public DirectiveChunkGenerator(DirectiveDescriptor descriptor) { Descriptor = descriptor; }
public DirectiveVisitor(DirectiveDescriptor directive) { _directive = directive; }
/// <summary> /// Adds the specified <see cref="DirectiveDescriptor"/>. /// </summary> /// <param name="builder">The <see cref="RazorProjectEngineBuilder"/>.</param> /// <param name="directive">The <see cref="DirectiveDescriptor"/> to add.</param> /// <returns>The <see cref="RazorProjectEngineBuilder"/>.</returns> public static RazorProjectEngineBuilder AddDirective(this RazorProjectEngineBuilder builder, DirectiveDescriptor directive) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (directive == null) { throw new ArgumentNullException(nameof(directive)); } var directiveFeature = GetDirectiveFeature(builder); directiveFeature.Directives.Add(directive); return(builder); }
private static void AssertRazorCompletionItem(DirectiveDescriptor directive, CompletionItem item, IAsyncCompletionSource source) => AssertRazorCompletionItem(directive.Directive, directive, item, source);
private static Completion CreateDirectiveCompletion(DirectiveDescriptor directive) { return new Completion(directive.DisplayName, directive.DisplayName, directive.Description, null, null); }