Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit 3bafd0d

Browse files
author
N. Taylor Mullen
committed
Add line mappings to project TagHelper attribute values.
- We now create LineMappings for instances where a TagHelper's attribute value is not of a string type. - This will enable the Razor editor to create projections from .cshtml => .cs for TagHelper attributes. - Modified the TagHelperCodeGenerator and TagHelperBlockBuiler to accurately track the attribute values start locations so it could flow into code generation. - Modified existing tests to account for the new line mappings. #207
1 parent 8101461 commit 3bafd0d

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

src/Microsoft.AspNet.Razor/Generator/Compiler/CodeBuilder/CSharp/CSharpTagHelperCodeRenderer.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Globalization;
77
using System.Linq;
88
using Microsoft.AspNet.Razor.TagHelpers;
9+
using Microsoft.AspNet.Razor.Text;
910

1011
namespace Microsoft.AspNet.Razor.Generator.Compiler.CSharp
1112
{
@@ -249,7 +250,7 @@ private void RenderBoundHTMLAttributes(IDictionary<string, Chunk> chunkAttribute
249250

250251
// We aren't a bufferable attribute which means we have no Razor code in our value.
251252
// Therefore we can just use the "textValue" as the attribute value.
252-
RenderRawAttributeValue(textValue, attributeDescriptor);
253+
RenderRawAttributeValue(textValue, attributeValueChunk.Start, attributeDescriptor);
253254
}
254255

255256
// End the assignment to the attribute.
@@ -405,13 +406,26 @@ private void RenderBufferedAttributeValue(TagHelperAttributeDescriptor attribute
405406
});
406407
}
407408

408-
private void RenderRawAttributeValue(string value, TagHelperAttributeDescriptor attributeDescriptor)
409+
private void RenderRawAttributeValue(string value,
410+
SourceLocation documentLocation,
411+
TagHelperAttributeDescriptor attributeDescriptor)
409412
{
410413
RenderAttributeValue(
411414
attributeDescriptor,
412415
valueRenderer: (writer) =>
413416
{
414-
writer.Write(value);
417+
// We only want to do the work of generating a line mapping if we're in design time mode.
418+
if (_context.Host.DesignTimeMode)
419+
{
420+
using (new CSharpLineMappingWriter(_writer, documentLocation, value.Length))
421+
{
422+
writer.Write(value);
423+
}
424+
}
425+
else
426+
{
427+
writer.Write(value);
428+
}
415429
});
416430
}
417431

src/Microsoft.AspNet.Razor/Generator/TagHelperCodeGenerator.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using Microsoft.AspNet.Razor.Generator.Compiler;
78
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
89
using Microsoft.AspNet.Razor.Parser.TagHelpers;
910
using Microsoft.AspNet.Razor.TagHelpers;
11+
using Microsoft.AspNet.Razor.Text;
1012

1113
namespace Microsoft.AspNet.Razor.Generator
1214
{
@@ -63,7 +65,8 @@ public override void GenerateStartBlockCode(Block target, CodeGeneratorContext c
6365

6466
attributes[attribute.Key] = new ChunkBlock
6567
{
66-
Children = chunks
68+
Children = chunks,
69+
Start = chunks.FirstOrDefault()?.Start ?? SourceLocation.Zero
6770
};
6871

6972
// Reset the code tree builder so we can build a new one for the next attribute

src/Microsoft.AspNet.Razor/Parser/TagHelpers/TagHelperBlockBuilder.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ private static KeyValuePair<string, SyntaxTreeNode> ParseSpan(
159159
Kind = span.Kind
160160
};
161161
var htmlSymbols = span.Symbols.OfType<HtmlSymbol>().ToArray();
162+
var capturedAttributeValueStart = false;
163+
var attributeValueStartLocation = span.Start;
162164
var symbolOffset = 1;
163165
string name = null;
164166

@@ -174,6 +176,16 @@ private static KeyValuePair<string, SyntaxTreeNode> ParseSpan(
174176
}
175177
else if (afterEquals)
176178
{
179+
// When symbols are accepted into SpanBuilders their locations get altered to abide by the
180+
// parent which is why we need to mark our start location prior to adding the symbol so we know
181+
// the location of the attribute value start within the document.
182+
if (!capturedAttributeValueStart)
183+
{
184+
capturedAttributeValueStart = true;
185+
186+
attributeValueStartLocation += symbol.Start;
187+
}
188+
177189
builder.Accept(symbol);
178190
}
179191
else if (symbol.Type == HtmlSymbolType.Equals)
@@ -202,6 +214,10 @@ private static KeyValuePair<string, SyntaxTreeNode> ParseSpan(
202214
}
203215
}
204216

217+
// After all symbols have been added we need to offset the builders start position. Adding symbols to a
218+
// SpanBuilder alters its position prior to it being occupied.
219+
builder.Start = attributeValueStartLocation;
220+
205221
return CreateMarkupAttribute(name, builder, attributeValueTypes);
206222
}
207223

test/Microsoft.AspNet.Razor.Test/Generator/CSharpTagHelperRenderingTest.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,14 @@ public static TheoryData DesignTimeTagHelperTestData
8181
generatedAbsoluteIndex: 475,
8282
generatedLineIndex: 15,
8383
characterOffsetIndex: 14,
84-
contentLength: 11)
84+
contentLength: 11),
85+
BuildLineMapping(documentAbsoluteIndex: 57,
86+
documentLineIndex: 2,
87+
documentCharacterOffsetIndex: 28,
88+
generatedAbsoluteIndex: 927,
89+
generatedLineIndex: 33,
90+
generatedCharacterOffsetIndex: 31,
91+
contentLength: 4)
8592
}
8693
},
8794
{
@@ -95,7 +102,14 @@ public static TheoryData DesignTimeTagHelperTestData
95102
generatedAbsoluteIndex: 475,
96103
generatedLineIndex: 15,
97104
characterOffsetIndex: 14,
98-
contentLength: 11)
105+
contentLength: 11),
106+
BuildLineMapping(documentAbsoluteIndex: 189,
107+
documentLineIndex: 6,
108+
documentCharacterOffsetIndex: 40,
109+
generatedAbsoluteIndex: 1599,
110+
generatedLineIndex: 44,
111+
generatedCharacterOffsetIndex: 40,
112+
contentLength: 4)
99113
}
100114
},
101115
{
@@ -125,6 +139,7 @@ public static TheoryData DesignTimeTagHelperTestData
125139
BuildLineMapping(218, 9, 13, 1356, 56, 12, 27),
126140
BuildLineMapping(346, 12, 1754, 68, 0, 48),
127141
BuildLineMapping(440, 15, 46, 2004, 78, 6, 8),
142+
BuildLineMapping(457, 15, 63, 2267, 85, 40, 4),
128143
BuildLineMapping(501, 16, 31, 2384, 88, 6, 30),
129144
BuildLineMapping(568, 17, 30, 2733, 97, 0, 10),
130145
BuildLineMapping(601, 17, 63, 2815, 103, 0, 8),

0 commit comments

Comments
 (0)