hcl: SourceRange.PartitionAround
This is a convenience wrapper around SourceRange.Overlap that also calculates the ranges in the receiver that _aren't_ overlapping with the given range. This is useful when, for example, partitioning a portion of source code to insert markers to highlight the location of an error, as we do when printing code snippets as part of diagnostic output.
This commit is contained in:
parent
1365a2cfe5
commit
368a3f81c0
29
hcl/pos.go
29
hcl/pos.go
@ -231,3 +231,32 @@ func (r Range) Overlap(other Range) Range {
|
||||
End: end,
|
||||
}
|
||||
}
|
||||
|
||||
// PartitionAround finds the portion of the given range that overlaps with
|
||||
// the reciever and returns three ranges: the portion of the reciever that
|
||||
// precedes the overlap, the overlap itself, and then the portion of the
|
||||
// reciever that comes after the overlap.
|
||||
//
|
||||
// If the two ranges do not overlap then all three returned ranges are empty.
|
||||
//
|
||||
// If the given range aligns with or extends beyond either extent of the
|
||||
// reciever then the corresponding outer range will be empty.
|
||||
func (r Range) PartitionAround(other Range) (before, overlap, after Range) {
|
||||
overlap = r.Overlap(other)
|
||||
if overlap.Empty() {
|
||||
return overlap, overlap, overlap
|
||||
}
|
||||
|
||||
before = Range{
|
||||
Filename: r.Filename,
|
||||
Start: r.Start,
|
||||
End: overlap.Start,
|
||||
}
|
||||
after = Range{
|
||||
Filename: r.Filename,
|
||||
Start: overlap.End,
|
||||
End: r.End,
|
||||
}
|
||||
|
||||
return before, overlap, after
|
||||
}
|
||||
|
132
hcl/pos_test.go
132
hcl/pos_test.go
@ -307,6 +307,138 @@ func TestPosOverlap(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRangePartitionAround(t *testing.T) {
|
||||
tests := []struct {
|
||||
Outer Range
|
||||
Inner Range
|
||||
WantBefore Range
|
||||
WantOverlap Range
|
||||
WantAfter Range
|
||||
}{
|
||||
{
|
||||
Range{ // ##
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
Range{ // ####
|
||||
Start: Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
Range{ // (empty)
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
},
|
||||
Range{ // ##
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
Range{ // (empty)
|
||||
Start: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Range{ // ####
|
||||
Start: Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
Range{ // ####
|
||||
Start: Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
Range{ // #
|
||||
Start: Pos{Byte: 0, Line: 1, Column: 1},
|
||||
End: Pos{Byte: 1, Line: 1, Column: 2},
|
||||
},
|
||||
Range{ // ###
|
||||
Start: Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
Range{ // (empty)
|
||||
Start: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
},
|
||||
{
|
||||
Range{ // ####
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
Range{ // ####
|
||||
Start: Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
Range{ // (empty)
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
},
|
||||
Range{ // ###
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
Range{ // #
|
||||
Start: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
},
|
||||
{
|
||||
Range{ // ####
|
||||
Start: Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
Range{ // ##
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
Range{ // #
|
||||
Start: Pos{Byte: 1, Line: 1, Column: 2},
|
||||
End: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
},
|
||||
Range{ // ##
|
||||
Start: Pos{Byte: 2, Line: 1, Column: 3},
|
||||
End: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
},
|
||||
Range{ // #
|
||||
Start: Pos{Byte: 4, Line: 1, Column: 5},
|
||||
End: Pos{Byte: 5, Line: 1, Column: 6},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(fmt.Sprintf("%s around %s", test.Outer, test.Inner), func(t *testing.T) {
|
||||
gotBefore, gotOverlap, gotAfter := test.Outer.PartitionAround(test.Inner)
|
||||
if !reflect.DeepEqual(gotBefore, test.WantBefore) {
|
||||
t.Errorf(
|
||||
"wrong before\nA : %-10s %s\nB : %-10s %s\ngot : %-10s %s\nwant: %-10s %s",
|
||||
visRangeOffsets(test.Outer), test.Outer,
|
||||
visRangeOffsets(test.Inner), test.Inner,
|
||||
visRangeOffsets(gotBefore), gotBefore,
|
||||
visRangeOffsets(test.WantBefore), test.WantBefore,
|
||||
)
|
||||
}
|
||||
if !reflect.DeepEqual(gotOverlap, test.WantOverlap) {
|
||||
t.Errorf(
|
||||
"wrong overlap\nA : %-10s %s\nB : %-10s %s\ngot : %-10s %s\nwant: %-10s %s",
|
||||
visRangeOffsets(test.Outer), test.Outer,
|
||||
visRangeOffsets(test.Inner), test.Inner,
|
||||
visRangeOffsets(gotOverlap), gotOverlap,
|
||||
visRangeOffsets(test.WantOverlap), test.WantOverlap,
|
||||
)
|
||||
}
|
||||
if !reflect.DeepEqual(gotAfter, test.WantAfter) {
|
||||
t.Errorf(
|
||||
"wrong after\nA : %-10s %s\nB : %-10s %s\ngot : %-10s %s\nwant: %-10s %s",
|
||||
visRangeOffsets(test.Outer), test.Outer,
|
||||
visRangeOffsets(test.Inner), test.Inner,
|
||||
visRangeOffsets(gotAfter), gotAfter,
|
||||
visRangeOffsets(test.WantAfter), test.WantAfter,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// visRangeOffsets is a helper that produces a visual representation of the
|
||||
// start and end byte offsets of the given range, which can then be stacked
|
||||
// with the same for other ranges to more easily see how the ranges relate
|
||||
|
Loading…
x
Reference in New Issue
Block a user