Example #1
0
        public void WriterConstructedWithoutContentLengthAndSourceFile_AddsLinePragmas_OnDispose()
        {
            // Arrange
            var location = new SourceLocation(10, 1, 20);
            var expected = string.Join(Environment.NewLine,
                                       @"#line 2 ""myfile""",
                                       "Hello world",
                                       "",
                                       "#line default",
                                       "#line hidden",
                                       "");
            var expectedMappings = new LineMapping(
                new MappingLocation(location, 30),
                new MappingLocation(new SourceLocation(18, 1, 0), 11));
            var writer = new CSharpCodeWriter();

            // Act
            using (var mappingWriter = new CSharpLineMappingWriter(writer, location, "myfile"))
            {
                writer.Write("Hello world");
            }

            // Assert
            Assert.Equal(expected, writer.GenerateCode());
            Assert.Empty(writer.LineMappingManager.Mappings);
        }
        public void WriterConstructedWithoutContentLengthAndSourceFile_AddsLinePragmas_OnDispose()
        {
            // Arrange
            var location = new SourceLocation(10, 1, 20);
            var expected = string.Join(Environment.NewLine,
                                       @"#line 2 ""myfile""",
                                       "Hello world",
                                       "",
                                       "#line default",
                                       "#line hidden",
                                       "");
            var expectedMappings = new LineMapping(
                                new MappingLocation(location, 30),
                                new MappingLocation(new SourceLocation(18, 1, 0), 11));
            var writer = new CSharpCodeWriter();

            // Act
            using (var mappingWriter = new CSharpLineMappingWriter(writer, location, "myfile"))
            {
                writer.Write("Hello world");
            }

            // Assert
            Assert.Equal(expected, writer.GenerateCode());
            Assert.Empty(writer.LineMappingManager.Mappings);
        }
Example #3
0
        public void CreateCodeMapping(string padding, string code, Chunk chunk)
        {
            using (CSharpLineMappingWriter mappingWriter = Writer.BuildLineMapping(chunk.Start, code.Length, Context.SourceFile))
            {
                Writer.Write(padding);

                mappingWriter.MarkLineMappingStart();
                Writer.Write(code);
                mappingWriter.MarkLineMappingEnd();
            }
        }
Example #4
0
        private void RenderRuntimeExpressionBlockChunkWithContentSpan(ExpressionBlockChunk chunk, Span contentSpan)
        {
            var generateInstrumentation = ShouldGenerateInstrumentationForExpressions();

            if (generateInstrumentation)
            {
                Writer.WriteStartInstrumentationContext(Context, contentSpan, isLiteral: false);
            }

            using (var mappingWriter = new CSharpLineMappingWriter(Writer, chunk.Start, Context.SourceFile))
            {
                if (!string.IsNullOrEmpty(Context.TargetWriterName))
                {
                    var generatedStart =
                        WriteToMethodName.Length +
                        Context.TargetWriterName.Length +
                        3; // 1 for the opening '(' and 2 for ', '

                    var padding = _paddingBuilder.BuildExpressionPadding(contentSpan, generatedStart);

                    Writer
                    .Write(padding)
                    .WriteStartMethodInvocation(WriteToMethodName)
                    .Write(Context.TargetWriterName)
                    .WriteParameterSeparator();
                }
                else
                {
                    var generatedStart =
                        WriteMethodName.Length +
                        1;  // for the opening '('

                    var padding = _paddingBuilder.BuildExpressionPadding(contentSpan, generatedStart);

                    Writer
                    .Write(padding)
                    .WriteStartMethodInvocation(WriteMethodName);
                }

                Accept(chunk.Children);

                Writer.WriteEndMethodInvocation();
            }

            if (generateInstrumentation)
            {
                Writer.WriteEndInstrumentationContext(Context);
            }
        }
        protected override void Visit(SetBaseTypeChunk chunk)
        {
            if (Context.Host.DesignTimeMode)
            {
                using (CSharpLineMappingWriter lineMappingWriter = Writer.BuildLineMapping(chunk.Start, chunk.TypeName.Length, Context.SourceFile))
                {
                    Writer.Indent(chunk.Start.CharacterIndex);

                    lineMappingWriter.MarkLineMappingStart();
                    Writer.Write(chunk.TypeName);
                    lineMappingWriter.MarkLineMappingEnd();

                    Writer.Write(" ").Write(InheritsHelper).Write(" = null;");
                }
            }
        }
        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);
        }
Example #7
0
        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);
        }
