Esempio n. 1
0
        public void WriteSetPreallocatedTagHelperProperty_IndexerAttribute_MultipleValues()
        {
            // Arrange
            var extension = new PreallocatedAttributeTargetExtension();
            var context   = TestCodeRenderingContext.CreateRuntime();

            var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "FooTagHelper", "Test");

            tagHelperBuilder.TypeName("FooTagHelper");

            var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);

            builder
            .Name("Foo")
            .TypeName("System.Collections.Generic.Dictionary<System.String, System.String>")
            .AsDictionaryAttribute("pre-", "System.String")
            .PropertyName("FooProp");

            var boundAttribute = builder.Build();
            var tagHelper      = tagHelperBuilder.Build();

            var tagHelperNode = new TagHelperIntermediateNode();
            var node1         = new PreallocatedTagHelperPropertyIntermediateNode()
            {
                AttributeName      = "pre-Bar",
                FieldName          = "__FooTagHelper",
                VariableName       = "_tagHelper0s",
                BoundAttribute     = boundAttribute,
                IsIndexerNameMatch = true,
                PropertyName       = "FooProp",
                TagHelper          = tagHelper,
            };
            var node2 = new PreallocatedTagHelperPropertyIntermediateNode()
            {
                AttributeName      = "pre-Foo",
                FieldName          = "__FooTagHelper",
                VariableName       = "_tagHelper1",
                BoundAttribute     = boundAttribute,
                IsIndexerNameMatch = true,
                PropertyName       = "FooProp",
                TagHelper          = tagHelper,
            };

            tagHelperNode.Children.Add(node1);
            tagHelperNode.Children.Add(node2);
            Push(context, tagHelperNode);

            // Act
            extension.WriteTagHelperProperty(context, node2);

            // Assert
            var csharp = context.CodeWriter.GenerateCode();

            Assert.Equal(
                @"__FooTagHelper.FooProp[""Foo""] = (string)_tagHelper1.Value;
__tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1);
",
                csharp,
                ignoreLineEndingDifferences: true);
        }
Esempio n. 2
0
            public void VisitExtension(DefaultTagHelperPropertyIntermediateNode node)
            {
                if (!(node.BoundAttribute.IsStringProperty || (node.IsIndexerNameMatch && node.BoundAttribute.IsIndexerStringProperty)) ||
                    node.Children.Count != 1 ||
                    !(node.Children.First() is HtmlContentIntermediateNode))
                {
                    return;
                }

                var htmlContentNode = node.Children.First() as HtmlContentIntermediateNode;
                var plainTextValue  = GetContent(htmlContentNode);

                PreallocatedTagHelperPropertyValueIntermediateNode declaration = null;

                for (var i = 0; i < _classDeclaration.Children.Count; i++)
                {
                    var current = _classDeclaration.Children[i];

                    if (current is PreallocatedTagHelperPropertyValueIntermediateNode existingDeclaration)
                    {
                        if (string.Equals(existingDeclaration.AttributeName, node.AttributeName, StringComparison.Ordinal) &&
                            string.Equals(existingDeclaration.Value, plainTextValue, StringComparison.Ordinal) &&
                            existingDeclaration.AttributeStructure == node.AttributeStructure)
                        {
                            declaration = existingDeclaration;
                            break;
                        }
                    }
                }

                if (declaration == null)
                {
                    var variableCount = _classDeclaration.Children.Count - _variableCountOffset;
                    var preAllocatedAttributeVariableName = PreAllocatedAttributeVariablePrefix + variableCount;
                    declaration = new PreallocatedTagHelperPropertyValueIntermediateNode()
                    {
                        VariableName       = preAllocatedAttributeVariableName,
                        AttributeName      = node.AttributeName,
                        Value              = plainTextValue,
                        AttributeStructure = node.AttributeStructure,
                    };
                    _classDeclaration.Children.Insert(_preallocatedDeclarationCount++, declaration);
                }

                var setPreallocatedProperty = new PreallocatedTagHelperPropertyIntermediateNode(node)
                {
                    VariableName = declaration.VariableName,
                };

                var nodeIndex = Parent.Children.IndexOf(node);

                Parent.Children[nodeIndex] = setPreallocatedProperty;
            }
        private static string GetPropertyAccessor(PreallocatedTagHelperPropertyIntermediateNode node)
        {
            var propertyAccessor = $"{node.FieldName}.{node.PropertyName}";

            if (node.IsIndexerNameMatch)
            {
                var dictionaryKey = node.AttributeName.Substring(node.BoundAttribute.IndexerNamePrefix.Length);
                propertyAccessor += $"[\"{dictionaryKey}\"]";
            }

            return(propertyAccessor);
        }
        public void WriteTagHelperProperty(CodeRenderingContext context, PreallocatedTagHelperPropertyIntermediateNode node)
        {
            var tagHelperNode = context.Parent as TagHelperIntermediateNode;

            if (tagHelperNode == null)
            {
                var message = Resources.FormatIntermediateNodes_InvalidParentNode(node.GetType(), typeof(TagHelperIntermediateNode));
                throw new InvalidOperationException(message);
            }

            // Ensure that the property we're trying to set has initialized its dictionary bound properties.
            if (node.IsIndexerNameMatch &&
                object.ReferenceEquals(FindFirstUseOfIndexer(tagHelperNode, node), node))
            {
                // Throw a reasonable Exception at runtime if the dictionary property is null.
                context.CodeWriter
                .Write("if (")
                .Write(node.FieldName)
                .Write(".")
                .Write(node.PropertyName)
                .WriteLine(" == null)");
                using (context.CodeWriter.BuildScope())
                {
                    // System is in Host.NamespaceImports for all MVC scenarios. No need to generate FullName
                    // of InvalidOperationException type.
                    context.CodeWriter
                    .Write("throw ")
                    .WriteStartNewObject(nameof(InvalidOperationException))
                    .WriteStartMethodInvocation(FormatInvalidIndexerAssignmentMethodName)
                    .WriteStringLiteral(node.AttributeName)
                    .WriteParameterSeparator()
                    .WriteStringLiteral(node.TagHelper.GetTypeName())
                    .WriteParameterSeparator()
                    .WriteStringLiteral(node.PropertyName)
                    .WriteEndMethodInvocation(endLine: false) // End of method call
                    .WriteEndMethodInvocation();              // End of new expression / throw statement
                }
            }

            context.CodeWriter
            .WriteStartAssignment(GetPropertyAccessor(node))
            .Write("(string)")
            .Write($"{node.VariableName}.Value")
            .WriteLine(";")
            .WriteStartInstanceMethodInvocation(ExecutionContextVariableName, ExecutionContextAddTagHelperAttributeMethodName)
            .Write(node.VariableName)
            .WriteEndMethodInvocation();
        }
