コード例 #1
0
        protected override void ExecuteCore(
            RazorCodeDocument codeDocument,
            DocumentIntermediateNode documentNode)
        {
            var visitor = new Visitor();

            visitor.Visit(documentNode);

            var properties = new HashSet <string>(StringComparer.Ordinal);
            var classNode  = documentNode.FindPrimaryClass();

            for (var i = visitor.Directives.Count - 1; i >= 0; i--)
            {
                var directive = visitor.Directives[i];
                var tokens    = directive.Tokens.ToArray();
                if (tokens.Length < 2)
                {
                    continue;
                }

                var typeName   = tokens[0].Content;
                var memberName = tokens[1].Content;

                if (!properties.Add(memberName))
                {
                    continue;
                }

                classNode.Children.Add(new ComponentInjectIntermediateNode(typeName, memberName));
            }
        }
コード例 #2
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (!IsComponentDocument(documentNode))
            {
                return;
            }

            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            var references = documentNode.FindDescendantReferences <TagHelperDirectiveAttributeIntermediateNode>();

            for (var i = 0; i < references.Count; i++)
            {
                var reference = references[i];
                var node      = (TagHelperDirectiveAttributeIntermediateNode)reference.Node;

                if (node.TagHelper.IsKeyTagHelper())
                {
                    reference.Replace(RewriteUsage(reference.Parent, node));
                }
            }
        }
コード例 #3
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            var context = new Context(@namespace, @class);

            // For each VCTH *usage* we need to rewrite the tag helper node to use the tag helper runtime to construct
            // and set properties on the the correct field, and using the name of the type we will generate.
            var nodes = documentNode.FindDescendantNodes <TagHelperIntermediateNode>();

            for (var i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];
                foreach (var tagHelper in node.TagHelpers)
                {
                    RewriteUsage(context, node, tagHelper);
                }
            }

            // Then for each VCTH *definition* that we've seen we need to generate the class that implements
            // ITagHelper and the field that will hold it.
            foreach (var tagHelper in context.TagHelpers)
            {
                AddField(context, tagHelper);
                AddTagHelperClass(context, tagHelper);
            }
        }
コード例 #4
0
ファイル: RefLoweringPass.cs プロジェクト: sjroe/Blazor
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            var nodes = documentNode.FindDescendantNodes <TagHelperIntermediateNode>();

            for (var i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];

                for (var j = node.Children.Count - 1; j >= 0; j--)
                {
                    var attributeNode = node.Children[j] as ComponentAttributeExtensionNode;
                    if (attributeNode != null &&
                        attributeNode.TagHelper != null &&
                        attributeNode.TagHelper.IsRefTagHelper())
                    {
                        RewriteUsage(@class, node, j, attributeNode);
                    }
                }
            }
        }
コード例 #5
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @class = documentNode.FindPrimaryClass();

            if (@class == null)
            {
                return;
            }

            var directiveNodes = new List <IntermediateNodeReference>();

            directiveNodes.AddRange(documentNode.FindDirectiveReferences(FunctionsDirective.Directive));

            if (FileKinds.IsComponent(codeDocument.GetFileKind()))
            {
                directiveNodes.AddRange(documentNode.FindDirectiveReferences(ComponentCodeDirective.Directive));
            }

            // Now we have all the directive nodes, we want to add them to the end of the class node in document order.
            var orderedDirectives = directiveNodes.OrderBy(n => n.Node.Source?.AbsoluteIndex);

            foreach (var directiveReference in orderedDirectives)
            {
                var node = directiveReference.Node;
                for (var i = 0; i < node.Children.Count; i++)
                {
                    @class.Children.Add(node.Children[i]);
                }

                // We don't want to keep the original directive node around anymore.
                // Otherwise this can cause unintended side effects in the subsequent passes.
                directiveReference.Remove();
            }
        }
コード例 #6
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (documentNode.DocumentKind != RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
                documentNode.DocumentKind != MvcViewDocumentClassifierPass.MvcViewDocumentKind)
            {
                // Not a MVC file. Skip.
                return;
            }

            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            var classIndex = @namespace.Children.IndexOf(@class);

            if (classIndex == -1)
            {
                return;
            }

            var identifierFeature = Engine.Features.OfType <IMetadataIdentifierFeature>().First();
            var identifier        = identifierFeature.GetIdentifier(codeDocument, codeDocument.Source);

            var metadataAttributeNode = new CreateNewOnMetadataUpdateAttributeIntermediateNode();

            // Metadata attributes need to be inserted right before the class declaration.
            @namespace.Children.Insert(classIndex, metadataAttributeNode);

            // [global:Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute("Identifier", "/Views/Home/Index.cshtml")]
            @namespace.Children.Insert(classIndex, new RazorCompiledItemMetadataAttributeIntermediateNode
            {
                Key   = "Identifier",
                Value = identifier,
            });
        }
