Skip to content

Commit 2f97455

Browse files
Preserve multibyte characters when wrapping long source lines (#8520)
* Preserve multibyte characters when wrapping long source lines in compiler code frames * Changelog
1 parent f5de340 commit 2f97455

5 files changed

Lines changed: 77 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#### :bug: Bug fix
2424

25+
- Preserve multibyte characters when wrapping long source lines in compiler code frames. https://github.com/rescript-lang/rescript/pull/8520
26+
2527
#### :memo: Documentation
2628

2729
#### :nail_care: Polish

compiler/ml/code_frame.ml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,23 @@ let leading_space_count str =
3737
loop 0 0
3838

3939
let break_long_line max_width line =
40+
let line_length = String.length line in
41+
let rec find_chunk_end pos remaining_width =
42+
if pos = line_length || remaining_width = 0 then pos
43+
else
44+
let char_length =
45+
String.get_utf_8_uchar line pos |> Uchar.utf_decode_length
46+
in
47+
find_chunk_end (pos + char_length) (remaining_width - 1)
48+
in
4049
let rec loop pos accum =
41-
if pos = String.length line then accum
50+
if pos = line_length then List.rev accum
4251
else
43-
let chunk_length = min max_width (String.length line - pos) in
44-
let chunk = String.sub line pos chunk_length in
45-
loop (pos + chunk_length) (chunk :: accum)
52+
let chunk_end = find_chunk_end pos max_width in
53+
let chunk = String.sub line pos (chunk_end - pos) in
54+
loop chunk_end (chunk :: accum)
4655
in
47-
loop 0 [] |> List.rev
56+
loop 0 []
4857

4958
let filter_mapi f l =
5059
let rec loop f l i accum =
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/bash
2+
3+
cd $(dirname $0)
4+
source "../utils.sh"
5+
6+
bold "Test: Compiler warnings preserve UTF-8 when wrapping source lines"
7+
8+
fixture=$(mktemp -d 2>/dev/null || mktemp -d -t rewatch-utf8-warning)
9+
trap "rm -rf '$fixture'" EXIT
10+
11+
mkdir -p "$fixture/src"
12+
13+
cat > "$fixture/package.json" <<'EOF'
14+
{
15+
"name": "rewatch-utf8-warning",
16+
"version": "0.0.1"
17+
}
18+
EOF
19+
20+
cat > "$fixture/rescript.json" <<'EOF'
21+
{
22+
"name": "rewatch-utf8-warning",
23+
"sources": { "dir": "src" },
24+
"warnings": { "number": "+27" }
25+
}
26+
EOF
27+
28+
cat > "$fixture/src/Main.res" <<'EOF'
29+
let f = (~a, ~b, ~c) => ()
30+
31+
@doc("generic placeholder text with no real source disclosed here ....—trailing text so the line is long enough to wrap onto a second row")
32+
let _g = 1
33+
EOF
34+
35+
cd "$fixture"
36+
compiler_output=$(rewatch build 2>&1)
37+
build_status=$?
38+
39+
if [ $build_status -ne 0 ]; then
40+
error "Build failed"
41+
printf "%s\n" "$compiler_output" >&2
42+
exit 1
43+
fi
44+
45+
if ! echo "$compiler_output" | grep -qF ''; then
46+
error "Wrapped warning corrupted the em dash"
47+
printf "%s\n" "$compiler_output" >&2
48+
exit 1
49+
fi
50+
51+
if echo "$compiler_output" | grep -qF ''; then
52+
error "Wrapped warning contains a Unicode replacement character"
53+
printf "%s\n" "$compiler_output" >&2
54+
exit 1
55+
fi
56+
57+
success "Wrapped warning preserves the em dash"

rewatch/tests/suite.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ fi
8181
./compile/13-no-infinite-loop-with-cycle.sh &&
8282
./compile/17-prod-flag.sh &&
8383
./compile/18-external-dep-uncurried-dot.sh &&
84+
./compile/19-utf8-warning.sh &&
8485
./compile/14-no-testrepo-changes.sh &&
8586
./compile/15-no-new-files.sh &&
8687
./compile/16-snapshots-unchanged.sh &&

tests/ounit_tests/ounit_utf8_test.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
let ( >:: ), ( >::: ) = OUnit.(( >:: ), ( >::: ))
55

66
let ( =~ ) = OUnit.assert_equal
7+
78
let suites =
89
__FILE__
910
>::: [
@@ -29,4 +30,6 @@ let suites =
2930
105;
3031
] );
3132
(__LOC__ >:: fun _ -> Ext_utf8.decode_utf8_string "" =~ []);
33+
( __LOC__ >:: fun _ ->
34+
Code_frame.break_long_line 4 "abc—def" =~ ["abc—"; "def"] );
3235
]

0 commit comments

Comments
 (0)