@@ -44,11 +44,14 @@ final class InterpolationMap {
4444
4545 /// Maps [error] 's span in the string generated from this interpolation to its
4646 /// original source.
47+ ///
48+ /// Returns [error] if its span is null, or if it's already been mapped.
4749 FormatException mapException (SourceSpanFormatException error) {
4850 var target = error.span;
4951 if (target == null ) return error;
5052
5153 if (_interpolation.contents.isEmpty) {
54+ if (_isMapped (target)) return error;
5255 return SourceSpanFormatException (
5356 error.message,
5457 _interpolation.span,
@@ -57,6 +60,8 @@ final class InterpolationMap {
5760 }
5861
5962 var source = mapSpan (target);
63+ if (identical (source, target)) return error;
64+
6065 var startIndex = _indexInContents (target.start);
6166 var endIndex = _indexInContents (target.end);
6267
@@ -79,24 +84,36 @@ final class InterpolationMap {
7984
8085 /// Maps a span in the string generated from this interpolation to its
8186 /// original source.
82- FileSpan mapSpan (SourceSpan target) => switch ((
83- _mapLocation (target.start),
84- _mapLocation (target.end),
85- )) {
86- (FileSpan start, FileSpan end) => start.expand (end),
87- (FileSpan start, FileLocation end) => _interpolation.span.file.span (
88- _expandInterpolationSpanLeft (start.start),
89- end.offset,
90- ),
91- (FileLocation start, FileSpan end) => _interpolation.span.file.span (
92- start.offset,
93- _expandInterpolationSpanRight (end.end),
94- ),
95- (FileLocation start, FileLocation end) => _interpolation.span.file.span (
96- start.offset,
97- end.offset,
98- ),
99- _ => throw '[BUG] Unreachable' ,
87+ ///
88+ /// Returns [target] as-is if it's already been mapped.
89+ FileSpan mapSpan (SourceSpan target) {
90+ if (_isMapped (target)) return target as FileSpan ;
91+
92+ return switch ((
93+ _mapLocation (target.start),
94+ _mapLocation (target.end),
95+ )) {
96+ (FileSpan start, FileSpan end) => start.expand (end),
97+ (FileSpan start, FileLocation end) => _interpolation.span.file.span (
98+ _expandInterpolationSpanLeft (start.start),
99+ end.offset,
100+ ),
101+ (FileLocation start, FileSpan end) => _interpolation.span.file.span (
102+ start.offset,
103+ _expandInterpolationSpanRight (end.end),
104+ ),
105+ (FileLocation start, FileLocation end) => _interpolation.span.file.span (
106+ start.offset,
107+ end.offset,
108+ ),
109+ _ => throw '[BUG] Unreachable' ,
110+ };
111+ }
112+
113+ /// Returns whether [span] has already been mapped by this mapper.
114+ bool _isMapped (SourceSpan span) => switch (span) {
115+ FileSpan (: var file) => identical (file, _interpolation.span.file),
116+ _ => false ,
100117 };
101118
102119 /// Maps a location in the string generated from this interpolation to its
0 commit comments