コード例 #7
0
            private void CreateTypeInferenceMethod(DocumentIntermediateNode documentNode, ComponentIntermediateNode node)
            {
                var @namespace = documentNode.FindPrimaryNamespace().Content;

                @namespace  = string.IsNullOrEmpty(@namespace) ? "__Blazor" : "__Blazor." + @namespace;
                @namespace += "." + documentNode.FindPrimaryClass().ClassName;

                var typeInferenceNode = new ComponentTypeInferenceMethodIntermediateNode()
                {
                    Component = node,

                    // Method name is generated and guaranteed not to collide, since it's unique for each
                    // component call site.
                    MethodName   = $"Create{CSharpIdentifier.SanitizeIdentifier(node.TagName)}_{_id++}",
                    FullTypeName = @namespace + ".TypeInference",
                };

                node.TypeInferenceNode = typeInferenceNode;

                // Now we need to insert the type inference node into the tree.
                var namespaceNode = documentNode.Children
                                    .OfType <NamespaceDeclarationIntermediateNode>()
                                    .Where(n => n.Annotations.Contains(new KeyValuePair <object, object>(ComponentMetadata.Component.GenericTypedKey, bool.TrueString)))
                                    .FirstOrDefault();

                if (namespaceNode == null)
                {
                    namespaceNode = new NamespaceDeclarationIntermediateNode()
                    {
                        Annotations =
                        {
                            { ComponentMetadata.Component.GenericTypedKey, bool.TrueString },
                        },
                        Content = @namespace,
                    };

                    documentNode.Children.Add(namespaceNode);
                }

                var classNode = namespaceNode.Children
                                .OfType <ClassDeclarationIntermediateNode>()
                                .Where(n => n.ClassName == "TypeInference")
                                .FirstOrDefault();

                if (classNode == null)
                {
                    classNode = new ClassDeclarationIntermediateNode()
                    {
                        ClassName = "TypeInference",
                        Modifiers =
                        {
                            "internal",
                            "static",
                        },
                    };
                    namespaceNode.Children.Add(classNode);
                }

                classNode.Children.Add(typeInferenceNode);
            }
コード例 #8
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            // For each component *usage* we need to rewrite the tag helper node to map to the relevant component
            // APIs.
            var nodes = documentNode.FindDescendantNodes <TagHelperIntermediateNode>();

            for (var i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];
                if (node.TagHelpers.Count > 1)
                {
                    node.Diagnostics.Add(BlazorDiagnosticFactory.Create_MultipleComponents(node.Source, node.TagName, node.TagHelpers));
                }

                RewriteUsage(node, node.TagHelpers[0]);
            }
        }
コード例 #9
0
ファイル: BindLoweringPass.cs プロジェクト: vbnisim/Blazor
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            // For each bind *usage* we need to rewrite the tag helper node to map to basic constructs.
            var nodes = documentNode.FindDescendantNodes <TagHelperIntermediateNode>();

            for (var i = 0; i < nodes.Count; i++)
            {
                var node = nodes[i];

                ProcessDuplicates(node);

                for (var j = node.Children.Count - 1; j >= 0; j--)
                {
                    var attributeNode = node.Children[j] as ComponentAttributeExtensionNode;
                    if (attributeNode != null &&
                        attributeNode.TagHelper != null &&
                        attributeNode.TagHelper.IsBindTagHelper())
                    {
                        RewriteUsage(node, j, attributeNode);
                    }
                }
            }
        }
