Skip to content

Commit 0b54306

Browse files
authored
Fix off-by-one error in annotated string concat (#51803)
A new unit test is also added for the edge-case found, and a few details of the test string adjusted to make it easier to reason about at a glance. ----- This seems to have slipped into #49586 when the `annotatedstring` function had to be refactored to no longer use `eachstyle` (which was moved into the stdlib), and escaped the unit tests for index corectness.
1 parent 0617fec commit 0b54306

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

base/strings/annotated.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ function annotatedstring(xs...)
212212
for (region, annot) in x.string.annotations
213213
start, stop = first(region), last(region)
214214
if start <= x.offset + x.ncodeunits && stop > x.offset
215-
rstart = s.io.size + max(0, start - x.offset) + 1
215+
rstart = s.io.size + max(0, start - x.offset - 1) + 1
216216
rstop = s.io.size + min(stop, x.offset + x.ncodeunits) - x.offset
217217
push!(annotations, (rstart:rstop, annot))
218218
end

test/strings/annotated.jl

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,23 @@
1313
@test str * "a" == Base.AnnotatedString("some stringa")
1414
@test str * str == Base.AnnotatedString("some stringsome string")
1515
Base.annotate!(str, 1:4, :thing => 0x01)
16-
Base.annotate!(str, 5:11, :other => 0x02)
16+
Base.annotate!(str, 6:11, :other => 0x02)
1717
Base.annotate!(str, 1:11, :all => 0x03)
18+
# :thing :other
19+
# ┌┸─┐ ┌──┸─┐
20+
# "some string"
21+
# └───┰─────┘
22+
# :all
1823
@test str[3:4] == SubString(str, 3, 4)
1924
@test Base.AnnotatedString(str[3:4]) ==
2025
Base.AnnotatedString("me", [(1:2, :thing => 0x01), (1:2, :all => 0x03)])
21-
@test str == Base.AnnotatedString("some string", [(1:4, :thing => 0x01), (1:11, :all => 0x03), (5:11, :other => 0x02)])
26+
@test Base.AnnotatedString(str[3:6]) ==
27+
Base.AnnotatedString("me s", [(1:2, :thing => 0x01), (1:4, :all => 0x03), (4:4, :other => 0x02)])
28+
@test str == Base.AnnotatedString("some string", [(1:4, :thing => 0x01), (1:11, :all => 0x03), (6:11, :other => 0x02)])
2229
@test str != Base.AnnotatedString("some string")
23-
@test str != Base.AnnotatedString("some string", [(1:1, :thing => 0x01), (5:5, :other => 0x02), (11:11, :all => 0x03)])
24-
@test str != Base.AnnotatedString("some string", [(1:4, :thing => 0x11), (1:11, :all => 0x13), (5:11, :other => 0x12)])
25-
@test str != Base.AnnotatedString("some thingg", [(1:4, :thing => 0x01), (1:11, :all => 0x03), (5:11, :other => 0x02)])
30+
@test str != Base.AnnotatedString("some string", [(1:1, :thing => 0x01), (6:6, :other => 0x02), (11:11, :all => 0x03)])
31+
@test str != Base.AnnotatedString("some string", [(1:4, :thing => 0x11), (1:11, :all => 0x13), (6:11, :other => 0x12)])
32+
@test str != Base.AnnotatedString("some thingg", [(1:4, :thing => 0x01), (1:11, :all => 0x03), (6:11, :other => 0x02)])
2633
let allstrings =
2734
['a', Base.AnnotatedChar('a'), Base.AnnotatedChar('a', [:aaa => 0x04]),
2835
"a string", Base.AnnotatedString("a string"),
@@ -62,7 +69,7 @@ end
6269
end
6370

6471
@testset "Styling preservation" begin
65-
str = Base.AnnotatedString("some string", [(1:4, :thing => 0x01), (1:11, :all => 0x03), (5:11, :other => 0x02)])
72+
str = Base.AnnotatedString("some string", [(1:4, :thing => 0x01), (1:11, :all => 0x03), (6:11, :other => 0x02)])
6673
@test match(r".e", str).match == str[3:4]
6774
@test match(r"(.e)", str).captures == [str[3:4]]
6875
let m0 = match(r"(.)e", str)
@@ -74,11 +81,11 @@ end
7481
@test lpad(str, 12) ==
7582
Base.AnnotatedString(" some string", [(2:5, :thing => 0x01),
7683
(2:12, :all => 0x03),
77-
(6:12, :other => 0x02)])
84+
(7:12, :other => 0x02)])
7885
@test rpad(str, 12) ==
7986
Base.AnnotatedString("some string ", [(1:4, :thing => 0x01),
8087
(1:11, :all => 0x03),
81-
(5:11, :other => 0x02)])
88+
(6:11, :other => 0x02)])
8289
str1 = Base.AnnotatedString("test", [(1:4, :label => 5)])
8390
str2 = Base.AnnotatedString("case", [(2:3, :label => "oomph")])
8491
@test join([str1, str1], Base.AnnotatedString(" ")) ==

0 commit comments

Comments
 (0)