public void TagHelpers_CanReplaceAttributeChunkGeneratorLogic()
        {
            // Arrange
            var inputTypePropertyInfo = typeof(TestType).GetProperty("Type");
            var checkedPropertyInfo = typeof(TestType).GetProperty("Checked");
            var tagHelperDescriptors = new TagHelperDescriptor[]
            {
                new TagHelperDescriptor
                {
                    TagName = "p",
                    TypeName = "PTagHelper",
                    AssemblyName = "SomeAssembly"
                },
                new TagHelperDescriptor
                {
                    TagName = "input",
                    TypeName = "InputTagHelper",
                    AssemblyName = "SomeAssembly",
                    Attributes = new TagHelperAttributeDescriptor[]
                    {
                        new TagHelperAttributeDescriptor("type", inputTypePropertyInfo)
                    },
                    TagStructure = TagStructure.WithoutEndTag
                },
                new TagHelperDescriptor
                {
                    TagName = "input",
                    TypeName = "InputTagHelper2",
                    AssemblyName = "SomeAssembly",
                    Attributes = new TagHelperAttributeDescriptor[]
                    {
                        new TagHelperAttributeDescriptor("type", inputTypePropertyInfo),
                        new TagHelperAttributeDescriptor("checked", checkedPropertyInfo)
                    }
                }
            };

            // Act & Assert
            RunTagHelperTest(testName: "BasicTagHelpers",
                             baseLineName: "BasicTagHelpers.CustomAttributeCodeGenerator",
                             tagHelperDescriptors: tagHelperDescriptors,
                             hostConfig: (host) =>
                             {
                                 return new CodeGeneratorReplacingHost(host);
                             });
        }
예제 #2
0
        public void TagHelperDescriptor_CanBeSerialized()
        {
            // Arrange
            var descriptor = new TagHelperDescriptor
            {
                Prefix = "prefix:",
                TagName = "tag name",
                TypeName = "type name",
                AssemblyName =  "assembly name",
                RequiredAttributes = new[] { "required attribute one", "required attribute two" },
                AllowedChildren = new[] { "allowed child one" },
                RequiredParent = "parent name",
                DesignTimeDescriptor = new TagHelperDesignTimeDescriptor
                {
                    Summary = "usage summary",
                    Remarks = "usage remarks",
                    OutputElementHint = "some-tag"
                },
            };

            var expectedSerializedDescriptor =
                $"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
                $"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
                $"\"{ nameof(TagHelperDescriptor.FullTagName) }\":\"prefix:tag name\"," +
                $"\"{ nameof(TagHelperDescriptor.TypeName) }\":\"type name\"," +
                $"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," +
                $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[]," +
                $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":" +
                "[\"required attribute one\",\"required attribute two\"]," +
                $"\"{ nameof(TagHelperDescriptor.AllowedChildren) }\":[\"allowed child one\"]," +
                $"\"{ nameof(TagHelperDescriptor.RequiredParent) }\":\"parent name\"," +
                $"\"{ nameof(TagHelperDescriptor.TagStructure) }\":0," +
                $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":{{"+
                $"\"{ nameof(TagHelperDesignTimeDescriptor.Summary) }\":\"usage summary\"," +
                $"\"{ nameof(TagHelperDesignTimeDescriptor.Remarks) }\":\"usage remarks\"," +
                $"\"{ nameof(TagHelperDesignTimeDescriptor.OutputElementHint) }\":\"some-tag\"}}}}";

            // Act
            var serializedDescriptor = JsonConvert.SerializeObject(descriptor);

            // Assert
            Assert.Equal(expectedSerializedDescriptor, serializedDescriptor, StringComparer.Ordinal);
        }
        public void CreateDescriptor_OnlyAcceptsPropertiesWithGetAndSet()
        {
            // Arrange
            var validProperty = typeof(MissingAccessorTagHelper).GetProperty(
                nameof(MissingAccessorTagHelper.ValidAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "missing-accessor",
                typeof(MissingAccessorTagHelper).FullName,
                AssemblyName,
                new[] {
                new TagHelperAttributeDescriptor("valid-attribute", validProperty)
            });

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(MissingAccessorTagHelper));

            // Assert
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
        }
예제 #4
0
    public void GetDescriptors_DuplicateDescriptorsAreNotPartOfTagHelperDescriptorPool()
    {
        // Arrange
        var divDescriptor = TagHelperDescriptorBuilder.Create("foo1", "SomeAssembly")
                            .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
                            .Build();
        var descriptors     = new TagHelperDescriptor[] { divDescriptor, divDescriptor };
        var tagHelperBinder = new TagHelperBinder(null, descriptors);

        // Act
        var bindingResult = tagHelperBinder.GetBinding(
            tagName: "div",
            attributes: Array.Empty <KeyValuePair <string, string> >(),
            parentTagName: "p",
            parentIsTagHelper: false);

        // Assert
        var descriptor = Assert.Single(bindingResult.Descriptors);

        Assert.Same(divDescriptor, descriptor);
    }
        public void CreateDescriptor_DoesntResolveInheritedTagNames()
        {
            // Arrange
            var validProp          = typeof(InheritedMultiTagTagHelper).GetProperty(nameof(InheritedMultiTagTagHelper.ValidAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "InheritedMultiTag",
                typeof(InheritedMultiTagTagHelper).FullName,
                AssemblyName,
                ContentBehavior.None,
                new[] {
                new TagHelperAttributeDescriptor(nameof(InheritedMultiTagTagHelper.ValidAttribute), validProp)
            });

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(InheritedMultiTagTagHelper));

            // Assert
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
        }
        public void CreateDescriptor_BuildsDescriptorsWithInheritedProperties()
        {
            // Arrange
            var intProperty = typeof(InheritedSingleAttributeTagHelper).GetProperty(
                nameof(InheritedSingleAttributeTagHelper.IntAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "inherited-single-attribute",
                typeof(InheritedSingleAttributeTagHelper).FullName,
                AssemblyName,
                new[] {
                new TagHelperAttributeDescriptor("int-attribute", intProperty)
            });

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(InheritedSingleAttributeTagHelper));

            // Assert
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
        }
        public void CreateDescriptor_BuildsDescriptorsWithConventionNames()
        {
            // Arrange
            var intProperty        = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "SingleAttribute",
                typeof(SingleAttributeTagHelper).FullName,
                AssemblyName,
                ContentBehavior.None,
                new[] {
                new TagHelperAttributeDescriptor(nameof(SingleAttributeTagHelper.IntAttribute), intProperty)
            });

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(SingleAttributeTagHelper));

            // Assert
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
        }
예제 #8
0
        public async Task EnqueuePublish_OnProjectBeforeTagHelperProcessed_DoesNotPublish()
        {
            // Arrange
            var serializationSuccessful = false;
            var firstSnapshot           = CreateProjectSnapshot("/path/to/project.csproj");
            var tagHelpers = new TagHelperDescriptor[] {
                new DefaultTagHelperDescriptor(FileKinds.Component, "Namespace.FileNameOther", "Assembly", "FileName", "FileName document", "FileName hint",
                                               caseSensitive: false, tagMatchingRules: null, attributeDescriptors: null, allowedChildTags: null, metadata: null, diagnostics: null)
            };
            var secondSnapshot = CreateProjectSnapshot("/path/to/project.csproj", new ProjectWorkspaceState(tagHelpers, CodeAnalysis.CSharp.LanguageVersion.CSharp8), new string[] {
                "FileName.razor"
            });
            var expectedConfigurationFilePath = "/path/to/obj/bin/Debug/project.razor.json";
            var publisher = new TestDefaultRazorProjectChangePublisher(
                ProjectConfigurationFilePathStore,
                _razorLogger,
                onSerializeToFile: (snapshot, configurationFilePath) =>
            {
                Assert.Same(secondSnapshot, snapshot);
                Assert.Equal(expectedConfigurationFilePath, configurationFilePath);
                serializationSuccessful = true;
            },
                useRealShouldSerialize: true)
            {
                EnqueueDelay = 10,
                _active      = true,
            };

            publisher.Initialize(ProjectSnapshotManager);
            ProjectConfigurationFilePathStore.Set(firstSnapshot.FilePath, expectedConfigurationFilePath);

            // Act
            publisher.EnqueuePublish(secondSnapshot);

            // Assert
            var kvp = Assert.Single(publisher.DeferredPublishTasks);
            await kvp.Value.ConfigureAwait(false);

            Assert.False(serializationSuccessful);
        }