コード例 #10
0
    protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
    {
        var @namespace = documentNode.FindPrimaryNamespace();
        var @class     = documentNode.FindPrimaryClass();

        if (@namespace == null || @class == null)
        {
            return;
        }

        var classIndex = @namespace.Children.IndexOf(@class);

        foreach (var attribute in documentNode.FindDirectiveReferences(AttributeDirective.Directive))
        {
            var token = ((DirectiveIntermediateNode)attribute.Node).Tokens.FirstOrDefault();
            if (token != null)
            {
                var node = new CSharpCodeIntermediateNode
                {
                    Source = token.Source
                };

                node.Children.Add(new IntermediateToken()
                {
                    Content = token.Content,
                    Source  = token.Source,
                    Kind    = TokenKind.CSharp,
                });

                @namespace.Children.Insert(classIndex++, node);
            }
        }
    }
コード例 #11
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            @namespace.Content = $"{RootNamespace}.{PathTools.GetRelativePath($"{ProjectDirectory}{Path.DirectorySeparatorChar}", Path.GetDirectoryName(codeDocument.Source.FilePath)).Replace(Path.DirectorySeparatorChar, '.').Replace(Path.AltDirectorySeparatorChar, '.')}";
            @class.ClassName   = Path.GetFileNameWithoutExtension(codeDocument.Source.FilePath);
        }
コード例 #12
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (!IsComponentDocument(documentNode))
            {
                return;
            }

            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            var references = documentNode.FindDescendantReferences <TagHelperDirectiveAttributeIntermediateNode>();

            for (var i = 0; i < references.Count; i++)
            {
                var reference = references[i];
                var node      = (TagHelperDirectiveAttributeIntermediateNode)reference.Node;

                if (node.TagHelper.IsRefTagHelper())
                {
                    // We've found an @ref directive attribute.
                    //
                    // If we can't get a nonempty identifier, do nothing because there will
                    // already be a diagnostic for empty values
                    var identifier = DetermineIdentifierToken(node);
                    if (identifier == null)
                    {
                        continue;
                    }

                    var rewritten = RewriteUsage(reference.Parent, identifier);
                    reference.Replace(rewritten);

                    // Now we need to check if the field generation has been suppressed.
                    //
                    // You have to suppress field generation for generic types because we don't know the
                    // type name to create the field.
                    var generateField = ShouldGenerateField(reference.Parent);

                    // Insert the field with other fields, near the top of the class.
                    if (generateField)
                    {
                        var position = 0;
                        while (position < @class.Children.Count && @class.Children[i] is FieldDeclarationIntermediateNode)
                        {
                            position++;
                        }

                        @class.Children.Insert(position, CreateField(rewritten.FieldTypeName, identifier));
                    }
                }
            }
        }
コード例 #13
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();

            if (@namespace == null || string.IsNullOrEmpty(@namespace.Content))
            {
                // No namespace node or it's incomplete. Skip.
                return;
            }

            var @class = documentNode.FindPrimaryClass();

            if (@class == null || string.IsNullOrEmpty(@class.ClassName))
            {
                // No class node or it's incomplete. Skip.
                return;
            }

            var generatedTypeName = $"{@namespace.Content}.{@class.ClassName}";

            // The MVC attributes require a relative path to be specified so that we can make a view engine path.
            // We can't use a rooted path because we don't know what the project root is.
            //
            // If we can't sanitize the path, we'll just set it to null and let is blow up at runtime - we don't
            // want to create noise if this code has to run in some unanticipated scenario.
            var escapedPath = MakeVerbatimStringLiteral(ConvertToViewEnginePath(codeDocument.Source.RelativePath));

            string attribute;

            if (documentNode.DocumentKind == MvcViewDocumentClassifierPass.MvcViewDocumentKind)
            {
                attribute = $"[assembly:{RazorViewAttribute}({escapedPath}, typeof({generatedTypeName}))]";
            }
            else if (documentNode.DocumentKind == RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
                     PageDirective.TryGetPageDirective(documentNode, out var pageDirective))
            {
                var escapedRoutePrefix = MakeVerbatimStringLiteral(pageDirective.RouteTemplate);
                attribute = $"[assembly:{RazorPageAttribute}({escapedPath}, typeof({generatedTypeName}), {escapedRoutePrefix})]";
            }
            else
            {
                return;
            }

            var index = documentNode.Children.IndexOf(@namespace);

            Debug.Assert(index >= 0);

            var pageAttribute = new CSharpCodeIntermediateNode();

            pageAttribute.Children.Add(new IntermediateToken()
            {
                Kind    = TokenKind.CSharp,
                Content = attribute,
            });

            documentNode.Children.Insert(index, pageAttribute);
        }
