/// <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);
            AttributeValueCodeRenderer = new TagHelperAttributeValueCodeRenderer();
        }
Пример #2
0
        public void DecorateCodeGenerator_DesignTimeRazorPathNormalizer_NormalizesChunkInheritanceUtilityPaths(
            string rootPrefix)
        {
            // Arrange
            var rootedAppPath = $"{rootPrefix}SomeComputer/Location/Project/";
            var rootedFilePath = $"{rootPrefix}SomeComputer/Location/Project/src/file.cshtml";
            var host = new MvcRazorHost(
                chunkTreeCache: null,
                pathNormalizer: new DesignTimeRazorPathNormalizer(rootedAppPath));
            var chunkInheritanceUtility = new PathValidatingChunkInheritanceUtility(host);
            var codeGeneratorContext = new CodeGeneratorContext(
                new ChunkGeneratorContext(
                    host,
                    host.DefaultClassName,
                    host.DefaultNamespace,
                    rootedFilePath,
                    shouldGenerateLinePragmas: true),
                new ErrorSink());
            var codeGenerator = new CSharpCodeGenerator(codeGeneratorContext);
            host.ChunkInheritanceUtility = chunkInheritanceUtility;

            // Act
            host.DecorateCodeGenerator(codeGenerator, codeGeneratorContext);

            // Assert
            Assert.Equal("src/file.cshtml", chunkInheritanceUtility.InheritedChunkTreePagePath, StringComparer.Ordinal);
        }
Пример #3
0
        public MvcCSharpCodeGenerator(
            CodeGeneratorContext context,
            string defaultModel,
            string injectAttribute,
            GeneratedTagHelperAttributeContext tagHelperAttributeContext)
            : base(context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (defaultModel == null)
            {
                throw new ArgumentNullException(nameof(defaultModel));
            }

            if (injectAttribute == null)
            {
                throw new ArgumentNullException(nameof(injectAttribute));
            }

            if (tagHelperAttributeContext == null)
            {
                throw new ArgumentNullException(nameof(tagHelperAttributeContext));
            }

            _tagHelperAttributeContext = tagHelperAttributeContext;
            _defaultModel = defaultModel;
            _injectAttribute = injectAttribute;
        }
 public MvcCSharpDesignTimeCodeVisitor(
     CSharpCodeVisitor csharpCodeVisitor,
     CSharpCodeWriter writer,
     CodeGeneratorContext context)
     : base(csharpCodeVisitor, writer, context)
 {
 }
        /// <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);
        }
Пример #6
0
        protected override CSharpCodeVisitor CreateCSharpCodeVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
        {
            var csharpCodeVisitor = new MyCSharpCodeVisitor(writer, context);

            csharpCodeVisitor.TagHelperRenderer.AttributeValueCodeRenderer =
                new MvcTagHelperAttributeValueCodeRenderer(_tagHelperAttributeContext);

            return csharpCodeVisitor;
        }
            protected override CSharpCodeVisitor CreateCSharpCodeVisitor(
                CSharpCodeWriter writer,
                CodeGeneratorContext context)
            {
                var bodyVisitor = base.CreateCSharpCodeVisitor(writer, context);

                bodyVisitor.TagHelperRenderer.AttributeValueCodeRenderer = new CustomTagHelperAttributeCodeRenderer();

                return bodyVisitor;
            }
        /// <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
                    .WriteStartMethodInvocation(_context.CreateModelExpressionMethodName)
                    .Write(ModelLambdaVariableName)
                    .Write(" => ");
                if (!complexValue)
                {
                    writer
                        .Write(ModelLambdaVariableName)
                        .Write(".");

                }

                renderAttributeValue(writer);

                writer.WriteEndMethodInvocation(endLine: false);
            }
            else
            {
                base.RenderAttributeValue(
                    attributeDescriptor,
                    writer,
                    codeGeneratorContext,
                    renderAttributeValue,
                    complexValue);
            }
        }
Пример #9
0
 public override CodeGenerator DecorateCodeGenerator(CodeGenerator incomingBuilder, CodeGeneratorContext context)
 {
     if (incomingBuilder is CodeGenTestCodeGenerator)
     {
         return incomingBuilder;
     }
     else
     {
         return new CodeGenTestCodeGenerator(context);
     }
 }
Пример #10
0
 private static Mock<ChunkVisitor<CodeWriter>> CreateVisitor()
 {
     var codeGeneratorContext = new CodeGeneratorContext(
         new RazorEngineHost(new CSharpRazorCodeLanguage()),
         "myclass",
         "myns",
         string.Empty,
         shouldGenerateLinePragmas: false,
         errorSink: new ErrorSink());
     var writer = Mock.Of<CodeWriter>();
     return new Mock<ChunkVisitor<CodeWriter>>(writer, codeGeneratorContext);
 }