예제 #9
0
        public async Task ProjectManager_Changed_Remove_Change_NoopsOnDelayedPublish()
        {
            // Arrange
            var serializationSuccessful = false;
            var tagHelpers = new TagHelperDescriptor[] {
                new DefaultTagHelperDescriptor(FileKinds.Component, "Namespace.FileNameOther", "Assembly", "FileName", "FileName document", "FileName hint",
                                               caseSensitive: false, tagMatchingRules: null, attributeDescriptors: null, allowedChildTags: null, metadata: null, diagnostics: null)
            };
            var initialProjectSnapshot        = CreateProjectSnapshot("/path/to/project.csproj", new ProjectWorkspaceState(tagHelpers, CodeAnalysis.CSharp.LanguageVersion.Preview));
            var expectedProjectSnapshot       = CreateProjectSnapshot("/path/to/project.csproj", new ProjectWorkspaceState(ImmutableArray <TagHelperDescriptor> .Empty, CodeAnalysis.CSharp.LanguageVersion.Preview));
            var expectedConfigurationFilePath = "/path/to/obj/bin/Debug/project.razor.json";
            var publisher = new TestDefaultRazorProjectChangePublisher(
                ProjectConfigurationFilePathStore,
                _razorLogger,
                onSerializeToFile: (snapshot, configurationFilePath) =>
            {
                Assert.Same(expectedProjectSnapshot, snapshot);
                Assert.Equal(expectedConfigurationFilePath, configurationFilePath);
                serializationSuccessful = true;
            })
            {
                EnqueueDelay = 10,
                _active      = true,
            };

            publisher.Initialize(ProjectSnapshotManager);
            ProjectConfigurationFilePathStore.Set(expectedProjectSnapshot.FilePath, expectedConfigurationFilePath);
            var documentRemovedArgs = ProjectChangeEventArgs.CreateTestInstance(initialProjectSnapshot, initialProjectSnapshot, documentFilePath: "/path/to/file.razor", ProjectChangeKind.DocumentRemoved);
            var projectChangedArgs  = ProjectChangeEventArgs.CreateTestInstance(initialProjectSnapshot, expectedProjectSnapshot, documentFilePath: null, ProjectChangeKind.ProjectChanged);

            // Act
            publisher.ProjectSnapshotManager_Changed(null, documentRemovedArgs);
            publisher.ProjectSnapshotManager_Changed(null, projectChangedArgs);

            // Assert
            var stalePublishTask = Assert.Single(publisher.DeferredPublishTasks);
            await stalePublishTask.Value.ConfigureAwait(false);

            Assert.True(serializationSuccessful);
        }
예제 #10
0
        public void DescriptorResolver_ResolvesMultipleTypes()
        {
            // Arrange
            var resolver = new TestTagHelperDescriptorResolver(
                new LookupBasedTagHelperTypeResolver(
                    new Dictionary <string, IEnumerable <Type> >(StringComparer.OrdinalIgnoreCase)
            {
                { AssemblyName, new Type[] { Valid_PlainTagHelperType, Valid_InheritedTagHelperType } },
            }));
            var expectedDescriptors = new TagHelperDescriptor[]
            {
                Valid_PlainTagHelperDescriptor,
                Valid_InheritedTagHelperDescriptor
            };

            // Act
            var descriptors = resolver.Resolve(AssemblyName).ToArray();

            // Assert
            Assert.Equal(descriptors.Length, 2);
            Assert.Equal(expectedDescriptors, descriptors, CompleteTagHelperDescriptorComparer.Default);
        }
예제 #11
0
    public void GetDescriptors_ReturnsNothingForUnregisteredTags()
    {
        // Arrange
        var divDescriptor = TagHelperDescriptorBuilder.Create("foo1", "SomeAssembly")
                            .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
                            .Build();
        var spanDescriptor = TagHelperDescriptorBuilder.Create("foo2", "SomeAssembly")
                             .TagMatchingRuleDescriptor(rule => rule.RequireTagName("span"))
                             .Build();
        var descriptors     = new TagHelperDescriptor[] { divDescriptor, spanDescriptor };
        var tagHelperBinder = new TagHelperBinder(null, descriptors);

        // Act
        var tagHelperBinding = tagHelperBinder.GetBinding(
            tagName: "foo",
            attributes: Array.Empty <KeyValuePair <string, string> >(),
            parentTagName: "p",
            parentIsTagHelper: false);

        // Assert
        Assert.Null(tagHelperBinding);
    }
예제 #12
0
    private void Register(TagHelperDescriptor descriptor)
    {
        var count = descriptor.TagMatchingRules.Count;

        for (var i = 0; i < count; i++)
        {
            var rule            = descriptor.TagMatchingRules[i];
            var registrationKey =
                string.Equals(rule.TagName, TagHelperMatchingConventions.ElementCatchAllName, StringComparison.Ordinal) ?
                TagHelperMatchingConventions.ElementCatchAllName :
                _tagHelperPrefix + rule.TagName;

            // Ensure there's a HashSet to add the descriptor to.
            if (!_registrations.TryGetValue(registrationKey, out HashSet <TagHelperDescriptor> descriptorSet))
            {
                descriptorSet = new HashSet <TagHelperDescriptor>(TagHelperDescriptorComparer.Default);
                _registrations[registrationKey] = descriptorSet;
            }

            descriptorSet.Add(descriptor);
        }
    }