コード例 #14
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (!IsComponentDocument(documentNode))
            {
                return;
            }

            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            // For each @bind *usage* we need to rewrite the tag helper node to map to basic constructs.
            var references          = documentNode.FindDescendantReferences <TagHelperDirectiveAttributeIntermediateNode>();
            var parameterReferences = documentNode.FindDescendantReferences <TagHelperDirectiveAttributeParameterIntermediateNode>();

            var parents = new HashSet <IntermediateNode>();

            for (var i = 0; i < references.Count; i++)
            {
                parents.Add(references[i].Parent);
            }
            for (var i = 0; i < parameterReferences.Count; i++)
            {
                parents.Add(parameterReferences[i].Parent);
            }

            foreach (var parent in parents)
            {
                ProcessDuplicates(parent);
            }

            // First, collect all the non-parameterized @bind or @bind-* attributes.
            // The dict key is a tuple of (parent, attributeName) to differentiate attributes with the same name in two different elements.
            // We don't have to worry about duplicate bound attributes in the same element
            // like, <Foo @bind="bar" @bind="bar" />, because IR lowering takes care of that.
            var bindEntries = new Dictionary <(IntermediateNode, string), BindEntry>();

            for (var i = 0; i < references.Count; i++)
            {
                var reference = references[i];
                var parent    = reference.Parent;
                var node      = (TagHelperDirectiveAttributeIntermediateNode)reference.Node;

                if (!parent.Children.Contains(node))
                {
                    // This node was removed as a duplicate, skip it.
                    continue;
                }

                if (node.TagHelper.IsBindTagHelper())
                {
                    bindEntries[(parent, node.AttributeName)] = new BindEntry(reference);
コード例 #15
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (!IsComponentDocument(documentNode))
            {
                return;
            }

            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            // For each component *usage* we need to rewrite the tag helper node to map to the relevant component
            // APIs.
            var references = documentNode.FindDescendantReferences <TagHelperIntermediateNode>();

            for (var i = 0; i < references.Count; i++)
            {
                var reference = references[i];
                var node      = (TagHelperIntermediateNode)reference.Node;
                if (node.TagHelpers.Any(t => t.IsChildContentTagHelper()))
                {
                    // This is a child content tag helper. This will be rewritten when we visit its parent.
                    continue;
                }

                // The element didn't match any child content descriptors. Look for any matching component descriptors.
                var count = 0;
                for (var j = 0; j < node.TagHelpers.Count; j++)
                {
                    if (node.TagHelpers[j].IsComponentTagHelper())
                    {
                        // Only allow a single component tag helper per element. If there are multiple, we'll just consider
                        // the first one and ignore the others.
                        if (++count > 1)
                        {
                            node.Diagnostics.Add(ComponentDiagnosticFactory.Create_MultipleComponents(node.Source, node.TagName, node.TagHelpers));
                            break;
                        }
                    }
                }

                if (count >= 1)
                {
                    reference.Replace(RewriteAsComponent(node, node.TagHelpers.First(t => t.IsComponentTagHelper())));
                }
                else
                {
                    reference.Replace(RewriteAsElement(node));
                }
            }
        }
コード例 #16
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (!IsComponentDocument(documentNode))
            {
                return;
            }

            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            // For each bind *usage* we need to rewrite the tag helper node to map to basic constructs.
            var references = documentNode.FindDescendantReferences <TagHelperPropertyIntermediateNode>();

            var parents = new HashSet <IntermediateNode>();

            for (var i = 0; i < references.Count; i++)
            {
                parents.Add(references[i].Parent);
            }

            foreach (var parent in parents)
            {
                ProcessDuplicates(parent);
            }

            for (var i = 0; i < references.Count; i++)
            {
                var reference = references[i];
                var node      = (TagHelperPropertyIntermediateNode)reference.Node;

                if (!reference.Parent.Children.Contains(node))
                {
                    // This node was removed as a duplicate, skip it.
                    continue;
                }

                if (node.TagHelper.IsBindTagHelper() && node.AttributeName.StartsWith("bind"))
                {
                    // Workaround for https://github.com/aspnet/Blazor/issues/703
                    var rewritten = RewriteUsage(reference.Parent, node);
                    reference.Remove();

                    for (var j = 0; j < rewritten.Length; j++)
                    {
                        reference.Parent.Children.Add(rewritten[j]);
                    }
                }
            }
        }