Esempio n. 5
0
        public void WriteTagHelperProperty_RendersCorrectly()
        {
            // Arrange
            var extension = new PreallocatedAttributeTargetExtension();
            var context   = TestCodeRenderingContext.CreateRuntime();

            var tagHelperBuilder = new DefaultTagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "FooTagHelper", "Test");

            tagHelperBuilder.TypeName("FooTagHelper");

            var builder = new DefaultBoundAttributeDescriptorBuilder(tagHelperBuilder, TagHelperConventions.DefaultKind);

            builder
            .Name("Foo")
            .TypeName("System.String")
            .PropertyName("FooProp");

            var descriptor = builder.Build();

            var tagHelperNode = new TagHelperIntermediateNode();
            var node          = new PreallocatedTagHelperPropertyIntermediateNode()
            {
                AttributeName  = descriptor.Name,
                BoundAttribute = descriptor,
                FieldName      = "__FooTagHelper",
                PropertyName   = "FooProp",
                VariableName   = "_tagHelper1",
            };

            tagHelperNode.Children.Add(node);
            Push(context, tagHelperNode);

            // Act
            extension.WriteTagHelperProperty(context, node);

            // Assert
            var csharp = context.CodeWriter.GenerateCode();

            Assert.Equal(
                @"__FooTagHelper.FooProp = (string)_tagHelper1.Value;
__tagHelperExecutionContext.AddTagHelperAttribute(_tagHelper1);
",
                csharp,
                ignoreLineEndingDifferences: true);
        }
        private static PreallocatedTagHelperPropertyIntermediateNode FindFirstUseOfIndexer(
            TagHelperIntermediateNode tagHelperNode,
            PreallocatedTagHelperPropertyIntermediateNode propertyNode)
        {
            Debug.Assert(tagHelperNode.Children.Contains(propertyNode));
            Debug.Assert(propertyNode.IsIndexerNameMatch);

            for (var i = 0; i < tagHelperNode.Children.Count; i++)
            {
                if (tagHelperNode.Children[i] is PreallocatedTagHelperPropertyIntermediateNode otherPropertyNode &&
                    otherPropertyNode.TagHelper.Equals(propertyNode.TagHelper) &&
                    otherPropertyNode.BoundAttribute.Equals(propertyNode.BoundAttribute) &&
                    otherPropertyNode.IsIndexerNameMatch)
                {
                    return(otherPropertyNode);
                }
            }

            // This is unreachable, we should find 'propertyNode' in the list of children.
            throw new InvalidOperationException();
        }