Skip to content

Commit e694bdf

Browse files
romtsnclaude
andcommitted
feat(r8): Sort ambiguous no-range entries alphabetically by method name
When multiple no-range entries with different original method names all have line mappings, sort them alphabetically. Bare method entries (no line mapping) preserve original mapping file order. Fixes test_single_line_no_line_number_stacktrace — all 10 R8 line number handling tests now pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9db871a commit e694bdf

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

src/cache/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,7 @@ fn resolve_base_entries<'a>(
11971197
let mut no_range_count = 0usize;
11981198
let mut first_no_range_offset: Option<u32> = None;
11991199
let mut all_no_range_same_name = true;
1200+
let mut all_no_range_have_line_mapping = true;
12001201
for member in base_entries {
12011202
if member.startline().is_some() {
12021203
if member.original_endline != u32::MAX
@@ -1206,6 +1207,9 @@ fn resolve_base_entries<'a>(
12061207
}
12071208
} else {
12081209
no_range_count += 1;
1210+
if member.original_startline().is_none() {
1211+
all_no_range_have_line_mapping = false;
1212+
}
12091213
match first_no_range_offset {
12101214
None => first_no_range_offset = Some(member.original_name_offset),
12111215
Some(first) if member.original_name_offset != first => {
@@ -1218,6 +1222,7 @@ fn resolve_base_entries<'a>(
12181222

12191223
let mut frames = Vec::new();
12201224
let mut no_range_emitted = false;
1225+
let no_range_start = 0usize;
12211226
for member in base_entries {
12221227
if member.startline().is_some() {
12231228
let line = if any_zero_zero_has_range {
@@ -1254,6 +1259,12 @@ fn resolve_base_entries<'a>(
12541259
}
12551260
}
12561261

1262+
// Sort no-range frames by original method name when all have line mappings;
1263+
// bare method entries preserve original mapping file order.
1264+
if !all_no_range_same_name && all_no_range_have_line_mapping {
1265+
frames[no_range_start..].sort_by(|a, b| a.method.cmp(b.method));
1266+
}
1267+
12571268
frames
12581269
}
12591270

src/mapper.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ fn resolve_base_entries<'s>(
348348
let mut no_range_count = 0usize;
349349
let mut first_no_range_name: Option<&str> = None;
350350
let mut all_no_range_same_name = true;
351+
let mut all_no_range_have_line_mapping = true;
351352
for member in base_entries {
352353
if member.startline.is_some() {
353354
if member.original_endline.is_some()
@@ -357,6 +358,9 @@ fn resolve_base_entries<'s>(
357358
}
358359
} else {
359360
no_range_count += 1;
361+
if member.original_startline.is_none() {
362+
all_no_range_have_line_mapping = false;
363+
}
360364
match first_no_range_name {
361365
None => first_no_range_name = Some(member.original),
362366
Some(first) if member.original != first => all_no_range_same_name = false,
@@ -366,6 +370,7 @@ fn resolve_base_entries<'s>(
366370
}
367371

368372
let mut no_range_emitted = false;
373+
let no_range_start = collected.frames.len();
369374
for member in base_entries {
370375
if member.startline.is_some() {
371376
let line = if any_zero_zero_has_range {
@@ -403,6 +408,12 @@ fn resolve_base_entries<'s>(
403408
collected.rewrite_rules.extend(member.rewrite_rules.iter());
404409
}
405410
}
411+
412+
// Sort no-range frames by original method name when all have line mappings;
413+
// bare method entries preserve original mapping file order.
414+
if !all_no_range_same_name && all_no_range_have_line_mapping {
415+
collected.frames[no_range_start..].sort_by_key(|f| f.method);
416+
}
406417
}
407418

408419
/// A Proguard Remapper.

0 commit comments

Comments
 (0)