コード例 #17
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();

            if (@namespace == null || string.IsNullOrEmpty(@namespace.Content))
            {
                // No namespace node or it's incomplete. Skip.
                return;
            }

            var @class = documentNode.FindPrimaryClass();

            if (@class == null || string.IsNullOrEmpty(@class.ClassName))
            {
                // No class node or it's incomplete. Skip.
                return;
            }

            var generatedTypeName = $"{@namespace.Content}.{@class.ClassName}";
            var path        = codeDocument.GetRelativePath();
            var escapedPath = EscapeAsVerbatimLiteral(path);

            string attribute;

            if (documentNode.DocumentKind == MvcViewDocumentClassifierPass.MvcViewDocumentKind)
            {
                attribute = $"[assembly:{RazorViewAttribute}({escapedPath}, typeof({generatedTypeName}))]";
            }
            else if (documentNode.DocumentKind == RazorPageDocumentClassifierPass.RazorPageDocumentKind &&
                     PageDirective.TryGetPageDirective(documentNode, out var pageDirective))
            {
                var escapedRoutePrefix = EscapeAsVerbatimLiteral(pageDirective.RouteTemplate);
                attribute = $"[assembly:{RazorPageAttribute}({escapedPath}, typeof({generatedTypeName}), {escapedRoutePrefix})]";
            }
            else
            {
                return;
            }

            var index = documentNode.Children.IndexOf(@namespace);

            Debug.Assert(index >= 0);

            var pageAttribute = new CSharpCodeIntermediateNode();

            pageAttribute.Children.Add(new IntermediateToken()
            {
                Kind    = TokenKind.CSharp,
                Content = attribute,
            });

            documentNode.Children.Insert(index, pageAttribute);
        }
コード例 #18
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @class = documentNode.FindPrimaryClass();

            if (@class == null)
            {
                // Bail if we can't find a class node, we need to be able to create fields.
                return;
            }

            var context = new Context(@class);

            // First find all tag helper nodes that require the default tag helper runtime.
            //
            // This phase lowers the conceptual nodes to default runtime nodes we only care about those.
            var tagHelperNodes = documentNode
                                 .FindDescendantNodes <TagHelperIntermediateNode>()
                                 .Where(IsTagHelperRuntimeNode)
                                 .ToArray();

            if (tagHelperNodes.Length == 0)
            {
                // If nothing uses the default runtime then we're done.
                return;
            }

            AddDefaultRuntime(context);

            // Each tagHelperNode should be rewritten to use the default tag helper runtime. That doesn't necessarily
            // mean that all of these tag helpers are the default kind, just that them are compatible with ITagHelper.
            for (var i = 0; i < tagHelperNodes.Length; i++)
            {
                var tagHelperNode = tagHelperNodes[i];

                RewriteBody(tagHelperNode);
                RewriteHtmlAttributes(tagHelperNode);
                AddExecute(tagHelperNode);

                // We need to find all of the 'default' kind tag helpers and rewrite their usage site to use the
                // extension nodes for the default tag helper runtime (ITagHelper).
                foreach (var tagHelper in tagHelperNode.TagHelpers)
                {
                    RewriteUsage(context, tagHelperNode, tagHelper);
                }
            }

            // Then for each 'default' kind tag helper we need to generate the field that will hold it.
            foreach (var tagHelper in context.TagHelpers)
            {
                AddField(context, tagHelper);
            }
        }
コード例 #19
0
            protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
            {
                var visitor = new Visitor();
                var output  = GetExtension(documentNode, visitor);



                documentNode.FindPrimaryClass().Children.Insert(0, new IntermediateToken
                {
                    Content = $"public override string Extension => {output};",
                    Kind    = TokenKind.CSharp
                });
            }
コード例 #20
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (!IsComponentDocument(documentNode))
            {
                return;
            }

            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                // Nothing to do, bail. We can't function without the standard structure.
                return;
            }

            // For each event handler *usage* we need to rewrite the tag helper node to map to basic constructs.
            // Each usage will be represented by a tag helper property that is a descendant of either
            // a component or element.
            var references = documentNode.FindDescendantReferences <TagHelperPropertyIntermediateNode>();

            var parents = new HashSet <IntermediateNode>();

            for (var i = 0; i < references.Count; i++)
            {
                parents.Add(references[i].Parent);
            }

            foreach (var parent in parents)
            {
                ProcessDuplicates(parent);
            }

            for (var i = 0; i < references.Count; i++)
            {
                var reference = references[i];
                var node      = (TagHelperPropertyIntermediateNode)reference.Node;

                if (!reference.Parent.Children.Contains(node))
                {
                    // This node was removed as a duplicate, skip it.
                    continue;
                }

                if (node.TagHelper.IsEventHandlerTagHelper())
                {
                    reference.Replace(RewriteUsage(reference.Parent, node));
                }
            }
        }