Пример #11
0
        /// <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(
            [NotNull] IChunkVisitor bodyVisitor,
            [NotNull] CSharpCodeWriter writer,
            [NotNull] CodeGeneratorContext context)
        {
            _bodyVisitor = bodyVisitor;
            _writer = writer;
            _context = context;
            _tagHelperContext = context.Host.GeneratedClassContext.GeneratedTagHelperContext;
            _designTimeMode = context.Host.DesignTimeMode;

            _literalBodyVisitor = new CSharpLiteralCodeVisitor(this, writer, context);
            AttributeValueCodeRenderer = new TagHelperAttributeValueCodeRenderer();
        }
Пример #12
0
        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));
            }
        }
Пример #13
0
        public void ChunkTreeWithUsings()
        {
            var syntaxTreeNode = new Mock<Span>(new SpanBuilder());
            var language = new CSharpRazorCodeLanguage();
            var host = new CodeGenTestHost(language);
            var codeGeneratorContext = new CodeGeneratorContext(
                host,
                "TestClass",
                "TestNamespace",
                "Foo.cs",
                shouldGenerateLinePragmas: false,
                errorSink: new ErrorSink());
            codeGeneratorContext.ChunkTreeBuilder.AddUsingChunk("FakeNamespace1", syntaxTreeNode.Object);
            codeGeneratorContext.ChunkTreeBuilder.AddUsingChunk("FakeNamespace2.SubNamespace", syntaxTreeNode.Object);
            var codeGenerator = new CodeGenTestCodeGenerator(codeGeneratorContext);
            var testFile = TestFile.Create("TestFiles/CodeGenerator/Output/CSharpCodeGenerator.cs");

            string expectedOutput;
#if GENERATE_BASELINES
            if (testFile.Exists())
            {
                expectedOutput = testFile.ReadAllText();
            }
            else
            {
                expectedOutput = null;
            }
#else
            expectedOutput = testFile.ReadAllText();
#endif

            // Act
            var result = codeGenerator.Generate();

            // Assert
#if GENERATE_BASELINES
            // Update baseline files if files do not already match.
            if (!string.Equals(expectedOutput, result.Code, StringComparison.Ordinal))
            {
                BaselineWriter.WriteBaseline(
                    @"test\Microsoft.AspNet.Razor.Test\TestFiles\CodeGenerator\Output\CSharpCodeGenerator.cs",
                    result.Code);
            }
#else
            Assert.Equal(expectedOutput, result.Code);
#endif
        }
Пример #14
0
        public CodeGenerator DecorateCodeGenerator(CodeGenerator incomingGenerator, CodeGeneratorContext context)
        {
            var inheritedChunkTrees = GetInheritedChunkTrees(context.SourceFile);

            ChunkInheritanceUtility.MergeInheritedChunkTrees(
                context.ChunkTreeBuilder.ChunkTree,
                inheritedChunkTrees,
                _host.DefaultModel);

            return new MyCSharpCodeGenerator(
                context,
                _host.DefaultModel,
                _host.InjectAttribute,
                new GeneratedTagHelperAttributeContext
                {
                    ModelExpressionTypeName = _host.ModelExpressionType,
                    CreateModelExpressionMethodName = _host.CreateModelExpressionMethod
                });
        }
        public void CreateCodeGenerator_ReturnsNewCSharpCodeGenerator()
        {
            // Arrange
            var language = new CSharpRazorCodeLanguage();
            var host = new RazorEngineHost(language);
            var codeGeneratorContext = new CodeGeneratorContext(
                host,
                "myclass",
                "myns",
                string.Empty,
                shouldGenerateLinePragmas: false,
                errorSink: new ErrorSink());

            // Act
            var generator = language.CreateCodeGenerator(codeGeneratorContext);

            // Assert
            Assert.IsType<CSharpCodeGenerator>(generator);
        }
Пример #16
0
        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;
        }
        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
            {
                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());
        }
Пример #18
0
        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 + "]";
        }
Пример #19
0
        /// <inheritdoc />
        public override CodeGenerator DecorateCodeGenerator(
            CodeGenerator incomingGenerator,
            CodeGeneratorContext context)
        {
            if (incomingGenerator == null)
            {
                throw new ArgumentNullException(nameof(incomingGenerator));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var inheritedChunkTrees = GetInheritedChunkTrees(context.SourceFile);

            ChunkInheritanceUtility.MergeInheritedChunkTrees(
                context.ChunkTreeBuilder.ChunkTree,
                inheritedChunkTrees,
                DefaultModel);

            return new MvcCSharpCodeGenerator(
                context,
                DefaultModel,
                InjectAttribute,
                new GeneratedTagHelperAttributeContext
                {
                    ModelExpressionTypeName = ModelExpressionType,
                    CreateModelExpressionMethodName = CreateModelExpressionMethod
                });
        }
Пример #20
0
        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);
        }
