public void CreateDescriptor_DoesntResolveInheritedTagNames()
        {
            // Arrange
            var errorSink          = new ParserErrorSink();
            var validProp          = typeof(InheritedMultiTagTagHelper).GetProperty(nameof(InheritedMultiTagTagHelper.ValidAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "inherited-multi-tag",
                typeof(InheritedMultiTagTagHelper).FullName,
                AssemblyName,
                new[] {
                new TagHelperAttributeDescriptor("valid-attribute", validProp)
            });

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

            // Assert
            Assert.Empty(errorSink.Errors);
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
Example #2
0
        private void ParserTest(string content, Block document, TagProvidersCollection providers = null)
        {
            providers = providers ?? TagProvidersCollection.Default;

            var output = new StringBuilder();

            using (var reader = new StringReader(content))
            {
                using (var source = new SeekableTextReader(reader))
                {
                    var errors = new ParserErrorSink();
                    var parser = new HandlebarsParser();

                    var context = new ParserContext(source, parser, errors, providers);
                    parser.Context = context;

                    parser.ParseDocument();

                    var results = context.CompleteParse();

                    var comparer = new EquivalanceComparer(output, 0);

                    Assert.True(comparer.Equals(document, results.Document), output.ToString());
                }
            }
        }
        public void CreateDescriptor_OnlyAcceptsPropertiesWithPublicGetAndSet()
        {
            // Arrange
            var errorSink     = new ParserErrorSink();
            var validProperty = typeof(PrivateAccessorTagHelper).GetProperty(
                nameof(PrivateAccessorTagHelper.ValidAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "private-accessor",
                typeof(PrivateAccessorTagHelper).FullName,
                AssemblyName,
                new[] {
                new TagHelperAttributeDescriptor(
                    "valid-attribute", validProperty)
            });

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

            // Assert
            Assert.Empty(errorSink.Errors);
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
Example #4
0
        public void RenderAttributeValue_RendersModelExpressionsCorrectly(string modelExpressionType,
                                                                          string propertyType,
                                                                          string expectedValue)
        {
            // Arrange
            var renderer = new MvcTagHelperAttributeValueCodeRenderer(
                new GeneratedTagHelperAttributeContext
            {
                ModelExpressionTypeName         = modelExpressionType,
                CreateModelExpressionMethodName = "SomeMethod"
            });
            var attributeDescriptor = new TagHelperAttributeDescriptor("MyAttribute", "SomeProperty", propertyType);
            var writer           = new CSharpCodeWriter();
            var generatorContext = new CodeGeneratorContext(host: null,
                                                            className: string.Empty,
                                                            rootNamespace: string.Empty,
                                                            sourceFile: string.Empty,
                                                            shouldGenerateLinePragmas: true);
            var errorSink = new ParserErrorSink();
            var context   = new CodeBuilderContext(generatorContext, errorSink);

            // Act
            renderer.RenderAttributeValue(attributeDescriptor, writer, context,
                                          (codeWriter) =>
            {
                codeWriter.Write("MyValue");
            },
                                          complexValue: false);

            // Assert
            Assert.Equal(expectedValue, writer.GenerateCode());
        }
        public void CreateDescriptor_ResolvesMultipleTagHelperDescriptorsFromSingleType()
        {
            // Arrange
            var errorSink           = new ParserErrorSink();
            var validProp           = typeof(MultiTagTagHelper).GetProperty(nameof(MultiTagTagHelper.ValidAttribute));
            var expectedDescriptors = new[] {
                new TagHelperDescriptor(
                    "p",
                    typeof(MultiTagTagHelper).FullName,
                    AssemblyName,
                    new[] {
                    new TagHelperAttributeDescriptor("valid-attribute", validProp)
                }),
                new TagHelperDescriptor(
                    "div",
                    typeof(MultiTagTagHelper).FullName,
                    AssemblyName,
                    new[] {
                    new TagHelperAttributeDescriptor("valid-attribute", validProp)
                })
            };

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
                AssemblyName,
                typeof(MultiTagTagHelper),
                errorSink);

            // Assert
            Assert.Empty(errorSink.Errors);
            Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
        public void CreateDescriptor_AllowsOverridenAttributeNameOnUnimplementedVirtual()
        {
            // Arrange
            var errorSink      = new ParserErrorSink();
            var validProperty1 = typeof(InheritedNotOverriddenAttributeTagHelper).GetProperty(
                nameof(InheritedNotOverriddenAttributeTagHelper.ValidAttribute1));
            var validProperty2 = typeof(InheritedNotOverriddenAttributeTagHelper).GetProperty(
                nameof(InheritedNotOverriddenAttributeTagHelper.ValidAttribute2));
            var expectedDescriptors = new[] {
                new TagHelperDescriptor(
                    "inherited-not-overridden-attribute",
                    typeof(InheritedNotOverriddenAttributeTagHelper).FullName,
                    AssemblyName,
                    new[] {
                    new TagHelperAttributeDescriptor("SomethingElse", validProperty1),
                    new TagHelperAttributeDescriptor("Something-Else", validProperty2)
                })
            };

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
                AssemblyName,
                typeof(InheritedNotOverriddenAttributeTagHelper),
                errorSink);

            // Assert
            Assert.Empty(errorSink.Errors);
            Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
        public void CreateDescriptor_BuildsDescriptorsWithConventionNames()
        {
            // Arrange
            var errorSink          = new ParserErrorSink();
            var intProperty        = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
            var expectedDescriptor = new TagHelperDescriptor(
                "single-attribute",
                typeof(SingleAttributeTagHelper).FullName,
                AssemblyName,
                new[] {
                new TagHelperAttributeDescriptor("int-attribute", intProperty)
            });

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
                AssemblyName,
                typeof(SingleAttributeTagHelper),
                new ParserErrorSink());

            // Assert
            Assert.Empty(errorSink.Errors);
            var descriptor = Assert.Single(descriptors);

            Assert.Equal(expectedDescriptor, descriptor, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
Example #8
0
 protected override IEnumerable <TagHelperDescriptor> ResolveDescriptorsInAssembly(
     string assemblyName,
     SourceLocation documentLocation,
     ParserErrorSink errorSink)
 {
     throw _error;
 }
Example #9
0
        public void DescriptorResolver_UnderstandsUnexpectedExceptions_DoesNotThrow()
        {
            // Arrange
            var expectedErrorMessage = "Encountered an unexpected error when attempting to resolve tag helper " +
                                       "directive '@addtaghelper' with value 'A custom lookup text'. Error: A " +
                                       "custom exception";
            var documentLocation            = new SourceLocation(1, 2, 3);
            var directiveType               = TagHelperDirectiveType.AddTagHelper;
            var errorSink                   = new ParserErrorSink();
            var expectedError               = new Exception("A custom exception");
            var tagHelperDescriptorResolver = new ThrowingTagHelperDescriptorResolver(expectedError);
            var resolutionContext           = new TagHelperDescriptorResolutionContext(
                new[] { new TagHelperDirectiveDescriptor("A custom lookup text", documentLocation, directiveType) },
                errorSink);


            // Act
            tagHelperDescriptorResolver.Resolve(resolutionContext);

            // Assert
            var error = Assert.Single(errorSink.Errors);

            Assert.Equal(1, error.Length);
            Assert.Equal(documentLocation, error.Location);
            Assert.Equal(expectedErrorMessage, error.Message);
        }
Example #10
0
        /// <summary>
        /// Creates a document <see cref="Block"/> from the given template.
        /// </summary>
        /// <param name="template">The template.</param>
        /// <returns>The document <see cref="Block"/></returns>
        private Block CreateDocument(string template)
        {
            using (var reader = new StringReader(template))
            {
                using (var source = new SeekableTextReader(reader))
                {
                    var errors = new ParserErrorSink();
                    var parser = new HandlebarsParser();

                    var context = new ParserContext(source, parser, errors, TagProviders);
                    parser.Context = context;

                    parser.ParseDocument();
                    var results = context.CompleteParse();

                    if (results.Success)
                    {
                        return(results.Document);
                    }

                    throw new InvalidOperationException(
                              string.Join("\n", results.Errors.Select(e => string.Format("{0}: {1}", e.Location, e.Message))));
                }
            }
        }
Example #11
0
        public void DescriptorResolver_CreatesErrorIfNullOrEmptyLookupText_DoesNotThrow(string lookupText)
        {
            // Arrange
            var errorSink = new ParserErrorSink();
            var tagHelperDescriptorResolver =
                new TestTagHelperDescriptorResolver(
                    new TestTagHelperTypeResolver(InvalidTestableTagHelpers));
            var documentLocation     = new SourceLocation(1, 2, 3);
            var directiveType        = TagHelperDirectiveType.AddTagHelper;
            var expectedErrorMessage =
                Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText);
            var resolutionContext = new TagHelperDescriptorResolutionContext(
                new [] { new TagHelperDirectiveDescriptor(lookupText, documentLocation, directiveType) },
                errorSink);

            // Act
            tagHelperDescriptorResolver.Resolve(resolutionContext);

            // Assert
            var error = Assert.Single(errorSink.Errors);

            Assert.Equal(1, error.Length);
            Assert.Equal(documentLocation, error.Location);
            Assert.Equal(expectedErrorMessage, error.Message);
        }
        private static LookupInfo GetLookupInfo(TagHelperDirectiveDescriptor directiveDescriptor,
                                                ParserErrorSink errorSink)
        {
            var lookupText    = directiveDescriptor.DirectiveText;
            var lookupStrings = lookupText?.Split(new[] { ',' });

            // Ensure that we have valid lookupStrings to work with. Valid formats are:
            // "assemblyName"
            // "typeName, assemblyName"
            if (lookupStrings == null ||
                lookupStrings.Any(string.IsNullOrWhiteSpace) ||
                lookupStrings.Length != 2)
            {
                errorSink.OnError(
                    directiveDescriptor.Location,
                    Resources.FormatTagHelperDescriptorResolver_InvalidTagHelperLookupText(lookupText));

                return(null);
            }

            return(new LookupInfo
            {
                TypePattern = lookupStrings[0].Trim(),
                AssemblyName = lookupStrings[1].Trim()
            });
        }
Example #13
0
 /// <summary>
 /// Instantiates a new instance of <see cref="TagHelperDescriptorResolutionContext"/>.
 /// </summary>
 /// <param name="directiveDescriptors"><see cref="TagHelperDirectiveDescriptor"/>s used to resolve
 /// <see cref="TagHelperDescriptor"/>s.</param>
 /// <param name="errorSink">Used to aggregate <see cref="Parser.SyntaxTree.RazorError"/>s.</param>
 public TagHelperDescriptorResolutionContext(
     [NotNull] IEnumerable <TagHelperDirectiveDescriptor> directiveDescriptors,
     [NotNull] ParserErrorSink errorSink)
 {
     DirectiveDescriptors = new List <TagHelperDirectiveDescriptor>(directiveDescriptors);
     ErrorSink            = errorSink;
 }
        public void VisitSendsErrorsToVisitor()
        {
            // Arrange
            Mock <ParserVisitor> targetMock = new Mock <ParserVisitor>();
            var root = new BlockBuilder()
            {
                Type = BlockType.Comment
            }.Build();
            var errorSink            = new ParserErrorSink();
            List <RazorError> errors = new List <RazorError>
            {
                new RazorError("Foo", 1, 0, 1),
                new RazorError("Bar", 2, 0, 2),
            };

            foreach (var error in errors)
            {
                errorSink.OnError(error);
            }
            var results = new ParserResults(root, Enumerable.Empty <TagHelperDescriptor>(), errorSink);

            // Act
            targetMock.Object.Visit(results);

            // Assert
            targetMock.Verify(v => v.VisitError(errors[0]));
            targetMock.Verify(v => v.VisitError(errors[1]));
        }
        public void CreateDescriptor_IgnoresDuplicateTagNamesFromAttribute()
        {
            // Arrange
            var errorSink           = new ParserErrorSink();
            var expectedDescriptors = new[] {
                new TagHelperDescriptor(
                    "p",
                    typeof(DuplicateTagNameTagHelper).FullName,
                    AssemblyName),
                new TagHelperDescriptor(
                    "div",
                    typeof(DuplicateTagNameTagHelper).FullName,
                    AssemblyName)
            };

            // Act
            var descriptors = TagHelperDescriptorFactory.CreateDescriptors(
                AssemblyName,
                typeof(DuplicateTagNameTagHelper),
                errorSink);

            // Assert
            Assert.Empty(errorSink.Errors);
            Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default);
        }
Example #16
0
            protected override TagHelperDescriptorResolutionContext GetTagHelperDescriptorResolutionContext(
                IEnumerable <TagHelperDirectiveDescriptor> descriptors,
                ParserErrorSink errorSink)
            {
                var directivesToImport = MergeDirectiveDescriptors(descriptors, _globalImportDirectiveDescriptors);

                return(base.GetTagHelperDescriptorResolutionContext(directivesToImport, errorSink));
            }
Example #17
0
        private static IEnumerable <TargetElementAttribute> GetValidTargetElementAttributes(
            TypeInfo typeInfo,
            ParserErrorSink errorSink)
        {
            var targetElementAttributes = typeInfo.GetCustomAttributes <TargetElementAttribute>(inherit: false);

            return(targetElementAttributes.Where(attribute => ValidTargetElementAttributeNames(attribute, errorSink)));
        }
Example #18
0
 public GlobalImportTagHelperDirectiveSpanVisitor(
     ITagHelperDescriptorResolver descriptorResolver,
     IEnumerable <TagHelperDirectiveDescriptor> globalImportDirectiveDescriptors,
     ParserErrorSink errorSink)
     : base(descriptorResolver, errorSink)
 {
     _globalImportDirectiveDescriptors = globalImportDirectiveDescriptors;
 }
Example #19
0
 public ViewStartAddRemoveTagHelperVisitor(
     ITagHelperDescriptorResolver descriptorResolver,
     IEnumerable <TagHelperDirectiveDescriptor> viewStartDirectiveDescriptors,
     ParserErrorSink errorSink)
     : base(descriptorResolver, errorSink)
 {
     _viewStartDirectiveDescriptors = viewStartDirectiveDescriptors;
 }
Example #20
0
 protected override TagHelperDescriptorResolutionContext GetTagHelperDescriptorResolutionContext(
     IEnumerable <TagHelperDirectiveDescriptor> descriptors,
     ParserErrorSink errorSink)
 {
     return(base.GetTagHelperDescriptorResolutionContext(
                _viewStartDirectiveDescriptors.Concat(descriptors),
                errorSink));
 }
Example #21
0
            protected override IEnumerable <TagHelperDescriptor> ResolveDescriptorsInAssembly(
                string assemblyName,
                SourceLocation documentLocation,
                ParserErrorSink errorSink)
            {
                CalledWithAssemblyName = assemblyName;

                return(Enumerable.Empty <TagHelperDescriptor>());
            }
Example #22
0
 protected virtual ParserResults ParseDocument(string document,
                                               bool designTimeParser,
                                               ParserErrorSink errorSink)
 {
     return(RunParse(document,
                     parser => parser.ParseDocument,
                     designTimeParser,
                     parserSelector: c => c.MarkupParser,
                     errorSink: errorSink));
 }
Example #23
0
        /// <inheritdoc />
        protected override IEnumerable <TagHelperDescriptor> GetTagHelperDescriptors(
            [NotNull] Block documentRoot,
            [NotNull] ParserErrorSink errorSink)
        {
            var visitor = new ViewStartAddRemoveTagHelperVisitor(TagHelperDescriptorResolver,
                                                                 _viewStartDirectiveDescriptors,
                                                                 errorSink);

            return(visitor.GetDescriptors(documentRoot));
        }
Example #24
0
        /// <inheritdoc />
        protected override IEnumerable <TagHelperDescriptor> GetTagHelperDescriptors(
            [NotNull] Block documentRoot,
            [NotNull] ParserErrorSink errorSink)
        {
            var visitor = new GlobalImportTagHelperDirectiveSpanVisitor(
                TagHelperDescriptorResolver,
                _globalImportDirectiveDescriptors,
                errorSink);

            return(visitor.GetDescriptors(documentRoot));
        }
Example #25
0
 /// <summary>
 /// Instantiates a new <see cref="ParserResults"/> instance.
 /// </summary>
 /// <param name="success"><c>true</c> if parsing was successful, <c>false</c> otherwise.</param>
 /// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
 /// <param name="tagHelperDescriptors">
 /// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document.
 /// </param>
 /// <param name="errorSink">
 /// The <see cref="ParserErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the
 /// current Razor document.
 /// </param>
 protected ParserResults(bool success,
                         [NotNull] Block document,
                         [NotNull] IEnumerable <TagHelperDescriptor> tagHelperDescriptors,
                         [NotNull] ParserErrorSink errorSink)
 {
     Success              = success;
     Document             = document;
     TagHelperDescriptors = tagHelperDescriptors;
     ErrorSink            = errorSink;
     ParserErrors         = errorSink.Errors;
 }
Example #26
0
 public virtual ParserContext CreateParserContext(ITextDocument input,
                                                  ParserBase codeParser,
                                                  ParserBase markupParser,
                                                  ParserErrorSink errorSink)
 {
     return(new ParserContext(input,
                              codeParser,
                              markupParser,
                              SelectActiveParser(codeParser, markupParser),
                              errorSink));
 }
Example #27
0
 // Internal for testing.
 internal CodeBuilderContext(RazorEngineHost host,
                             string className,
                             string rootNamespace,
                             string sourceFile,
                             bool shouldGenerateLinePragmas,
                             ParserErrorSink errorSink)
     : base(host, className, rootNamespace, sourceFile, shouldGenerateLinePragmas)
 {
     ErrorSink = errorSink;
     ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput;
 }
Example #28
0
        public void ConstructorAcceptsActiveParserIfIsSameAsEitherCodeOrMarkupParser()
        {
            var codeParser   = new CSharpCodeParser();
            var markupParser = new HtmlMarkupParser();
            var errorSink    = new ParserErrorSink();

            new ParserContext(
                new SeekableTextReader(TextReader.Null), codeParser, markupParser, codeParser, errorSink);
            new ParserContext(
                new SeekableTextReader(TextReader.Null), codeParser, markupParser, markupParser, errorSink);
        }
Example #29
0
 /// <summary>
 /// Instantiates a new <see cref="GeneratorResults"/> instance.
 /// </summary>
 /// <param name="document">The <see cref="Block"/> for the syntax tree.</param>
 /// <param name="tagHelperDescriptors">
 /// The <see cref="TagHelperDescriptor"/>s that apply to the current Razor document.
 /// </param>
 /// <param name="errorSink">
 /// The <see cref="ParserErrorSink"/> used to collect <see cref="RazorError"/>s encountered when parsing the
 /// current Razor document.
 /// </param>
 /// <param name="codeBuilderResult">The results of generating code for the document.</param>
 /// <param name="codeTree">A <see cref="CodeTree"/> for the document.</param>
 public GeneratorResults([NotNull] Block document,
                         [NotNull] IEnumerable <TagHelperDescriptor> tagHelperDescriptors,
                         [NotNull] ParserErrorSink errorSink,
                         [NotNull] CodeBuilderResult codeBuilderResult,
                         [NotNull] CodeTree codeTree)
     : base(document, tagHelperDescriptors, errorSink)
 {
     GeneratedCode          = codeBuilderResult.Code;
     DesignTimeLineMappings = codeBuilderResult.DesignTimeLineMappings;
     CodeTree = codeTree;
 }
        public static TagHelperBlockBuilder Rewrite(string tagName,
                                                    bool validStructure,
                                                    Block tag,
                                                    IEnumerable <TagHelperDescriptor> descriptors,
                                                    ParserErrorSink errorSink)
        {
            // There will always be at least one child for the '<'.
            var start      = tag.Children.First().Start;
            var attributes = GetTagAttributes(tagName, validStructure, tag, descriptors, errorSink);

            return(new TagHelperBlockBuilder(tagName, start, attributes, descriptors));
        }
 public TagHelperDirectiveSpanVisitor([NotNull] ITagHelperDescriptorResolver descriptorResolver,
                                        [NotNull] ParserErrorSink errorSink)
 {
     _descriptorResolver = descriptorResolver;
     _errorSink = errorSink;
 }