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)); } }
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)); } } }
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); } }
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); } } } }
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(); } }
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, }); }
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); }
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]); } }
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); } } } }
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); } } }
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); }
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)); } } } }
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); }
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);
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)); } } }
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]); } } } }
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); }
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); } }
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 }); }
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)); } } }
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); }
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]); } } }
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); }
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); } }
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; } } }
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; } } }
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; } }
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() } } }); }
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); } } }
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); } }