예제 #13
0
        public void CreateDescriptor_OnlyAcceptsPropertiesWithPublicGetAndSet()
        {
            // Arrange
            var validProperty = typeof(PrivateAccessorTagHelper).GetProperty(
                nameof(PrivateAccessorTagHelper.ValidAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "PrivateAccessor",
                typeof(PrivateAccessorTagHelper).FullName,
                ContentBehavior.None,
                new[] {
                new TagHelperAttributeDescriptor(
                    nameof(PrivateAccessorTagHelper.ValidAttribute), validProperty)
            });

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(typeof(PrivateAccessorTagHelper));

            // Assert
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
        }
        public override int GetHashCode(TagHelperDescriptor descriptor)
        {
            var hashCodeCombiner = HashCodeCombiner.Start();

            hashCodeCombiner.Add(base.GetHashCode(descriptor));
            hashCodeCombiner.Add(descriptor.TagName, StringComparer.Ordinal);
            hashCodeCombiner.Add(descriptor.Prefix, StringComparer.Ordinal);

            if (descriptor.DesignTimeDescriptor != null)
            {
                hashCodeCombiner.Add(
                    TagHelperDesignTimeDescriptorComparer.Default.GetHashCode(descriptor.DesignTimeDescriptor));
            }

            foreach (var requiredAttribute in descriptor.RequiredAttributes.OrderBy(attribute => attribute.Name))
            {
                hashCodeCombiner.Add(
                    CaseSensitiveTagHelperRequiredAttributeDescriptorComparer.Default.GetHashCode(requiredAttribute));
            }

            if (descriptor.AllowedChildren != null)
            {
                foreach (var child in descriptor.AllowedChildren.OrderBy(child => child))
                {
                    hashCodeCombiner.Add(child, StringComparer.Ordinal);
                }
            }

            var orderedAttributeHashCodes = descriptor.Attributes
                                            .Select(attribute => TagHelperAttributeDescriptorComparer.Default.GetHashCode(attribute))
                                            .OrderBy(hashcode => hashcode);

            foreach (var attributeHashCode in orderedAttributeHashCodes)
            {
                hashCodeCombiner.Add(attributeHashCode);
            }

            return(hashCodeCombiner.CombinedHash);
        }
        private static bool MatchesLookupInfo(TagHelperDescriptor descriptor, LookupInfo lookupInfo)
        {
            if (!string.Equals(descriptor.AssemblyName, lookupInfo.AssemblyName, StringComparison.Ordinal))
            {
                return(false);
            }

            if (lookupInfo.TypePattern.EndsWith("*", StringComparison.Ordinal))
            {
                if (lookupInfo.TypePattern.Length == 1)
                {
                    // TypePattern is "*".
                    return(true);
                }

                var lookupTypeName = lookupInfo.TypePattern.Substring(0, lookupInfo.TypePattern.Length - 1);

                return(descriptor.TypeName.StartsWith(lookupTypeName, StringComparison.Ordinal));
            }

            return(string.Equals(descriptor.TypeName, lookupInfo.TypePattern, StringComparison.Ordinal));
        }
        public void DescriptorResolver_ResolvesOnlyTypeResolverProvidedTypes()
        {
            // Arrange
            var resolver = new TagHelperDescriptorResolver(
                new LookupBasedTagHelperTypeResolver(
                    new Dictionary <string, IEnumerable <Type> >(StringComparer.OrdinalIgnoreCase)
            {
                { "lookupText1", ValidTestableTagHelpers },
                { "lookupText2", new Type[] { typeof(Valid_PlainTagHelper) } }
            }));
            var expectedDescriptor = new TagHelperDescriptor("Valid_Plain",
                                                             typeof(Valid_PlainTagHelper).FullName,
                                                             ContentBehavior.None);

            // Act
            var descriptors = resolver.Resolve("lookupText2");

            // Assert
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(descriptor, expectedDescriptor, CompleteTagHelperDescriptorComparer.Default);
        }
예제 #17
0
    public void GetDescriptors_ReturnsCatchAllsWithEveryTagName()
    {
        // Arrange
        var divDescriptor = TagHelperDescriptorBuilder.Create("foo1", "SomeAssembly")
                            .TagMatchingRuleDescriptor(rule => rule.RequireTagName("div"))
                            .Build();
        var spanDescriptor = TagHelperDescriptorBuilder.Create("foo2", "SomeAssembly")
                             .TagMatchingRuleDescriptor(rule => rule.RequireTagName("span"))
                             .Build();
        var catchAllDescriptor = TagHelperDescriptorBuilder.Create("foo3", "SomeAssembly")
                                 .TagMatchingRuleDescriptor(rule => rule.RequireTagName(TagHelperMatchingConventions.ElementCatchAllName))
                                 .Build();
        var descriptors     = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
        var tagHelperBinder = new TagHelperBinder(null, descriptors);

        // Act
        var divBinding = tagHelperBinder.GetBinding(
            tagName: "div",
            attributes: Array.Empty <KeyValuePair <string, string> >(),
            parentTagName: "p",
            parentIsTagHelper: false);
        var spanBinding = tagHelperBinder.GetBinding(
            tagName: "span",
            attributes: Array.Empty <KeyValuePair <string, string> >(),
            parentTagName: "p",
            parentIsTagHelper: false);

        // Assert
        // For divs
        Assert.Equal(2, divBinding.Descriptors.Count());
        Assert.Contains(divDescriptor, divBinding.Descriptors);
        Assert.Contains(catchAllDescriptor, divBinding.Descriptors);

        // For spans
        Assert.Equal(2, spanBinding.Descriptors.Count());
        Assert.Contains(spanDescriptor, spanBinding.Descriptors);
        Assert.Contains(catchAllDescriptor, spanBinding.Descriptors);
    }
예제 #18
0
            public TagHelperDescriptor GetTagHelperDescriptorOne()
            {
                var descriptor = new TagHelperDescriptor
                {
                    TagName      = "vc:one",
                    TypeName     = "__Generated__OneViewComponentTagHelper",
                    AssemblyName = "Microsoft.AspNetCore.Mvc.Razor",
                    Attributes   = new List <TagHelperAttributeDescriptor>
                    {
                        new TagHelperAttributeDescriptor
                        {
                            Name         = "foo",
                            PropertyName = "foo",
                            TypeName     = typeof(string).FullName
                        },
                        new TagHelperAttributeDescriptor
                        {
                            Name         = "bar",
                            PropertyName = "bar",
                            TypeName     = typeof(string).FullName
                        }
                    },
                    RequiredAttributes = new List <TagHelperRequiredAttributeDescriptor>
                    {
                        new TagHelperRequiredAttributeDescriptor
                        {
                            Name = "foo"
                        },
                        new TagHelperRequiredAttributeDescriptor
                        {
                            Name = "bar"
                        }
                    }
                };

                descriptor.PropertyBag.Add(ViewComponentTagHelperDescriptorConventions.ViewComponentNameKey, "One");
                return(descriptor);
            }
        public void DescriptorResolver_IgnoresSpaces(string lookupText)
        {
            // Arrange
            var tagHelperTypeResolver = new TestTagHelperTypeResolver(TestableTagHelpers)
            {
                OnGetLibraryDefinedTypes = (assemblyName) =>
                {
                    Assert.Equal("MyAssembly", assemblyName.Name);
                }
            };
            var tagHelperDescriptorResolver = new TagHelperDescriptorResolver(tagHelperTypeResolver);
            var expectedDescriptor          = new TagHelperDescriptor("Valid_Plain",
                                                                      typeof(Valid_PlainTagHelper).FullName,
                                                                      ContentBehavior.None);

            // Act
            var descriptors = tagHelperDescriptorResolver.Resolve(lookupText);

            // Assert
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CompleteTagHelperDescriptorComparer.Default);
        }
        public override bool Equals(TagHelperDescriptor descriptorX, TagHelperDescriptor descriptorY)
        {
            if (descriptorX == descriptorY)
            {
                return(true);
            }

            return(base.Equals(descriptorX, descriptorY) &&
                   // Normal comparer doesn't care about the case, required attribute order, attributes or prefixes.
                   // In tests we do.
                   string.Equals(descriptorX.TagName, descriptorY.TagName, StringComparison.Ordinal) &&
                   string.Equals(descriptorX.Prefix, descriptorY.Prefix, StringComparison.Ordinal) &&
                   Enumerable.SequenceEqual(
                       descriptorX.RequiredAttributes,
                       descriptorY.RequiredAttributes,
                       StringComparer.Ordinal) &&
                   descriptorX.Attributes.SequenceEqual(
                       descriptorY.Attributes,
                       TagHelperAttributeDescriptorComparer.Default) &&
                   TagHelperDesignTimeDescriptorComparer.Default.Equals(
                       descriptorX.DesignTimeDescriptor,
                       descriptorY.DesignTimeDescriptor));
        }
예제 #21
0
        private static void ValidateBinding(
            TagHelperBinding bindingResult,
            string tagName,
            Block tagBlock,
            ErrorSink errorSink)
        {
            // Ensure that all descriptors associated with this tag have appropriate TagStructures. Cannot have
            // multiple descriptors that expect different TagStructures (other than TagStructure.Unspecified).
            TagHelperDescriptor baseDescriptor = null;
            TagStructure?       baseStructure  = null;

            foreach (var descriptor in bindingResult.Descriptors)
            {
                var boundRules = bindingResult.GetBoundRules(descriptor);
                foreach (var rule in boundRules)
                {
                    if (rule.TagStructure != TagStructure.Unspecified)
                    {
                        // Can't have a set of TagHelpers that expect different structures.
                        if (baseStructure.HasValue && baseStructure != rule.TagStructure)
                        {
                            errorSink.OnError(
                                tagBlock.Start,
                                LegacyResources.FormatTagHelperParseTreeRewriter_InconsistentTagStructure(
                                    baseDescriptor.DisplayName,
                                    descriptor.DisplayName,
                                    tagName,
                                    nameof(TagMatchingRuleDescriptor.TagStructure)),
                                tagBlock.Length);
                        }

                        baseDescriptor = descriptor;
                        baseStructure  = rule.TagStructure;
                    }
                }
            }
        }