コード例 #21
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();

            if (@namespace == null || string.IsNullOrEmpty(@namespace.Content))
            {
                // No namespace node or it's incomplete. Skip.
                return;
            }

            var @class = documentNode.FindPrimaryClass();

            if (@class == null || string.IsNullOrEmpty(@class.ClassName))
            {
                // No class node or it's incomplete. Skip.
                return;
            }

            string generatedTypeName  = $"{@namespace.Content}.{@class.ClassName}";
            string templateKey        = codeDocument.Source.FilePath;
            string escapedTemplateKey = EscapeAsVerbatimLiteral(templateKey);

            string attribute;

            if (documentNode.DocumentKind == RazorLightTemplateDocumentClassifierPass.RazorLightTemplateDocumentKind)
            {
                attribute = $"[assembly:{RazorLightTemplateAttribute}({escapedTemplateKey}, typeof({generatedTypeName}))]";
            }
            else
            {
                return;
            }

            int index = documentNode.Children.IndexOf(@namespace);

            Debug.Assert(index >= 0);

            var pageAttribute = new CSharpCodeIntermediateNode();

            pageAttribute.Children.Add(new IntermediateToken()
            {
                Kind    = TokenKind.CSharp,
                Content = attribute,
            });

            documentNode.Children.Insert(index, pageAttribute);
        }
コード例 #22
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @class = documentNode.FindPrimaryClass();

            if (@class == null)
            {
                return;
            }

            foreach (var functions in documentNode.FindDirectiveReferences(FunctionsDirective.Directive))
            {
                for (var i = 0; i < functions.Node.Children.Count; i++)
                {
                    @class.Children.Add(functions.Node.Children[i]);
                }
            }
        }
コード例 #23
0
    public void FindPrimaryClass_FindsClassWithAnnotation()
    {
        // Arrange
        var document = new DocumentIntermediateNode();
        var @class   = new ClassDeclarationIntermediateNode();

        @class.Annotations[CommonAnnotations.PrimaryClass] = CommonAnnotations.PrimaryClass;

        var builder = IntermediateNodeBuilder.Create(document);

        builder.Add(@class);

        // Act
        var result = document.FindPrimaryClass();

        // Assert
        Assert.Same(@class, result);
    }
コード例 #24
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (codeDocument == null)
            {
                throw new ArgumentNullException(nameof(codeDocument));
            }

            if (documentNode == null)
            {
                throw new ArgumentNullException(nameof(documentNode));
            }

            if (!IsComponentDocument(documentNode))
            {
                return;
            }

            if (documentNode.Options.SuppressPrimaryMethodBody)
            {
                // There's no benefit running the whitespace trimmer if we're not emitting
                // the method bodies.
                return;
            }

            // There's no benefit running the whitespace trimmer during design-time builds
            if (documentNode.Options.DesignTime)
            {
                return;
            }

            // Respect @preservewhitespace directives
            if (PreserveWhitespaceIsEnabled(documentNode))
            {
                return;
            }

            var @class = documentNode.FindPrimaryClass();

            if (@class != null)
            {
                var visitor = new Visitor();
                visitor.Visit(@class);
            }
        }
コード例 #25
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @class = documentNode.FindPrimaryClass();

            if (@class == null)
            {
                return;
            }

            foreach (var inherits in documentNode.FindDirectiveReferences(InheritsDirective.Directive))
            {
                var token = ((DirectiveIntermediateNode)inherits.Node).Tokens.FirstOrDefault();
                if (token != null)
                {
                    @class.BaseType = token.Content;
                    break;
                }
            }
        }
