/// <summary> /// Called during Razor's code generation process to generate code that instantiates the value of the tag /// helper's property. Last value written should not be or end with a semicolon. /// </summary> /// <param name="attributeDescriptor"> /// The <see cref="TagHelperAttributeDescriptor"/> to generate code for. /// </param> /// <param name="writer">The <see cref="CSharpCodeWriter"/> that's used to write code.</param> /// <param name="context">A <see cref="Chunks.Generators.ChunkGeneratorContext"/> instance that contains /// information about the current code generation process.</param> /// <param name="renderAttributeValue"> /// <see cref="Action"/> that renders the raw value of the HTML attribute. /// </param> /// <param name="complexValue"> /// Indicates whether or not the source attribute value contains more than simple text. <c>false</c> for plain /// C# expressions e.g. <c>"PropertyName"</c>. <c>true</c> if the attribute value contain at least one in-line /// Razor construct e.g. <c>"@(@readonly)"</c>. /// </param> public virtual void RenderAttributeValue( TagHelperAttributeDescriptor attributeDescriptor, CSharpCodeWriter writer, CodeGeneratorContext context, Action<CSharpCodeWriter> renderAttributeValue, bool complexValue) { if (attributeDescriptor == null) { throw new ArgumentNullException(nameof(attributeDescriptor)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } if (renderAttributeValue == null) { throw new ArgumentNullException(nameof(renderAttributeValue)); } renderAttributeValue(writer); }
public CSharpDisableWarningScope(CSharpCodeWriter writer, int warningNumber) { _writer = writer; _warningNumber = warningNumber; _writer.WritePragma("warning disable " + _warningNumber); }
public void Visit_GeneratesProperties_ForInjectChunks() { // Arrange var expected = @"[ActivateAttribute] public MyType1 MyPropertyName1 { get; private set; } [ActivateAttribute] public MyType2 @MyPropertyName2 { get; private set; } "; var writer = new CSharpCodeWriter(); var context = CreateContext(); var visitor = new InjectChunkVisitor(writer, context, "ActivateAttribute"); var factory = SpanFactory.CreateCsHtml(); var node = (Span)factory.Code("Some code") .As(new InjectParameterGenerator("MyType", "MyPropertyName")); // Act visitor.Accept(new Chunk[] { new LiteralChunk(), new InjectChunk("MyType1", "MyPropertyName1") { Association = node }, new InjectChunk("MyType2", "@MyPropertyName2") { Association = node } }); var code = writer.GenerateCode(); // Assert Assert.Equal(expected, code); }
/// <summary> /// Instantiates a new <see cref="CSharpTagHelperCodeRenderer"/>. /// </summary> /// <param name="bodyVisitor">The <see cref="IChunkVisitor"/> used to render chunks found in the body.</param> /// <param name="writer">The <see cref="CSharpCodeWriter"/> used to write code.</param> /// <param name="context">A <see cref="CodeGeneratorContext"/> instance that contains information about /// the current code generation process.</param> public CSharpTagHelperCodeRenderer( IChunkVisitor bodyVisitor, CSharpCodeWriter writer, CodeGeneratorContext context) { if (bodyVisitor == null) { throw new ArgumentNullException(nameof(bodyVisitor)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } _bodyVisitor = bodyVisitor; _writer = writer; _context = context; _tagHelperContext = context.Host.GeneratedClassContext.GeneratedTagHelperContext; _designTimeMode = context.Host.DesignTimeMode; _literalBodyVisitor = new CSharpLiteralCodeVisitor(this, writer, context); _attributeCodeVisitor = new TagHelperAttributeCodeVisitor(writer, context); AttributeValueCodeRenderer = new TagHelperAttributeValueCodeRenderer(); }
protected override CSharpCodeVisitor CreateCSharpCodeVisitor( CSharpCodeWriter writer, CodeGeneratorContext context) { var visitor = base.CreateCSharpCodeVisitor(writer, context); visitor.TagHelperRenderer = new NoUniqueIdsTagHelperCodeRenderer(visitor, writer, context); return visitor; }
/// <inheritdoc /> /// <remarks>If the attribute being rendered is of the type /// <see cref="GeneratedTagHelperAttributeContext.ModelExpressionTypeName"/>, then a model expression will be /// created by calling into <see cref="GeneratedTagHelperAttributeContext.CreateModelExpressionMethodName"/>. /// </remarks> public override void RenderAttributeValue( TagHelperAttributeDescriptor attributeDescriptor, CSharpCodeWriter writer, CodeGeneratorContext codeGeneratorContext, Action<CSharpCodeWriter> renderAttributeValue, bool complexValue) { if (attributeDescriptor == null) { throw new ArgumentNullException(nameof(attributeDescriptor)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (codeGeneratorContext == null) { throw new ArgumentNullException(nameof(codeGeneratorContext)); } if (renderAttributeValue == null) { throw new ArgumentNullException(nameof(renderAttributeValue)); } if (attributeDescriptor.TypeName.Equals(_context.ModelExpressionTypeName, StringComparison.Ordinal)) { writer .WriteStartInstanceMethodInvocation(_context.ModelExpressionProviderPropertyName, _context.CreateModelExpressionMethodName) .Write(_context.ViewDataPropertyName) .WriteParameterSeparator() .Write(ModelLambdaVariableName) .Write(" => "); if (!complexValue) { writer .Write(ModelLambdaVariableName) .Write("."); } renderAttributeValue(writer); writer.WriteEndMethodInvocation(endLine: false); } else { base.RenderAttributeValue( attributeDescriptor, writer, codeGeneratorContext, renderAttributeValue, complexValue); } }
public CSharpLineMappingWriter( CSharpCodeWriter writer, SourceLocation documentLocation, int contentLength, string sourceFilename) : this(writer, documentLocation, contentLength) { _writePragmas = true; _writer.WriteLineNumberDirective(documentLocation, sourceFilename); _generatedLocation = _writer.GetCurrentSourceLocation(); }
private CSharpLineMappingWriter(CSharpCodeWriter writer, bool addLineMappings) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } _writer = writer; _addLineMapping = addLineMappings; _startIndent = _writer.CurrentIndent; _writer.ResetIndent(); }
private void RenderBufferedAttributeValueAccessor(CSharpCodeWriter writer) { if (_designTimeMode) { // There is no value buffer in design time mode but we still want to write out a value. We write a // value to ensure the tag helper's property type is string. writer.Write("string.Empty"); } else { writer.Write(StringValueBufferVariableName); } }
/// <summary> /// Initializes a new instance of <see cref="CSharpLineMappingWriter"/> used for generation of runtime /// line mappings. The constructed instance of <see cref="CSharpLineMappingWriter"/> does not track /// mappings between the Razor content and the generated content. /// </summary> /// <param name="writer">The <see cref="CSharpCodeWriter"/> to write output to.</param> /// <param name="documentLocation">The <see cref="SourceLocation"/> of the Razor content being mapping.</param> /// <param name="sourceFileName">The input file path.</param> public CSharpLineMappingWriter( CSharpCodeWriter writer, SourceLocation documentLocation, string sourceFileName) : this(writer, addLineMappings : false) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } _writePragmas = true; _writer.WriteLineNumberDirective(documentLocation, sourceFileName); }
/// <summary> /// Initializes a new instance of <see cref="CSharpLineMappingWriter"/> used for generation of runtime /// line mappings. The constructed instance of <see cref="CSharpLineMappingWriter"/> does not track /// mappings between the Razor content and the generated content. /// </summary> /// <param name="writer">The <see cref="CSharpCodeWriter"/> to write output to.</param> /// <param name="documentLocation">The <see cref="SourceLocation"/> of the Razor content being mapping.</param> /// <param name="sourceFileName">The input file path.</param> public CSharpLineMappingWriter( CSharpCodeWriter writer, SourceLocation documentLocation, string sourceFileName) : this(writer, addLineMappings: false) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } _writePragmas = true; _writer.WriteLineNumberDirective(documentLocation, sourceFileName); }
protected override CSharpCodeWritingScope BuildClassDeclaration(CSharpCodeWriter writer) { if (Context.Host.DesignTimeMode && string.Equals( Path.GetFileName(Context.SourceFile), ViewHierarchyUtility.ViewImportsFileName, StringComparison.OrdinalIgnoreCase)) { // Write a using TModel = System.Object; token during design time to make intellisense work writer.WriteLine($"using {ChunkHelper.TModelToken} = {typeof(object).FullName};"); } return base.BuildClassDeclaration(writer); }
public MvcCSharpCodeVisitor( CSharpCodeWriter writer, CodeGeneratorContext context) : base(writer, context) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } }
public void WriteLineNumberDirective_UsesFilePath_WhenFileInSourceLocationIsNull() { // Arrange var filePath = "some-path"; var writer = new CSharpCodeWriter(); var expected = $"#line 5 \"{filePath}\"" + writer.NewLine; var sourceLocation = new SourceLocation(10, 4, 3); // Act writer.WriteLineNumberDirective(sourceLocation, filePath); var code = writer.GenerateCode(); // Assert Assert.Equal(expected, code); }
protected virtual CSharpCodeVisitor CreateCSharpCodeVisitor( CSharpCodeWriter writer, CodeGeneratorContext context) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } return(new CSharpCodeVisitor(writer, context)); }
protected override void BuildConstructor(CSharpCodeWriter writer) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } base.BuildConstructor(writer); writer.WriteLineHiddenDirective(); var injectVisitor = new InjectChunkVisitor(writer, Context, _injectAttribute); injectVisitor.Accept(Context.ChunkTreeBuilder.Root.Children); writer.WriteLine(); writer.WriteLineHiddenDirective(); }
private void RenderBufferedAttributeValueAccessor(CSharpCodeWriter writer) { if (_designTimeMode) { // There is no value buffer in design time mode but we still want to write out a value. We write a // value to ensure the tag helper's property type is string. writer.Write("string.Empty"); } else { writer.WriteInstanceMethodInvocation( StringValueBufferVariableName, _tagHelperContext.TagHelperContentGetContentMethodName, endLine: false, parameters: _tagHelperContext.HtmlEncoderPropertyName); } }
public void Visit_IgnoresNonInjectChunks() { // Arrange var writer = new CSharpCodeWriter(); var context = CreateContext(); var visitor = new InjectChunkVisitor(writer, context, "ActivateAttribute"); // Act visitor.Accept(new Chunk[] { new LiteralChunk(), new CodeAttributeChunk() }); var code = writer.GenerateCode(); // Assert Assert.Empty(code); }
public void RenderAttributeValue_RendersModelExpressionsCorrectly( string modelExpressionType, string propertyType, string expectedValue) { // Arrange var renderer = new MvcTagHelperAttributeValueCodeRenderer( new GeneratedTagHelperAttributeContext { ModelExpressionTypeName = modelExpressionType, CreateModelExpressionMethodName = "SomeMethod", ModelExpressionProviderPropertyName = "Provider", ViewDataPropertyName = "ViewData" }); var attributeDescriptor = new TagHelperAttributeDescriptor { Name = "MyAttribute", PropertyName = "SomeProperty", TypeName = propertyType, }; var writer = new CSharpCodeWriter(); var generatorContext = new ChunkGeneratorContext( host: null, className: string.Empty, rootNamespace: string.Empty, sourceFile: string.Empty, shouldGenerateLinePragmas: true); var errorSink = new ErrorSink(); var context = new CodeGeneratorContext(generatorContext, errorSink); // Act renderer.RenderAttributeValue(attributeDescriptor, writer, context, (codeWriter) => { codeWriter.Write("MyValue"); }, complexValue: false); // Assert Assert.Equal(expectedValue, writer.GenerateCode()); }
public void WriterConstructedWithContentLength_AddsLineMappings_OnDispose() { // Arrange var location = new SourceLocation(10, 15, 20); var expected = new LineMapping( new MappingLocation(location, 30), new MappingLocation(new SourceLocation(0, 0, 0), 11)); var writer = new CSharpCodeWriter(); // Act using (var mappingWriter = new CSharpLineMappingWriter(writer, location, 30)) { writer.Write("Hello world"); } // Assert Assert.Equal("Hello world", writer.GenerateCode()); var mapping = Assert.Single(writer.LineMappingManager.Mappings); Assert.Equal(expected, mapping); }
public InjectChunkVisitor( CSharpCodeWriter writer, CodeGeneratorContext context, string injectAttributeName) : base(writer, context) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } if (injectAttributeName == null) { throw new ArgumentNullException(nameof(injectAttributeName)); } _injectAttribute = "[" + injectAttributeName + "]"; }
protected override CSharpDesignTimeCodeVisitor CreateCSharpDesignTimeCodeVisitor( CSharpCodeVisitor csharpCodeVisitor, CSharpCodeWriter writer, CodeGeneratorContext context) { if (csharpCodeVisitor == null) { throw new ArgumentNullException(nameof(csharpCodeVisitor)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } return new MvcCSharpDesignTimeCodeVisitor(csharpCodeVisitor, writer, context); }
protected override CSharpCodeVisitor CreateCSharpCodeVisitor( CSharpCodeWriter writer, CodeGeneratorContext context) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var csharpCodeVisitor = base.CreateCSharpCodeVisitor(writer, context); csharpCodeVisitor.TagHelperRenderer.AttributeValueCodeRenderer = new MvcTagHelperAttributeValueCodeRenderer(_tagHelperAttributeContext); return csharpCodeVisitor; }
/// <summary> /// Provides an entry point to append code (after execute content) to a generated Razor class. /// </summary> /// <param name="writer">The <see cref="CSharpCodeWriter"/> to receive the additional content.</param> /// <param name="chunks">The list of <see cref="Chunk"/>s for the generated program.</param> protected virtual void BuildAfterExecuteContent(CSharpCodeWriter writer, IList <Chunk> chunks) { }
public CSharpDisableWarningScope(CSharpCodeWriter writer) : this(writer, 219) { }
public CSharpLineMappingWriter(CSharpCodeWriter writer, SourceLocation documentLocation, int contentLength) : this(writer, addLineMappings: true) { _documentMapping = new MappingLocation(documentLocation, contentLength); _generatedLocation = _writer.GetCurrentSourceLocation(); }
public NoUniqueIdsTagHelperCodeRenderer(IChunkVisitor bodyVisitor, CSharpCodeWriter writer, CodeGeneratorContext context) : base(bodyVisitor, writer, context) { }
public CSharpLiteralCodeVisitor( CSharpTagHelperCodeRenderer tagHelperRenderer, CSharpCodeWriter writer, CodeGeneratorContext context) : base(writer, context) { // Ensure that no matter how this class is used, we don't create numerous CSharpTagHelperCodeRenderer // instances. TagHelperRenderer = tagHelperRenderer; }
public TagHelperAttributeCodeVisitor( CSharpCodeWriter writer, CodeGeneratorContext context) : base(writer, context) { }
private static TrackingUniqueIdsTagHelperCodeRenderer CreateCodeRenderer() { var writer = new CSharpCodeWriter(); var codeGeneratorContext = CreateContext(); var visitor = new CSharpCodeVisitor(writer, codeGeneratorContext); var codeRenderer = new TrackingUniqueIdsTagHelperCodeRenderer( visitor, writer, codeGeneratorContext); visitor.TagHelperRenderer = codeRenderer; return codeRenderer; }
public CSharpLineMappingWriter(CSharpCodeWriter writer, SourceLocation documentLocation, int contentLength) : this(writer, addLineMappings : true) { _documentMapping = new MappingLocation(documentLocation, contentLength); _generatedLocation = _writer.GetCurrentSourceLocation(); }
public void Visit_WithDesignTimeHost_GeneratesPropertiesAndLinePragmas_ForInjectChunks() { // Arrange var expected = string.Join(Environment.NewLine, @"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]", @"public", @"#line 1 """"", @"MyType1 MyPropertyName1", "", @"#line default", @"#line hidden", @"{ get; private set; }", @"[Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]", @"public", @"#line 1 """"", @"MyType2 @MyPropertyName2", "", @"#line default", @"#line hidden", @"{ get; private set; }", ""); var writer = new CSharpCodeWriter(); var context = CreateContext(); context.Host.DesignTimeMode = true; var visitor = new InjectChunkVisitor(writer, context, "Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute"); var factory = SpanFactory.CreateCsHtml(); var node = (Span)factory.Code("Some code") .As(new InjectParameterGenerator("MyType", "MyPropertyName")); // Act visitor.Accept(new Chunk[] { new LiteralChunk(), new InjectChunk("MyType1", "MyPropertyName1") { Association = node }, new InjectChunk("MyType2", "@MyPropertyName2") { Association = node } }); var code = writer.GenerateCode(); // Assert Assert.Equal(expected, code); }