예제 #22
0
        private void RewriteUsage(TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
        {
            // We need to surround the contents of the node with open and close nodes to ensure the component
            // is scoped correctly.
            node.Children.Insert(0, new ComponentOpenExtensionNode()
            {
                TypeName = tagHelper.GetTypeName(),
            });

            for (var i = node.Children.Count - 1; i >= 0; i--)
            {
                if (node.Children[i] is TagHelperBodyIntermediateNode bodyNode)
                {
                    // Replace with a node that we recognize so that it we can do proper scope tracking.
                    //
                    // Note that we force the body node to be last, this is done to push it after the
                    // attribute nodes. This gives us the ordering we want for the render tree.
                    node.Children.RemoveAt(i);
                    node.Children.Add(new ComponentBodyExtensionNode(bodyNode)
                    {
                        TagMode = node.TagMode,
                        TagName = node.TagName,
                    });
                }
            }

            node.Children.Add(new ComponentCloseExtensionNode());

            // Now we need to rewrite any set property or HTML nodes to call the appropriate AddAttribute api.
            for (var i = node.Children.Count - 1; i >= 0; i--)
            {
                if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode &&
                    propertyNode.TagHelper == tagHelper)
                {
                    node.Children[i] = new ComponentAttributeExtensionNode(propertyNode);
                }
        public void TagHelperDescriptorProvider_GetTagHelpersReturnsCatchAllsWithEveryTagName()
        {
            // Arrange
            var divDescriptor      = new TagHelperDescriptor("div", "foo1", "SomeAssembly", ContentBehavior.None);
            var spanDescriptor     = new TagHelperDescriptor("span", "foo2", "SomeAssembly", ContentBehavior.None);
            var catchAllDescriptor = new TagHelperDescriptor("*", "foo3", "SomeAssembly", ContentBehavior.None);
            var descriptors        = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
            var provider           = new TagHelperDescriptorProvider(descriptors);

            // Act
            var divDescriptors  = provider.GetTagHelpers("div");
            var spanDescriptors = provider.GetTagHelpers("span");

            // Assert
            // For divs
            Assert.Equal(2, divDescriptors.Count());
            Assert.Contains(divDescriptor, divDescriptors);
            Assert.Contains(catchAllDescriptor, divDescriptors);

            // For spans
            Assert.Equal(2, spanDescriptors.Count());
            Assert.Contains(spanDescriptor, spanDescriptors);
            Assert.Contains(catchAllDescriptor, spanDescriptors);
        }
        public void Rewrite_AllowsCompatibleTagStructures(
            string documentContent,
            TagStructure structure1,
            TagStructure structure2,
            MarkupBlock expectedOutput)
        {
            // Arrange
            var factory = CreateDefaultSpanFactory();
            var blockFactory = new BlockFactory(factory);
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper1",
                        AssemblyName = "SomeAssembly",
                        TagStructure = structure1
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper2",
                        AssemblyName = "SomeAssembly",
                        TagStructure = structure2
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new RazorError[0]);
        }
        public void Rewrite_CreatesErrorForWithoutEndTagTagStructureForEndTags()
        {
            // Arrange
            var factory = CreateDefaultSpanFactory();
            var blockFactory = new BlockFactory(factory);
            var expectedError = new RazorError(
                RazorResources.FormatTagHelperParseTreeRewriter_EndTagTagHelperMustNotHaveAnEndTag(
                    "input",
                    "InputTagHelper",
                    TagStructure.WithoutEndTag),
                absoluteIndex: 2,
                lineIndex: 0,
                columnIndex: 2,
                length: 5);
            var documentContent = "</input>";
            var expectedOutput = new MarkupBlock(blockFactory.MarkupTagBlock("</input>"));
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper",
                        AssemblyName = "SomeAssembly",
                        TagStructure = TagStructure.WithoutEndTag
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new[] { expectedError });
        }
        public void Rewrite_CanHandleStartTagOnlyTagTagMode()
        {
            // Arrange
            var documentContent = "<input>";
            var expectedOutput = new MarkupBlock(new MarkupTagHelperBlock("input", TagMode.StartTagOnly));
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper",
                        AssemblyName = "SomeAssembly",
                        TagStructure = TagStructure.WithoutEndTag
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new RazorError[0]);
        }
        public void DescriptorResolver_ResolvesMultipleTypes()
        {
            // Arrange
            var resolver = new TestTagHelperDescriptorResolver(
                new LookupBasedTagHelperTypeResolver(
                    new Dictionary<string, IEnumerable<Type>>(StringComparer.OrdinalIgnoreCase)
                    {
                        { AssemblyName, new Type[]{ Valid_PlainTagHelperType, Valid_InheritedTagHelperType } },
                    }));
            var expectedDescriptors = new TagHelperDescriptor[]
            {
                Valid_PlainTagHelperDescriptor,
                Valid_InheritedTagHelperDescriptor
            };

            // Act
            var descriptors = resolver.Resolve("*, " + AssemblyName).ToArray();

            // Assert
            Assert.Equal(descriptors.Length, 2);
            Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
        public void GetDescriptors_ReturnsNothingForUnregisteredTags()
        {
            // Arrange
            var divDescriptor = new TagHelperDescriptor
            {
                TagName = "div",
                TypeName = "foo1",
                AssemblyName = "SomeAssembly",
            };
            var spanDescriptor = new TagHelperDescriptor
            {
                TagName = "span",
                TypeName = "foo2",
                AssemblyName = "SomeAssembly",
            };
            var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor };
            var provider = new TagHelperDescriptorProvider(descriptors);

            // Act
            var retrievedDescriptors = provider.GetDescriptors(
                tagName: "foo",
                attributeNames: Enumerable.Empty<string>(),
                parentTagName: "p");

            // Assert
            Assert.Empty(retrievedDescriptors);
        }
        public void GetDescriptors_DuplicateDescriptorsAreNotPartOfTagHelperDescriptorPool()
        {
            // Arrange
            var divDescriptor = new TagHelperDescriptor
            {
                TagName = "div",
                TypeName = "foo1",
                AssemblyName = "SomeAssembly",
            };
            var descriptors = new TagHelperDescriptor[] { divDescriptor, divDescriptor };
            var provider = new TagHelperDescriptorProvider(descriptors);

            // Act
            var retrievedDescriptors = provider.GetDescriptors(
                tagName: "div",
                attributeNames: Enumerable.Empty<string>(),
                parentTagName: "p");

            // Assert
            var descriptor = Assert.Single(retrievedDescriptors);
            Assert.Same(divDescriptor, descriptor);
        }
