/// <summary> /// Instantiates a new <see cref="RewritingContext"/>. /// </summary> public RewritingContext(Block syntaxTree, ParserErrorSink errorSink) { _errors = new List <RazorError>(); SyntaxTree = syntaxTree; ErrorSink = errorSink; }
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 Compile_ReturnsFailedResultIfParseFails() { // Arrange var errorSink = new ParserErrorSink(); errorSink.OnError(new RazorError("some message", 1, 1, 1, 1)); var generatorResult = new GeneratorResults( new Block(new BlockBuilder { Type = BlockType.Comment }), Enumerable.Empty<TagHelperDescriptor>(), errorSink, new CodeBuilderResult("", new LineMapping[0]), new CodeTree()); var host = new Mock<IMvcRazorHost>(); host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>())) .Returns(generatorResult) .Verifiable(); var fileInfo = new Mock<IFileInfo>(); fileInfo.Setup(f => f.CreateReadStream()) .Returns(Stream.Null); var compiler = new Mock<ICompilationService>(MockBehavior.Strict); var relativeFileInfo = new RelativeFileInfo(fileInfo.Object, @"Views\index\home.cshtml"); var razorService = new RazorCompilationService(compiler.Object, host.Object); // Act var result = razorService.Compile(relativeFileInfo); // Assert Assert.NotNull(result.CompilationFailure); var message = Assert.Single(result.CompilationFailure.Messages); Assert.Equal("some message", message.Message); host.Verify(); }
/// <summary> /// Instantiates a new <see cref="RewritingContext"/>. /// </summary> public RewritingContext(Block syntaxTree, ParserErrorSink errorSink) { _errors = new List<RazorError>(); SyntaxTree = syntaxTree; ErrorSink = errorSink; }
/// <summary> /// Returns a sequence of <see cref="TagHelperDescriptor"/>s for tag helpers that are registered in the /// specified <paramref name="documentRoot"/>. /// </summary> /// <param name="documentRoot">The <see cref="Block"/> to scan for tag helper registrations in.</param> /// <param name="errorSink">Used to manage <see cref="RazorError"/>s encountered during the Razor parsing /// phase.</param> /// <returns><see cref="TagHelperDescriptor"/>s that are applicable to the <paramref name="documentRoot"/> /// </returns> protected virtual IEnumerable <TagHelperDescriptor> GetTagHelperDescriptors([NotNull] Block documentRoot, [NotNull] ParserErrorSink errorSink) { var addOrRemoveTagHelperSpanVisitor = new AddOrRemoveTagHelperSpanVisitor(TagHelperDescriptorResolver, errorSink); return(addOrRemoveTagHelperSpanVisitor.GetDescriptors(documentRoot)); }
private static IEnumerable<TargetElementAttribute> GetValidTargetElementAttributes( TypeInfo typeInfo, ParserErrorSink errorSink) { var targetElementAttributes = typeInfo.GetCustomAttributes<TargetElementAttribute>(inherit: false); return targetElementAttributes.Where(attribute => ValidTargetElementAttributeNames(attribute, errorSink)); }
private ParserResults ParseCore(ITextDocument input) { // Setup the parser context var errorSink = new ParserErrorSink(); var context = new ParserContext(input, CodeParser, MarkupParser, MarkupParser, errorSink) { DesignTimeMode = DesignTimeMode }; MarkupParser.Context = context; CodeParser.Context = context; // Execute the parse MarkupParser.ParseDocument(); // Get the result var results = context.CompleteParse(); // Rewrite whitespace if supported var rewritingContext = new RewritingContext(results.Document, errorSink); foreach (ISyntaxTreeRewriter rewriter in Optimizers) { rewriter.Rewrite(rewritingContext); } var descriptors = Enumerable.Empty <TagHelperDescriptor>(); if (TagHelperDescriptorResolver != null) { descriptors = GetTagHelperDescriptors(rewritingContext.SyntaxTree, rewritingContext.ErrorSink); var tagHelperProvider = new TagHelperDescriptorProvider(descriptors); var tagHelperParseTreeRewriter = new TagHelperParseTreeRewriter(tagHelperProvider); // Rewrite the document to utilize tag helpers tagHelperParseTreeRewriter.Rewrite(rewritingContext); } var syntaxTree = rewritingContext.SyntaxTree; // Link the leaf nodes into a chain Span prev = null; foreach (Span node in syntaxTree.Flatten()) { node.Previous = prev; if (prev != null) { prev.Next = node; } prev = node; } // Return the new result return(new ParserResults(syntaxTree, descriptors, errorSink)); }
public void VisitThrowsOnNullVisitor() { ParserVisitor target = null; var errorSink = new ParserErrorSink(); var results = new ParserResults(new BlockBuilder() { Type = BlockType.Comment }.Build(), Enumerable.Empty<TagHelperDescriptor>(), errorSink); Assert.Throws<ArgumentNullException>("self", () => target.Visit(results)); }
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); }
// 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; }
public virtual ParserContext CreateParserContext(ITextDocument input, ParserBase codeParser, ParserBase markupParser, ParserErrorSink errorSink) { return new ParserContext(input, codeParser, markupParser, SelectActiveParser(codeParser, markupParser), errorSink); }
public void VisitSendsDocumentToVisitor() { // Arrange Mock<ParserVisitor> targetMock = new Mock<ParserVisitor>(); var root = new BlockBuilder() { Type = BlockType.Comment }.Build(); var errorSink = new ParserErrorSink(); var results = new ParserResults(root, Enumerable.Empty<TagHelperDescriptor>(), errorSink); // Act targetMock.Object.Visit(results); // Assert targetMock.Verify(v => v.VisitBlock(root)); }
public ParserContext([NotNull] ITextDocument source, [NotNull] ParserBase codeParser, [NotNull] ParserBase markupParser, [NotNull] ParserBase activeParser, [NotNull] ParserErrorSink errorSink) { if (activeParser != codeParser && activeParser != markupParser) { throw new ArgumentException(RazorResources.ActiveParser_Must_Be_Code_Or_Markup_Parser, "activeParser"); } CaptureOwnerTask(); Source = new TextDocumentReader(source); CodeParser = codeParser; MarkupParser = markupParser; ActiveParser = activeParser; _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])); }
private void EvaluateData(TagHelperDescriptorProvider provider, string documentContent, MarkupBlock expectedOutput, IEnumerable<RazorError> expectedErrors) { var errorSink = new ParserErrorSink(); var results = ParseDocument(documentContent, errorSink); var rewritingContext = new RewritingContext(results.Document, errorSink); new TagHelperParseTreeRewriter(provider).Rewrite(rewritingContext); var rewritten = rewritingContext.SyntaxTree; var actualErrors = errorSink.Errors.OrderBy(error => error.Location.AbsoluteIndex) .ToList(); EvaluateRazorErrors(actualErrors, expectedErrors.ToList()); EvaluateParseTree(rewritten, expectedOutput); }
public override ParserContext CreateParserContext(ITextDocument input, ParserBase codeParser, ParserBase markupParser, ParserErrorSink errorSink) { return base.CreateParserContext(input, codeParser, markupParser, errorSink); }
private ParserResults ParseCore(ITextDocument input) { // Setup the parser context var errorSink = new ParserErrorSink(); var context = new ParserContext(input, CodeParser, MarkupParser, MarkupParser, errorSink) { DesignTimeMode = DesignTimeMode }; MarkupParser.Context = context; CodeParser.Context = context; // Execute the parse MarkupParser.ParseDocument(); // Get the result var results = context.CompleteParse(); // Rewrite whitespace if supported var rewritingContext = new RewritingContext(results.Document, errorSink); foreach (ISyntaxTreeRewriter rewriter in Optimizers) { rewriter.Rewrite(rewritingContext); } var descriptors = Enumerable.Empty<TagHelperDescriptor>(); if (TagHelperDescriptorResolver != null) { descriptors = GetTagHelperDescriptors(rewritingContext.SyntaxTree, rewritingContext.ErrorSink); var tagHelperProvider = new TagHelperDescriptorProvider(descriptors); var tagHelperParseTreeRewriter = new TagHelperParseTreeRewriter(tagHelperProvider); // Rewrite the document to utilize tag helpers tagHelperParseTreeRewriter.Rewrite(rewritingContext); } var syntaxTree = rewritingContext.SyntaxTree; // Link the leaf nodes into a chain Span prev = null; foreach (Span node in syntaxTree.Flatten()) { node.Previous = prev; if (prev != null) { prev.Next = node; } prev = node; } // Return the new result return new ParserResults(syntaxTree, descriptors, errorSink); }
public void CreateDescriptor_BuildsDescriptorsFromSimpleTypes() { // Arrange var errorSink = new ParserErrorSink(); var objectAssemblyName = typeof(object).GetTypeInfo().Assembly.GetName().Name; var expectedDescriptor = new TagHelperDescriptor("object", "System.Object", objectAssemblyName); // Act var descriptors = TagHelperDescriptorFactory.CreateDescriptors( objectAssemblyName, typeof(object), errorSink); // Assert Assert.Empty(errorSink.Errors); var descriptor = Assert.Single(descriptors); Assert.Equal(expectedDescriptor, descriptor, CaseSensitiveTagHelperDescriptorComparer.Default); }
/// <summary> /// Instantiates a new instance of the <see cref="CodeBuilderContext"/> object. /// </summary> /// <param name="generatorContext">A <see cref="CodeGeneratorContext"/> to copy information from.</param> /// <param name="errorSink"> /// The <see cref="ParserErrorSink"/> used to collect <see cref="Parser.SyntaxTree.RazorError"/>s encountered /// when parsing the current Razor document. /// </param> public CodeBuilderContext(CodeGeneratorContext generatorContext, ParserErrorSink errorSink) : base(generatorContext) { ErrorSink = errorSink; ExpressionRenderingMode = ExpressionRenderingMode.WriteToOutput; }
protected override TagHelperDescriptorResolutionContext GetTagHelperDescriptorResolutionContext( IEnumerable<TagHelperDirectiveDescriptor> descriptors, ParserErrorSink errorSink) { var directivesToImport = MergeDirectiveDescriptors(descriptors, _globalImportDirectiveDescriptors); return base.GetTagHelperDescriptorResolutionContext(directivesToImport, errorSink); }
protected virtual ParserResults ParseDocument(string document, bool designTimeParser, ParserErrorSink errorSink) { return RunParse(document, parser => parser.ParseDocument, designTimeParser, parserSelector: c => c.MarkupParser, errorSink: errorSink); }
protected virtual ParserResults RunParse(string document, Func<ParserBase, Action> parserActionSelector, bool designTimeParser, Func<ParserContext, ParserBase> parserSelector = null, ParserErrorSink errorSink = null) { parserSelector = parserSelector ?? (c => c.ActiveParser); errorSink = errorSink ?? new ParserErrorSink(); // Create the source ParserResults results = null; using (var reader = new SeekableTextReader(document)) { try { var codeParser = CreateCodeParser(); var markupParser = CreateMarkupParser(); var context = CreateParserContext(reader, codeParser, markupParser, errorSink); context.DesignTimeMode = designTimeParser; codeParser.Context = context; markupParser.Context = context; // Run the parser parserActionSelector(parserSelector(context))(); results = context.CompleteParse(); } finally { if (results != null && results.Document != null) { WriteTraceLine(String.Empty); WriteTraceLine("Actual Parse Tree:"); WriteNode(0, results.Document); } } } return results; }
public void ValidTargetElementAttributeNames_CreatesErrorOnInvalidNames( string name, string[] expectedErrorMessages) { // Arrange var errorSink = new ParserErrorSink(); var attribute = new TargetElementAttribute(name); // Act TagHelperDescriptorFactory.ValidTargetElementAttributeNames(attribute, errorSink); // Assert var errors = errorSink.Errors.ToArray(); for (var i = 0; i < errors.Length; i++) { Assert.Equal(expectedErrorMessages[i], errors[i].Message); Assert.Equal(SourceLocation.Zero, errors[i].Location); } }
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); }
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); }
/// <summary> /// Internal for testing. /// </summary> internal static bool ValidTargetElementAttributeNames( TargetElementAttribute attribute, ParserErrorSink errorSink) { var validTagName = ValidateName(attribute.Tag, targetingAttributes: false, errorSink: errorSink); var validAttributeNames = true; var attributeNames = GetCommaSeparatedValues(attribute.Attributes); foreach (var attributeName in attributeNames) { if (!ValidateName(attributeName, targetingAttributes: true, errorSink: errorSink)) { validAttributeNames = false; } } return validTagName && validAttributeNames; }
public void CreateDescriptor_OverridesTagNameFromAttribute() { // Arrange var errorSink = new ParserErrorSink(); var expectedDescriptors = new[] { new TagHelperDescriptor("data-condition", typeof(OverrideNameTagHelper).FullName, AssemblyName), }; // Act var descriptors = TagHelperDescriptorFactory.CreateDescriptors( AssemblyName, typeof(OverrideNameTagHelper), errorSink); // Assert Assert.Empty(errorSink.Errors); Assert.Equal(expectedDescriptors, descriptors, CaseSensitiveTagHelperDescriptorComparer.Default); }
private static bool ValidateName( string name, bool targetingAttributes, ParserErrorSink errorSink) { var targetName = targetingAttributes ? Resources.TagHelperDescriptorFactory_Attribute : Resources.TagHelperDescriptorFactory_Tag; var validName = true; if (string.IsNullOrWhiteSpace(name)) { errorSink.OnError( SourceLocation.Zero, Resources.FormatTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName)); validName = false; } else { foreach (var character in name) { if (char.IsWhiteSpace(character) || InvalidNonWhitespaceNameCharacters.Contains(character)) { errorSink.OnError( SourceLocation.Zero, Resources.FormatTargetElementAttribute_InvalidName( targetName.ToLower(), name, character)); validName = false; } } } return validName; }
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); }
public GlobalImportTagHelperDirectiveSpanVisitor( ITagHelperDescriptorResolver descriptorResolver, IEnumerable<TagHelperDirectiveDescriptor> globalImportDirectiveDescriptors, ParserErrorSink errorSink) : base(descriptorResolver, errorSink) { _globalImportDirectiveDescriptors = globalImportDirectiveDescriptors; }
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); }
protected virtual ParserResults ParseDocument(string document, ParserErrorSink errorSink) { return ParseDocument(document, designTimeParser: false, errorSink: errorSink); }
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); }