コード例 #26
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @namespace = documentNode.FindPrimaryNamespace();
            var @class     = documentNode.FindPrimaryClass();

            if (@namespace == null || @class == null)
            {
                return;
            }

            var directives = documentNode.FindDirectiveReferences(ComponentLayoutDirective.Directive);

            if (directives.Count == 0)
            {
                return;
            }

            var token = ((DirectiveIntermediateNode)directives[0].Node).Tokens.FirstOrDefault();

            if (token == null)
            {
                return;
            }

            var attributeNode = new CSharpCodeIntermediateNode();

            attributeNode.Children.Add(new IntermediateToken()
            {
                Kind    = TokenKind.CSharp,
                Content = $"[{ComponentsApi.LayoutAttribute.FullTypeName}(typeof({token.Content}))]",
            });

            // Insert the new attribute on top of the class
            for (var i = 0; i < @namespace.Children.Count; i++)
            {
                if (object.ReferenceEquals(@namespace.Children[i], @class))
                {
                    @namespace.Children.Insert(i, attributeNode);
                    break;
                }
            }
        }
コード例 #27
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            ClassDeclarationIntermediateNode primaryClass = documentNode.FindPrimaryClass();

            if (primaryClass == null)
            {
                return;
            }

            string fullClassName = null;

            foreach (IntermediateNodeReference directiveReference in documentNode.FindDirectiveReferences(InheritsDirective.Directive))
            {
                DirectiveTokenIntermediateNode intermediateNode =
                    ((DirectiveIntermediateNode)directiveReference.Node).Tokens
                    .FirstOrDefault <DirectiveTokenIntermediateNode>();
                if (intermediateNode != null)
                {
                    fullClassName = intermediateNode.Content;
                    break;
                }
            }
            if (fullClassName == null)
            {
                return;
            }


            if (PartialClassMode)
            {
                var info = new TypeReferenceInfo(fullClassName);

                var pns = documentNode.FindPrimaryNamespace().Content = info.Namespace;
                primaryClass.BaseType = null;
                primaryClass.Modifiers.Add("partial");
                primaryClass.ClassName = info.Name;
            }
            else
            {
                primaryClass.BaseType = fullClassName;
            }
        }
コード例 #28
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (!Enabled)
            {
                return;
            }
            var primary = documentNode.FindPrimaryClass();

            if (string.IsNullOrWhiteSpace(primary.BaseType) || !primary.BaseType.Contains("."))
            {
                throw new InvalidOperationException("Invalid base type");
            }
            var baseType = new TypeReferenceInfo(primary.BaseType);

            if (baseType.GenericTypeArguments.Count < 1)
            {
                throw new InvalidOperationException("Invalid base type");
            }

            var ctor = new StringBuilder();

            ctor.AppendLine($"public {primary.ClassName}({baseType.GenericTypeArguments[0]} props,");
            ctor.AppendLine("params Bridge.Union<Bridge.React.ReactElement, string>[] children) : ");
            ctor.AppendLine("base(props, children){}");


            primary.Children.Add(new CSharpCodeIntermediateNode()
            {
                Children =
                {
                    new IntermediateToken()
                    {
                        Kind    = TokenKind.CSharp,
                        Content = ctor.ToString()
                    }
                }
            });
        }
コード例 #29
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @class = documentNode.FindPrimaryClass();

            if (@class == null)
            {
                return;
            }

            if (@class.Interfaces == null)
            {
                @class.Interfaces = new List <string>();
            }

            foreach (var implements in documentNode.FindDirectiveReferences(ImplementsDirective.Directive))
            {
                var token = ((DirectiveIntermediateNode)implements.Node).Tokens.FirstOrDefault();
                if (token != null)
                {
                    @class.Interfaces.Add(token.Content);
                }
            }
        }
コード例 #30
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            var @class = documentNode.FindPrimaryClass();

            if (@class == null)
            {
                return;
            }

            foreach (var directive in documentNode.FindDirectiveReferences(SectionDirective.Directive))
            {
                var sectionName = ((DirectiveIntermediateNode)directive.Node).Tokens.FirstOrDefault()?.Content;

                var section = new SectionIntermediateNode()
                {
                    SectionName = sectionName,
                };

                var i = 0;
                for (; i < directive.Node.Children.Count; i++)
                {
                    if (!(directive.Node.Children[i] is DirectiveTokenIntermediateNode))
                    {
                        break;
                    }
                }

                while (i != directive.Node.Children.Count)
                {
                    // Move non-token children over to the section node so we don't have double references to children nodes.
                    section.Children.Add(directive.Node.Children[i]);
                    directive.Node.Children.RemoveAt(i);
                }

                directive.InsertAfter(section);
            }
        }