예제 #30
0
        public void TagHelperDescriptor_WithAttributes_CanBeDeserialized()
        {
            // Arrange
            var serializedDescriptor =
                $"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
                $"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
                $"\"{ nameof(TagHelperDescriptor.FullTagName) }\":\"prefix:tag name\"," +
                $"\"{ nameof(TagHelperDescriptor.TypeName) }\":\"type name\"," +
                $"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," +
                $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[" +
                $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
                $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," +
                $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
                $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
                $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
                $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
                $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
                $"\"{ nameof(TagHelperDescriptor.AllowedChildren) }\":null," +
                $"\"{ nameof(TagHelperDescriptor.RequiredParent) }\":null," +
                $"\"{nameof(TagHelperDescriptor.TagStructure)}\":0," +
                $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";
            var expectedDescriptor = new TagHelperDescriptor
            {
                Prefix = "prefix:",
                TagName = "tag name",
                TypeName = "type name",
                AssemblyName = "assembly name",
                Attributes = new[]
                {
                    new TagHelperAttributeDescriptor
                   {
                        Name = "attribute one",
                        PropertyName = "property name",
                        TypeName = "property type name"
                    },
                    new TagHelperAttributeDescriptor
                   {
                        Name = "attribute two",
                        PropertyName = "property name",
                        TypeName = typeof(string).FullName,
                        IsStringProperty = true
                    },
                },
                AllowedChildren = new[] { "allowed child one", "allowed child two" }
            };

            // Act
            var descriptor = JsonConvert.DeserializeObject<TagHelperDescriptor>(serializedDescriptor);

            // Assert
            Assert.NotNull(descriptor);
            Assert.Equal(expectedDescriptor.Prefix, descriptor.Prefix, StringComparer.Ordinal);
            Assert.Equal(expectedDescriptor.TagName, descriptor.TagName, StringComparer.Ordinal);
            Assert.Equal(expectedDescriptor.FullTagName, descriptor.FullTagName, StringComparer.Ordinal);
            Assert.Equal(expectedDescriptor.TypeName, descriptor.TypeName, StringComparer.Ordinal);
            Assert.Equal(expectedDescriptor.AssemblyName, descriptor.AssemblyName, StringComparer.Ordinal);
            Assert.Equal(expectedDescriptor.Attributes, descriptor.Attributes, TagHelperAttributeDescriptorComparer.Default);
            Assert.Empty(descriptor.RequiredAttributes);
        }
        public void Rewrite_UnderstandsNullTagNameWithAllowedChildrenForCatchAllWithPrefix()
        {
            // Arrange
            var documentContent = "<th:p></</th:p>";
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "PTagHelper",
                        AssemblyName = "SomeAssembly",
                        AllowedChildren = new[] { "custom" },
                        Prefix = "th:",
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "*",
                        TypeName = "CatchAllTagHelper",
                        AssemblyName = "SomeAssembly",
                        Prefix = "th:",
                    }
                };
            var expectedOutput = new MarkupBlock(
                new MarkupTagHelperBlock("th:p",
                    BlockFactory.MarkupTagBlock("</")));
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);
            var expectedErrors = new[]
            {
                new RazorError(
                    RazorResources.FormatTagHelperParseTreeRewriter_CannotHaveNonTagContent("th:p", "custom"),
                    absoluteIndex: 6,
                    lineIndex: 0,
                    columnIndex: 6,
                    length: 2)
            };

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
        }
 public static bool IsAttributeDescriptor(this TagHelperDescriptor d)
 {
     return(d.Metadata.TryGetValue(TagHelperMetadata.Common.ClassifyAttributesOnly, out var value) ||
            string.Equals(value, bool.TrueString, StringComparison.OrdinalIgnoreCase));
 }
예제 #33
0
 internal static bool TryGetDescriptor(int hashCode, out TagHelperDescriptor descriptor) =>
 CachedTagHelperDescriptors.TryGetValue(hashCode, out descriptor);
예제 #34
0
 public string GetFieldName(TagHelperDescriptor taghelper)
 {
     return(_tagHelpers[taghelper].fieldName);
 }
        public void Rewrite_CanHandleMultipleTagHelpersWithAllowedChildren()
        {
            // Arrange
            var factory = CreateDefaultSpanFactory();
            var documentContent = "<p><strong>Hello World</strong><br></p>";
            var expectedOutput = new MarkupBlock(
                new MarkupTagHelperBlock("p",
                    new MarkupTagHelperBlock("strong",
                        factory.Markup("Hello World")),
                    new MarkupTagHelperBlock("br", TagMode.StartTagOnly)));
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "PTagHelper1",
                        AssemblyName = "SomeAssembly",
                        AllowedChildren = new[] { "strong" }
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "PTagHelper2",
                        AssemblyName = "SomeAssembly",
                        AllowedChildren = new[] { "br" }
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "strong",
                        TypeName = "StrongTagHelper",
                        AssemblyName = "SomeAssembly"
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "br",
                        TypeName = "BRTagHelper",
                        AssemblyName = "SomeAssembly",
                        TagStructure = TagStructure.WithoutEndTag
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new RazorError[0]);
        }
 internal static string GetVariableName(TagHelperDescriptor descriptor)
 {
     return "__" + descriptor.TypeName.Replace('.', '_');
 }
예제 #37
0
        public void ProcessMessage_ResolveTagHelperDescriptors_ResolvesDesignTimeTagHelperDescriptors()
        {
            // Arrange
            var expectedSourceLocation = new SourceLocation(absoluteIndex: 1, lineIndex: 2, characterIndex: 3);
            var sourceLocationJson = JsonConvert.SerializeObject(expectedSourceLocation);
            var messageData = new JObject
            {
                { "AssemblyName", CustomTagHelperAssembly },
                { "SourceLocation", JObject.Parse(sourceLocationJson) }
            };
            var message = new JObject
            {
                { "MessageType", RazorPluginMessageTypes.ResolveTagHelperDescriptors },
                { "Data", messageData },
            };
            ResolveTagHelperDescriptorsMessage responseMessage = null;
            var messageBroker = new TestPluginMessageBroker(
                data => responseMessage = (ResolveTagHelperDescriptorsMessage)data);
            var assembly = new TestAssembly(typeof(DesignTimeTagHelper));
            var assemblyNameLookups = new Dictionary<string, Assembly>
            {
                { CustomTagHelperAssembly, assembly }
            };
            var assemblyLoadContext = new TestAssemblyLoadContext(assemblyNameLookups);
            var plugin = new RazorPlugin(messageBroker);
            var expectedDescriptor = new TagHelperDescriptor
            {
                Prefix = DefaultPrefix,
                TagName = "design-time",
                TypeName = typeof(DesignTimeTagHelper).FullName,
                AssemblyName = typeof(DesignTimeTagHelper).Assembly.GetName().Name,
                AllowedChildren = new[] { "br" },
                TagStructure = TagStructure.NormalOrSelfClosing,
                DesignTimeDescriptor = new TagHelperDesignTimeDescriptor
                {
                    OutputElementHint = "strong"
                }
            };

            // Act
            var handled = plugin.ProcessMessage(message, assemblyLoadContext);

            // Assert
            Assert.NotNull(responseMessage);
            Assert.Equal(
                RazorPluginMessageTypes.ResolveTagHelperDescriptors,
                responseMessage.MessageType,
                StringComparer.Ordinal);
            var responseData = responseMessage.Data;
            Assert.Equal(CustomTagHelperAssembly, responseData.AssemblyName, StringComparer.Ordinal);
            var actualDescriptor = Assert.Single(responseData.Descriptors);
            Assert.Equal(expectedDescriptor, actualDescriptor, CaseSensitiveTagHelperDescriptorComparer.Default);
            Assert.Empty(responseData.Errors);
            Assert.True(handled);
        }
        public void Rewrite_UnderstandsMinimizedAttributes(
            string documentContent,
            MarkupBlock expectedOutput,
            RazorError[] expectedErrors)
        {
            // Arrange
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper1",
                        AssemblyName = "SomeAssembly",
                        Attributes = new[]
                        {
                            new TagHelperAttributeDescriptor
                            {
                                Name = "bound-required-string",
                                PropertyName = "BoundRequiredString",
                                TypeName = typeof(string).FullName,
                                IsStringProperty = true
                            }
                        },
                        RequiredAttributes = new[] { "unbound-required" }
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper1",
                        AssemblyName = "SomeAssembly",
                        Attributes = new[]
                        {
                            new TagHelperAttributeDescriptor
                            {
                                Name = "bound-required-string",
                                PropertyName = "BoundRequiredString",
                                TypeName = typeof(string).FullName,
                                IsStringProperty = true
                            }
                        },
                        RequiredAttributes = new[] { "bound-required-string" }
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper2",
                        AssemblyName = "SomeAssembly",
                        Attributes = new[]
                        {
                            new TagHelperAttributeDescriptor
                            {
                                Name = "bound-required-int",
                                PropertyName = "BoundRequiredInt",
                                TypeName = typeof(int).FullName
                            }
                        },
                        RequiredAttributes = new[] { "bound-required-int" }
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper3",
                        AssemblyName = "SomeAssembly",
                        Attributes = new[]
                        {
                            new TagHelperAttributeDescriptor
                            {
                                Name = "int-dictionary",
                                PropertyName ="DictionaryOfIntProperty",
                                TypeName = typeof(IDictionary<string, int>).FullName
                            },
                            new TagHelperAttributeDescriptor
                            {
                                Name = "string-dictionary",
                                PropertyName = "DictionaryOfStringProperty",
                                TypeName = typeof(IDictionary<string, string>).FullName
                            },
                            new TagHelperAttributeDescriptor
                            {
                                Name = "int-prefix-",
                                PropertyName = "DictionaryOfIntProperty",
                                TypeName = typeof(int).FullName,
                                IsIndexer = true
                            },
                            new TagHelperAttributeDescriptor
                            {
                                Name = "string-prefix-",
                                PropertyName = "DictionaryOfStringProperty",
                                TypeName = typeof(string).FullName,
                                IsIndexer = true,
                                IsStringProperty = true
                            }
                        }
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "PTagHelper",
                        AssemblyName = "SomeAssembly",
                        Attributes = new[]
                        {
                            new TagHelperAttributeDescriptor
                            {
                                Name = "bound-string",
                                PropertyName = "BoundRequiredString",
                                TypeName = typeof(string).FullName,
                                IsStringProperty = true
                            },
                            new TagHelperAttributeDescriptor
                            {
                                Name = "bound-int",
                                PropertyName = "BoundRequiredString",
                                TypeName = typeof(int).FullName
                            }
                        }
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
        }
        public void Rewrite_UnderstandsAllowedChildren(
            string documentContent,
            IEnumerable<string> allowedChildren,
            MarkupBlock expectedOutput,
            RazorError[] expectedErrors)
        {
            // Arrange
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "PTagHelper",
                        AssemblyName = "SomeAssembly",
                        AllowedChildren = allowedChildren
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "strong",
                        TypeName = "StrongTagHelper",
                        AssemblyName = "SomeAssembly",
                        AllowedChildren = allowedChildren
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "br",
                        TypeName = "BRTagHelper",
                        AssemblyName = "SomeAssembly",
                        TagStructure = TagStructure.WithoutEndTag
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
        }