Пример #21
0
        /// <summary>
        /// Gets an instance of the code generator and is provided an opportunity to decorate or replace it
        /// </summary>
        /// <param name="incomingBuilder">The code generator</param>
        /// <returns>Either the same code generator, after modifications, or a different code generator.</returns>
        public virtual CodeGenerator DecorateCodeGenerator(
            CodeGenerator incomingBuilder,
            CodeGeneratorContext context)
        {
            if (incomingBuilder == null)
            {
                throw new ArgumentNullException(nameof(incomingBuilder));
            }

            return incomingBuilder;
        }
Пример #22
0
        protected internal virtual GeneratorResults GenerateCodeCore(
            [NotNull] ITextDocument input,
            string className,
            string rootNamespace,
            string sourceFileName,
            string checksum,
            CancellationToken? cancelToken)
        {
            className = (className ?? Host.DefaultClassName) ?? DefaultClassName;
            rootNamespace = (rootNamespace ?? Host.DefaultNamespace) ?? DefaultNamespace;

            // Run the parser
            var parser = CreateParser(sourceFileName);
            Debug.Assert(parser != null);
            var results = parser.Parse(input);

            // Generate code
            var chunkGenerator = CreateChunkGenerator(className, rootNamespace, sourceFileName);
            chunkGenerator.DesignTimeMode = Host.DesignTimeMode;
            chunkGenerator.Visit(results);

            var codeGeneratorContext = new CodeGeneratorContext(chunkGenerator.Context, results.ErrorSink);
            codeGeneratorContext.Checksum = checksum;
            var codeGenerator = CreateCodeGenerator(codeGeneratorContext);
            var codeGeneratorResult = codeGenerator.Generate();

            // Collect results and return
            return new GeneratorResults(results, codeGeneratorResult, codeGeneratorContext.ChunkTreeBuilder.ChunkTree);
        }
Пример #23
0
 protected override CSharpCodeVisitor CreateCSharpCodeVisitor(
     CSharpCodeWriter writer,
     CodeGeneratorContext context)
 {
     var visitor = base.CreateCSharpCodeVisitor(writer, context);
     visitor.TagHelperRenderer = new NoUniqueIdsTagHelperCodeRenderer(visitor, writer, context)
     {
         AttributeValueCodeRenderer =
             new MvcTagHelperAttributeValueCodeRenderer(_tagHelperAttributeContext)
     };
     return visitor;
 }
Пример #24
0
 public TestCSharpCodeGenerator(
     CodeGeneratorContext context,
     string defaultModel,
     string activateAttribute,
     GeneratedTagHelperAttributeContext tagHelperAttributeContext)
     : base(context, defaultModel, activateAttribute, tagHelperAttributeContext)
 {
     _tagHelperAttributeContext = tagHelperAttributeContext;
 }
Пример #25
0
            public override CodeGenerator DecorateCodeGenerator(
                CodeGenerator incomingBuilder,
                CodeGeneratorContext context)
            {
                base.DecorateCodeGenerator(incomingBuilder, context);

                return new TestCSharpCodeGenerator(
                    context,
                    DefaultModel,
                    "Microsoft.AspNet.Mvc.Razor.Internal.RazorInjectAttribute",
                    new GeneratedTagHelperAttributeContext
                    {
                        ModelExpressionTypeName = ModelExpressionType,
                        CreateModelExpressionMethodName = CreateModelExpressionMethod
                    });
            }
Пример #26
0
 /// <summary>
 /// Gets an instance of the code generator and is provided an opportunity to decorate or replace it
 /// </summary>
 /// <param name="incomingBuilder">The code generator</param>
 /// <returns>Either the same code generator, after modifications, or a different code generator.</returns>
 public virtual CodeGenerator DecorateCodeGenerator(
     [NotNull] CodeGenerator incomingBuilder,
     CodeGeneratorContext context)
 {
     return incomingBuilder;
 }
Пример #27
0
 protected internal virtual CodeGenerator CreateCodeGenerator(CodeGeneratorContext context)
 {
     return Host.DecorateCodeGenerator(Host.CodeLanguage.CreateCodeGenerator(context), context);
 }
Пример #28
0
 public CodeGenTestCodeGenerator(CodeGeneratorContext context)
     : base(context)
 {
 }
            public TrackingUniqueIdsTagHelperCodeRenderer(
                IChunkVisitor bodyVisitor,
                CSharpCodeWriter writer,
                CodeGeneratorContext context)
                : base(bodyVisitor, writer, context)
            {

            }
Пример #30
0
 public MyCSharpCodeVisitor(CSharpCodeWriter writer, CodeGeneratorContext context)
     : base(writer, context)
 {
     Writer = writer;
     Context = context;
 }