Example #8
0
        private void RenderBoundHTMLAttributes(IDictionary <string, Chunk> chunkAttributes,
                                               string tagHelperVariableName,
                                               IEnumerable <TagHelperAttributeDescriptor> attributeDescriptors,
                                               Dictionary <string, string> htmlAttributeValues)
        {
            foreach (var attributeDescriptor in attributeDescriptors)
            {
                Chunk attributeValueChunk;

                var providedAttribute = chunkAttributes.TryGetValue(attributeDescriptor.Name,
                                                                    out attributeValueChunk);

                if (providedAttribute)
                {
                    var attributeValueRecorded = htmlAttributeValues.ContainsKey(attributeDescriptor.Name);

                    // Bufferable attributes are attributes that can have Razor code inside of them.
                    var bufferableAttribute = IsStringAttribute(attributeDescriptor);

                    // Plain text values are non Razor code (@DateTime.Now) values. If an attribute is bufferable it
                    // may be more than just a plain text value, it may also contain Razor code which is why we attempt
                    // to retrieve a plain text value here.
                    string textValue;
                    var    isPlainTextValue = TryGetPlainTextValue(attributeValueChunk, out textValue);

                    // If we haven't recorded a value and we need to buffer an attribute value and the value is not
                    // plain text then we need to prepare the value prior to setting it below.
                    if (!attributeValueRecorded && bufferableAttribute && !isPlainTextValue)
                    {
                        BuildBufferedWritingScope(attributeValueChunk);
                    }

                    // We capture the tag helpers property value accessor so we can retrieve it later (if we need to).
                    var valueAccessor = string.Format(CultureInfo.InvariantCulture,
                                                      "{0}.{1}",
                                                      tagHelperVariableName,
                                                      attributeDescriptor.PropertyName);

                    // If we haven't recorded this attribute value before then we need to record its value.
                    if (!attributeValueRecorded)
                    {
                        // We only need to create attribute values once per HTML element (not once per tag helper).
                        // We're saving the value accessor so we can retrieve it later if there are more tag
                        // helpers that need the value.
                        htmlAttributeValues.Add(attributeDescriptor.Name, valueAccessor);

                        if (bufferableAttribute)
                        {
                            _writer.WriteStartAssignment(valueAccessor);

                            if (isPlainTextValue)
                            {
                                // If the attribute is bufferable but has a plain text value that means the value
                                // is a string which needs to be surrounded in quotes.
                                RenderQuotedAttributeValue(textValue, attributeDescriptor);
                            }
                            else
                            {
                                // The value contains more than plain text e.g.
                                // stringAttribute ="Time: @DateTime.Now"
                                RenderBufferedAttributeValue(attributeDescriptor);
                            }

                            _writer.WriteLine(";");
                        }
                        else
                        {
                            // Write out simple assignment for non-string property value. Try to keep the whole
                            // statement together and the #line pragma correct to make debugging possible.
                            using (var lineMapper = new CSharpLineMappingWriter(
                                       _writer,
                                       attributeValueChunk.Association.Start,
                                       _context.SourceFile))
                            {
                                // Place the assignment LHS to align RHS with original attribute value's indentation.
                                // Unfortunately originalIndent is incorrect if original line contains tabs. Unable to
                                // use a CSharpPaddingBuilder because the Association has no Previous node; lost the
                                // original Span sequence when the parse tree was rewritten.
                                var originalIndent  = attributeValueChunk.Start.CharacterIndex;
                                var generatedLength = valueAccessor.Length + " = ".Length;
                                var newIndent       = originalIndent - generatedLength;
                                if (newIndent > 0)
                                {
                                    _writer.Indent(newIndent);
                                }

                                _writer.WriteStartAssignment(valueAccessor);
                                lineMapper.MarkLineMappingStart();

                                // Write out bare expression for this attribute value. Property is not a string.
                                // So quoting or buffering are not helpful.
                                RenderRawAttributeValue(attributeValueChunk, attributeDescriptor, isPlainTextValue);

                                // End the assignment to the attribute.
                                lineMapper.MarkLineMappingEnd();
                                _writer.WriteLine(";");
                            }
                        }

                        // Execution contexts are a runtime feature.
                        if (_designTimeMode)
                        {
                            continue;
                        }

                        // We need to inform the context of the attribute value.
                        _writer
                        .WriteStartInstanceMethodInvocation(
                            ExecutionContextVariableName,
                            _tagHelperContext.ExecutionContextAddTagHelperAttributeMethodName)
                        .WriteStringLiteral(attributeDescriptor.Name)
                        .WriteParameterSeparator()
                        .Write(valueAccessor)
                        .WriteEndMethodInvocation();
                    }
                    else
                    {
                        // The attribute value has already been recorded, lets retrieve it from the stored value
                        // accessors.
                        _writer
                        .WriteStartAssignment(valueAccessor)
                        .Write(htmlAttributeValues[attributeDescriptor.Name])
                        .WriteLine(";");
                    }
                }
            }
        }