예제 #40
0
 public string GetClassName(TagHelperDescriptor taghelper)
 {
     return(_tagHelpers[taghelper].className);
 }
예제 #41
0
        public void TagHelperDescriptor_WithAttributes_CanBeSerialized()
        {
            // Arrange
            var descriptor = new TagHelperDescriptor
            {
                Prefix = "prefix:",
                TagName = "tag name",
                TypeName = "type name",
                AssemblyName = "assembly name",
                Attributes = new[]
                {
                   new TagHelperAttributeDescriptor
                   {
                        Name = "attribute one",
                        PropertyName = "property name",
                        TypeName = "property type name"
                   },
                    new TagHelperAttributeDescriptor
                   {
                        Name = "attribute two",
                        PropertyName = "property name",
                        TypeName = typeof(string).FullName,
                        IsStringProperty = true
                    },
                },
                TagStructure = TagStructure.NormalOrSelfClosing
            };

            var expectedSerializedDescriptor =
                $"{{\"{ nameof(TagHelperDescriptor.Prefix) }\":\"prefix:\"," +
                $"\"{ nameof(TagHelperDescriptor.TagName) }\":\"tag name\"," +
                $"\"{ nameof(TagHelperDescriptor.FullTagName) }\":\"prefix:tag name\"," +
                $"\"{ nameof(TagHelperDescriptor.TypeName) }\":\"type name\"," +
                $"\"{ nameof(TagHelperDescriptor.AssemblyName) }\":\"assembly name\"," +
                $"\"{ nameof(TagHelperDescriptor.Attributes) }\":[" +
                $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
                $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":false," +
                $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute one\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"property type name\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}," +
                $"{{\"{ nameof(TagHelperAttributeDescriptor.IsIndexer) }\":false," +
                $"\"{ nameof(TagHelperAttributeDescriptor.IsStringProperty) }\":true," +
                $"\"{ nameof(TagHelperAttributeDescriptor.Name) }\":\"attribute two\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.PropertyName) }\":\"property name\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.TypeName) }\":\"{ typeof(string).FullName }\"," +
                $"\"{ nameof(TagHelperAttributeDescriptor.DesignTimeDescriptor) }\":null}}]," +
                $"\"{ nameof(TagHelperDescriptor.RequiredAttributes) }\":[]," +
                $"\"{ nameof(TagHelperDescriptor.AllowedChildren) }\":null," +
                $"\"{ nameof(TagHelperDescriptor.RequiredParent) }\":null," +
                $"\"{ nameof(TagHelperDescriptor.TagStructure) }\":1," +
                $"\"{ nameof(TagHelperDescriptor.DesignTimeDescriptor) }\":null}}";

            // Act
            var serializedDescriptor = JsonConvert.SerializeObject(descriptor);

            // Assert
            Assert.Equal(expectedSerializedDescriptor, serializedDescriptor, StringComparer.Ordinal);
        }
        public void Rewrite_UnderstandsNestedRequiredParent(string documentContent, MarkupBlock expectedOutput)
        {
            // Arrange
            var descriptors = new TagHelperDescriptor[]
            {
                new TagHelperDescriptor
                {
                    TagName = "strong",
                    TypeName = "StrongTagHelper",
                    AssemblyName = "SomeAssembly",
                    RequiredParent = "p",
                },
                new TagHelperDescriptor
                {
                    TagName = "strong",
                    TypeName = "StrongTagHelper",
                    AssemblyName = "SomeAssembly",
                    RequiredParent = "div",
                },
                new TagHelperDescriptor
                {
                    TagName = "p",
                    TypeName = "PTagHelper",
                    AssemblyName = "SomeAssembly"
                }
            };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new RazorError[0]);
        }
        public void GetDescriptors_ReturnsCatchAllsWithEveryTagName()
        {
            // Arrange
            var divDescriptor = new TagHelperDescriptor
            {
                TagName = "div",
                TypeName = "foo1",
                AssemblyName = "SomeAssembly",
            };
            var spanDescriptor = new TagHelperDescriptor
            {
                TagName = "span",
                TypeName = "foo2",
                AssemblyName = "SomeAssembly",
            };
            var catchAllDescriptor = new TagHelperDescriptor
            {
                TagName = TagHelperDescriptorProvider.ElementCatchAllTarget,
                TypeName = "foo3",
                AssemblyName = "SomeAssembly",
            };
            var descriptors = new TagHelperDescriptor[] { divDescriptor, spanDescriptor, catchAllDescriptor };
            var provider = new TagHelperDescriptorProvider(descriptors);

            // Act
            var divDescriptors = provider.GetDescriptors(
                tagName: "div",
                attributeNames: Enumerable.Empty<string>(),
                parentTagName: "p");
            var spanDescriptors = provider.GetDescriptors(
                tagName: "span",
                attributeNames: Enumerable.Empty<string>(),
                parentTagName: "p");

            // Assert
            // For divs
            Assert.Equal(2, divDescriptors.Count());
            Assert.Contains(divDescriptor, divDescriptors);
            Assert.Contains(catchAllDescriptor, divDescriptors);

            // For spans
            Assert.Equal(2, spanDescriptors.Count());
            Assert.Contains(spanDescriptor, spanDescriptors);
            Assert.Contains(catchAllDescriptor, spanDescriptors);
        }
        public void TagHelpers_WithinHelpersAndSections_GeneratesExpectedOutput()
        {
            // Arrange
            var propertyInfo = typeof(TestType).GetProperty("BoundProperty");
            var tagHelperDescriptors = new TagHelperDescriptor[]
            {
                new TagHelperDescriptor
                {
                    TagName = "MyTagHelper",
                    TypeName = "MyTagHelper",
                    AssemblyName = "SomeAssembly",
                    Attributes = new []
                    {
                        new TagHelperAttributeDescriptor("BoundProperty", propertyInfo)
                    }
                },
                new TagHelperDescriptor
                {
                    TagName = "NestedTagHelper",
                    TypeName = "NestedTagHelper",
                    AssemblyName = "SomeAssembly"
                }
            };

            // Act & Assert
            RunTagHelperTest("TagHelpersInSection", tagHelperDescriptors: tagHelperDescriptors);
        }
        public void Rewrite_RecoversWhenRequiredAttributeMismatchAndRestrictedChildren()
        {
            // Arrange
            var factory = CreateDefaultSpanFactory();
            var blockFactory = new BlockFactory(factory);
            var documentContent = "<strong required><strong></strong></strong>";

            var expectedErrors = new[] {
                new RazorError(
                    RazorResources.FormatTagHelperParseTreeRewriter_InvalidNestedTag("strong", "strong", "br"),
                    absoluteIndex: 18,
                    lineIndex: 0,
                    columnIndex: 18,
                    length: 6)
            };
            var expectedOutput = new MarkupBlock(
                new MarkupTagHelperBlock("strong",
                    new List<KeyValuePair<string, SyntaxTreeNode>>
                    {
                        new KeyValuePair<string, SyntaxTreeNode>("required", null)
                    },
                    blockFactory.MarkupTagBlock("<strong>"),
                    blockFactory.MarkupTagBlock("</strong>")));
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "strong",
                        TypeName = "StrongTagHelper",
                        AssemblyName = "SomeAssembly",
                        RequiredAttributes = new[] { "required" },
                        AllowedChildren = new[] { "br" }
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
        }
        public void Rewrite_UnderstandsTagHelperPrefixAndAllowedChildren()
        {
            // Arrange
            var documentContent = "<th:p><th:strong></th:strong></th:p>";
            var expectedOutput = new MarkupBlock(
                new MarkupTagHelperBlock("th:p",
                    new MarkupTagHelperBlock("th:strong")));
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "PTagHelper",
                        AssemblyName = "SomeAssembly",
                        AllowedChildren = new[] { "strong" },
                        Prefix = "th:"
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "strong",
                        TypeName = "StrongTagHelper",
                        AssemblyName = "SomeAssembly",
                        Prefix = "th:"
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(
                descriptorProvider,
                documentContent,
                expectedOutput,
                expectedErrors: Enumerable.Empty<RazorError>());
        }
        public void TagHelperParseTreeRewriter_CreatesMarkupCodeSpansForNonStringTagHelperAttributes(
            string documentContent,
            MarkupBlock expectedOutput)
        {
            // Arrange
            var descriptors = new TagHelperDescriptor[]
            {
                new TagHelperDescriptor
                {
                    TagName = "person",
                    TypeName = "PersonTagHelper",
                    AssemblyName = "personAssembly",
                    Attributes = new[]
                    {
                        new TagHelperAttributeDescriptor
                        {
                            Name = "age",
                            PropertyName = "Age",
                            TypeName = typeof(int).FullName
                        },
                        new TagHelperAttributeDescriptor
                        {
                            Name = "birthday",
                            PropertyName = "BirthDay",
                            TypeName = typeof(DateTime).FullName
                        },
                        new TagHelperAttributeDescriptor
                        {
                            Name = "name",
                            PropertyName = "Name",
                            TypeName = typeof(string).FullName,
                            IsStringProperty = true
                        }
                    }
                }
            };
            var providerContext = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(providerContext,
                         documentContent,
                         expectedOutput,
                         expectedErrors: Enumerable.Empty<RazorError>());
        }
        public void Rewrite_CreatesErrorForInconsistentTagStructures()
        {
            // Arrange
            var factory = CreateDefaultSpanFactory();
            var blockFactory = new BlockFactory(factory);
            var expectedError = new RazorError(
                RazorResources.FormatTagHelperParseTreeRewriter_InconsistentTagStructure(
                    "InputTagHelper1",
                    "InputTagHelper2",
                    "input",
                    nameof(TagHelperDescriptor.TagStructure)),
                absoluteIndex: 0,
                lineIndex: 0,
                columnIndex: 0,
                length: 7);
            var documentContent = "<input>";
            var expectedOutput = new MarkupBlock(new MarkupTagHelperBlock("input", TagMode.StartTagOnly));
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper1",
                        AssemblyName = "SomeAssembly",
                        TagStructure = TagStructure.WithoutEndTag
                    },
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper2",
                        AssemblyName = "SomeAssembly",
                        TagStructure = TagStructure.NormalOrSelfClosing
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new[] { expectedError });
        }
        public void Rewrite_CanHandleInvalidChildrenWithWhitespace()
        {
            // Arrange
            var factory = CreateDefaultSpanFactory();
            var blockFactory = new BlockFactory(factory);
            var documentContent = $"<p>{Environment.NewLine}    <strong>{Environment.NewLine}        Hello" +
                $"{Environment.NewLine}    </strong>{Environment.NewLine}</p>";
            var newLineLength = Environment.NewLine.Length;
            var expectedErrors = new[] {
                new RazorError(
                    RazorResources.FormatTagHelperParseTreeRewriter_InvalidNestedTag("strong", "p", "br"),
                    absoluteIndex: 8 + newLineLength,
                    lineIndex: 1,
                    columnIndex: 5,
                    length: 6),
            };
            var expectedOutput = new MarkupBlock(
                new MarkupTagHelperBlock("p",
                    factory.Markup(Environment.NewLine + "    "),
                    blockFactory.MarkupTagBlock("<strong>"),
                    factory.Markup(Environment.NewLine + "        Hello" + Environment.NewLine + "    "),
                    blockFactory.MarkupTagBlock("</strong>"),
                    factory.Markup(Environment.NewLine)));
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "PTagHelper",
                        AssemblyName = "SomeAssembly",
                        AllowedChildren = new[] { "br" },
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
        }
        public void Rewrite_CanHandleWithoutEndTagTagStructure(string documentContent, MarkupBlock expectedOutput)
        {
            // Arrange
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "input",
                        TypeName = "InputTagHelper",
                        AssemblyName = "SomeAssembly",
                        TagStructure = TagStructure.WithoutEndTag,
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors: new RazorError[0]);
        }
