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);
        }
Esempio n. 4
0
        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));
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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));
    }
Esempio n. 11
0
        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();
        }
Esempio n. 12
0
        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);
    }
Esempio n. 15
0
        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);
Esempio n. 17
0
        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);
        }
Esempio n. 22
0
 private static Completion CreateDirectiveCompletion(DirectiveDescriptor directive)
 {
     return(new Completion(directive.DisplayName, directive.DisplayName, directive.Description, null, null));
 }
Esempio n. 23
0
 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);
 }