@@ -177,8 +177,9 @@ class MustachioParser {
177177 _index += 2 ;
178178
179179 var key = template.substring (startIndex, endIndex);
180- return _TagParseResult .ok (
181- Partial (key, span: _sourceFile.span (tagStartIndex, _index)));
180+ var keySpan = _sourceFile.span (startIndex, endIndex);
181+ return _TagParseResult .ok (Partial (key,
182+ span: _sourceFile.span (tagStartIndex, _index), keySpan: keySpan));
182183 }
183184
184185 /// Tries to parse a section tag at [_index] .
@@ -208,20 +209,30 @@ class MustachioParser {
208209 // inside the section, are the children of the [three] section. The
209210 // [three] section is the singular child node of the [two] section, and
210211 // the [two] section is the singular child of the [one] section.
211- var section =
212- Section ([parsedKey.names.last], children, invert: invert, span: span);
213- for (var sectionKey in parsedKey.names.reversed.skip (1 )) {
212+ var lastName = parsedKey.names.last;
213+ var keySpanEndOffset = parsedKey.span.end.offset;
214+ var lastNameSpan = _sourceFile.span (
215+ keySpanEndOffset - lastName.length, keySpanEndOffset);
216+ var section = Section ([lastName], children,
217+ invert: invert, span: span, keySpan: lastNameSpan);
218+ //for (var sectionKey in parsedKey.names.reversed.skip(1)) {
219+ for (var i = parsedKey.names.length - 2 ; i >= 0 ; i-- ) {
220+ var sectionKey = parsedKey.names[i];
221+ // To find the start offset of the ith name, take the length of all of
222+ // the names 0 through `i - 1` re-joined with '.', and a final '.' at
223+ // the end.
224+ var sectionKeyStartOffset = parsedKey.span.start.offset +
225+ (i == 0 ? 0 : parsedKey.names.take (i).join ('.' ).length + 1 );
226+ var keySpan = _sourceFile.span (
227+ sectionKeyStartOffset, sectionKeyStartOffset + sectionKey.length);
214228 section = Section ([sectionKey], [section],
215- invert: false ,
216- // TODO(srawlins): It may not make sense to use [span] here; we
217- // might want to do the work to find the span of [sectionKey].
218- span: span);
229+ invert: false , span: span, keySpan: keySpan);
219230 }
220231 return _TagParseResult .ok (section);
221232 }
222233
223- return _TagParseResult .ok (
224- Section (parsedKey.names, children, invert: invert, span: span));
234+ return _TagParseResult .ok (Section (parsedKey.names, children,
235+ invert: invert, span: span, keySpan : parsedKey. span));
225236 }
226237
227238 /// Tries to parse an end tag at [_index] .
@@ -257,8 +268,9 @@ class MustachioParser {
257268 return _TagParseResult .endOfFile;
258269 }
259270
271+ var span = _sourceFile.span (tagStartIndex, _index);
260272 return _TagParseResult .ok (Variable (parsedKey.names,
261- escape: escape, span: _sourceFile. span (tagStartIndex, _index) ));
273+ escape: escape, span: span, keySpan : parsedKey.span ));
262274 }
263275
264276 /// Tries to parse a key at [_index] .
@@ -289,6 +301,7 @@ class MustachioParser {
289301 }
290302
291303 var key = template.substring (startIndex, _index);
304+ var span = _sourceFile.span (startIndex, _index);
292305
293306 if (key.length > 1 &&
294307 (key.codeUnitAt (0 ) == $dot || key.codeUnitAt (key.length - 1 ) == $dot)) {
@@ -306,7 +319,7 @@ class MustachioParser {
306319 if (escape) {
307320 if (char0 == $rbrace && char1 == $rbrace) {
308321 _index += 2 ;
309- return _KeyParseResult (_KeyParseResultType .parsedKey, key);
322+ return _KeyParseResult (_KeyParseResultType .parsedKey, key, span : span );
310323 } else {
311324 return _KeyParseResult .notKey;
312325 }
@@ -318,7 +331,7 @@ class MustachioParser {
318331 var char2 = _nextNextChar;
319332 if (char0 == $rbrace && char1 == $rbrace && char2 == $rbrace) {
320333 _index += 3 ;
321- return _KeyParseResult (_KeyParseResultType .parsedKey, key);
334+ return _KeyParseResult (_KeyParseResultType .parsedKey, key, span : span );
322335 } else {
323336 return _KeyParseResult .notKey;
324337 }
@@ -391,7 +404,10 @@ class Variable implements MustachioNode {
391404 @override
392405 final SourceSpan span;
393406
394- Variable (this .key, {@required this .escape, @required this .span});
407+ final SourceSpan keySpan;
408+
409+ Variable (this .key,
410+ {@required this .escape, @required this .span, @required this .keySpan});
395411
396412 @override
397413 String toString () => 'Variable[$key , escape=$escape ]' ;
@@ -410,8 +426,10 @@ class Section implements MustachioNode {
410426 @override
411427 final SourceSpan span;
412428
429+ final SourceSpan keySpan;
430+
413431 Section (this .key, this .children,
414- {@required this .invert, @required this .span});
432+ {@required this .invert, @required this .span, @required this .keySpan });
415433
416434 @override
417435 String toString () => 'Section[$key , invert=$invert ]' ;
@@ -425,7 +443,9 @@ class Partial implements MustachioNode {
425443 @override
426444 final SourceSpan span;
427445
428- Partial (this .key, {@required this .span});
446+ final SourceSpan keySpan;
447+
448+ Partial (this .key, {@required this .span, @required this .keySpan});
429449}
430450
431451/// An enumeration of types of tag parse results.
@@ -490,13 +510,18 @@ class _KeyParseResult {
490510
491511 final List <String > names;
492512
493- const _KeyParseResult ._(this .type, this .names);
513+ /// The source span from where this key was parsed, if this represents a
514+ /// parsed key, othwerwise `null` .
515+ final SourceSpan /*?*/ span;
516+
517+ const _KeyParseResult ._(this .type, this .names, {this .span});
494518
495- factory _KeyParseResult (_KeyParseResultType type, String key) {
519+ factory _KeyParseResult (_KeyParseResultType type, String key,
520+ {@required SourceSpan span}) {
496521 if (key == '.' ) {
497- return _KeyParseResult ._(type, [key]);
522+ return _KeyParseResult ._(type, [key], span : span );
498523 } else {
499- return _KeyParseResult ._(type, key.split ('.' ));
524+ return _KeyParseResult ._(type, key.split ('.' ), span : span );
500525 }
501526 }
502527
0 commit comments