예제 #51
0
 internal static string GetVariableName(TagHelperDescriptor descriptor)
 {
     return("__" + descriptor.TypeName.Replace('.', '_'));
 }
        public void Rewrite_CreatesErrorForEmptyTagHelperBoundAttributes(
            string documentContent,
            MarkupBlock expectedOutput,
            RazorError[] expectedErrors)
        {
            // Arrange
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "myth",
                        TypeName = "mythTagHelper",
                        AssemblyName = "SomeAssembly",
                        Attributes = new[]
                        {
                            new TagHelperAttributeDescriptor
                            {
                                Name = "bound",
                                PropertyName = "Bound",
                                TypeName = typeof(bool).FullName
                            },
                            new TagHelperAttributeDescriptor
                            {
                                Name = "name",
                                PropertyName = "Name",
                                TypeName = typeof(string).FullName,
                                IsStringProperty = true
                            }
                        }
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
        }
예제 #53
0
 public string GetFullyQualifiedName(TagHelperDescriptor taghelper)
 {
     return(_tagHelpers[taghelper].fullyQualifiedName);
 }
        public void Rewrite_RequiredAttributeDescriptorsCreateMalformedTagHelperBlocksCorrectly(
            string documentContent,
            MarkupBlock expectedOutput,
            RazorError[] expectedErrors)
        {
            // Arrange
            var descriptors = new TagHelperDescriptor[]
                {
                    new TagHelperDescriptor
                    {
                        TagName = "p",
                        TypeName = "pTagHelper",
                        AssemblyName = "SomeAssembly",
                        RequiredAttributes = new[] { "class" }
                    }
                };
            var descriptorProvider = new TagHelperDescriptorProvider(descriptors);

            // Act & Assert
            EvaluateData(descriptorProvider, documentContent, expectedOutput, expectedErrors);
        }
예제 #55
0
 private static string GenerateFieldName(TagHelperDescriptor tagHelper)
 {
     return($"__{tagHelper.GetViewComponentName()}ViewComponentTagHelper");
 }
        public void TagHelperDescrictorsAreCompatibleWithPinnedVisualStudioVersion()
        {
            // Arrange
            var runtimeDescriptor = new TagHelperDescriptor
            {
                AllowedChildren = new[] { "tr", "td" },
                AssemblyName = "CustomAssembly",
                Prefix = "th:",
                RequiredAttributes = new[] { "runat" },
                RequiredParent = "body",
                TagName = "custom-table",
                TagStructure = TagStructure.NormalOrSelfClosing,
                TypeName = "Custom.Type.TableTagHelper",
                DesignTimeDescriptor = new TagHelperDesignTimeDescriptor
                {
                    OutputElementHint = "table",
                    Remarks = "Some tag level remarks.",
                    Summary = "Some tag level summary."
                },
                Attributes = new[]
                {
                    new TagHelperAttributeDescriptor
                    {
                        IsIndexer = false,
                        IsStringProperty = true,
                        Name = "bind",
                        PropertyName = "Bind",
                        TypeName = "System.String",
                        DesignTimeDescriptor = new TagHelperAttributeDesignTimeDescriptor
                        {
                            Remarks = "Some attribute level remarks.",
                            Summary = "Some attribute level summary."
                        }
                    }
                }
            };
            var expectedVSDescriptor = new VisualStudioTagHelperDescriptor
            {
                AllowedChildren = new[] { "tr", "td" },
                AssemblyName = "CustomAssembly",
                Prefix = "th:",
                RequiredAttributes = new[] { "runat" },
                RequiredParent = "body",
                TagName = "custom-table",
                TagStructure = VisualStudioTagStructure.NormalOrSelfClosing,
                TypeName = "Custom.Type.TableTagHelper",
                DesignTimeDescriptor = new VisualStudioTagHelperDesignTimeDescriptor
                {
                    OutputElementHint = "table",
                    Remarks = "Some tag level remarks.",
                    Summary = "Some tag level summary."
                },
                Attributes = new[]
                {
                    new VisualStudioTagHelperAttributeDescriptor
                    {
                        IsIndexer = false,
                        IsStringProperty = true,
                        Name = "bind",
                        PropertyName = "Bind",
                        TypeName = "System.String",
                        DesignTimeDescriptor = new VisualStudioTagHelperAttributeDesignTimeDescriptor
                        {
                            Remarks = "Some attribute level remarks.",
                            Summary = "Some attribute level summary."
                        }
                    }
                }
            };
            var serializedRuntimeDescriptor = JsonConvert.SerializeObject(runtimeDescriptor);

            // Act
            var vsDescriptor =
                JsonConvert.DeserializeObject<VisualStudioTagHelperDescriptor>(serializedRuntimeDescriptor);

            // Assert
            Assert.Equal(expectedVSDescriptor.AllowedChildren, vsDescriptor.AllowedChildren, StringComparer.Ordinal);
            Assert.Equal(expectedVSDescriptor.AssemblyName, vsDescriptor.AssemblyName, StringComparer.Ordinal);
            Assert.Equal(expectedVSDescriptor.Prefix, vsDescriptor.Prefix, StringComparer.Ordinal);
            Assert.Equal(expectedVSDescriptor.RequiredAttributes, vsDescriptor.RequiredAttributes, StringComparer.Ordinal);
            Assert.Equal(expectedVSDescriptor.RequiredParent, vsDescriptor.RequiredParent, StringComparer.Ordinal);
            Assert.Equal(expectedVSDescriptor.TagName, vsDescriptor.TagName, StringComparer.Ordinal);
            Assert.Equal(expectedVSDescriptor.TagStructure, vsDescriptor.TagStructure);
            Assert.Equal(expectedVSDescriptor.TypeName, vsDescriptor.TypeName, StringComparer.Ordinal);

            var dtDescriptor = vsDescriptor.DesignTimeDescriptor;
            var expectedDTDescriptor = expectedVSDescriptor.DesignTimeDescriptor;
            Assert.Equal(expectedDTDescriptor.OutputElementHint, dtDescriptor.OutputElementHint, StringComparer.Ordinal);
            Assert.Equal(expectedDTDescriptor.Remarks, dtDescriptor.Remarks, StringComparer.Ordinal);
            Assert.Equal(expectedDTDescriptor.Summary, dtDescriptor.Summary, StringComparer.Ordinal);

            var attribute = Assert.Single(vsDescriptor.Attributes);
            var expectedAttribute = Assert.Single(expectedVSDescriptor.Attributes);
            Assert.Equal(attribute.IsIndexer, expectedAttribute.IsIndexer);
            Assert.Equal(attribute.IsStringProperty, expectedAttribute.IsStringProperty);
            Assert.Equal(attribute.Name, expectedAttribute.Name, StringComparer.Ordinal);
            Assert.Equal(attribute.PropertyName, expectedAttribute.PropertyName, StringComparer.Ordinal);
            Assert.Equal(attribute.TypeName, expectedAttribute.TypeName, StringComparer.Ordinal);

            var dtAttribute = attribute.DesignTimeDescriptor;
            var expectedDTAttribute = expectedAttribute.DesignTimeDescriptor;
            Assert.Equal(dtAttribute.Remarks, expectedDTAttribute.Remarks, StringComparer.Ordinal);
            Assert.Equal(dtAttribute.Summary, expectedDTAttribute.Summary, StringComparer.Ordinal);
        }
예제 #57
0
 internal static void Set(int hashCode, TagHelperDescriptor descriptor) =>
 CachedTagHelperDescriptors.Set(hashCode, descriptor);
        public void CreateDescriptors_UnderstandsEditorBrowsableAttribute(
            Type tagHelperType,
            bool designTime,
            TagHelperDescriptor[] expectedDescriptors)
        {
            // Arrange
            var errorSink = new ErrorSink();
            var factory = new TagHelperDescriptorFactory(designTime);

            // Act
            var descriptors = factory.CreateDescriptors(
                AssemblyName,
                GetTypeInfo(tagHelperType),
                errorSink);

            // Assert
            Assert.Empty(errorSink.Errors);
            Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
예제 #59
0
 internal static bool TrySplitNamespaceAndType(TagHelperDescriptor tagHelperDescriptor, out StringSegment @namespace)
 => TrySplitNamespaceAndType(tagHelperDescriptor, out @namespace, out _);
        public void CreateDescriptors_IsEnumIsSetCorrectly(
            Type tagHelperType,
            TagHelperDescriptor[] expectedDescriptors)
        {
            // Arrange
            var errorSink = new ErrorSink();
            var factory = new TagHelperDescriptorFactory(designTime: false);

            // Act
            var descriptors = factory.CreateDescriptors(
                AssemblyName,
                GetTypeInfo(tagHelperType),
                errorSink: errorSink);

            // Assert
            Assert.Empty(errorSink.Errors);

            // We don't care about order. Mono returns reflected attributes differently so we need to ensure order
            // doesn't matter by sorting.
            descriptors = descriptors.OrderBy(descriptor => descriptor.TagName);

            Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default);
        }