Skip to content

Commit eda47ad

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 b1ce9ec commit eda47ad

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
@@ -1192,6 +1192,7 @@ fn resolve_base_entries<'a>(
11921192
let mut no_range_count = 0usize;
11931193
let mut first_no_range_offset: Option<u32> = None;
11941194
let mut all_no_range_same_name = true;
1195+
let mut all_no_range_have_line_mapping = true;
11951196
for member in base_entries {
11961197
if member.has_minified_range() {
11971198
if member.original_endline != u32::MAX
@@ -1201,6 +1202,9 @@ fn resolve_base_entries<'a>(
12011202
}
12021203
} else {
12031204
no_range_count += 1;
1205+
if !member.has_line_mapping() {
1206+
all_no_range_have_line_mapping = false;
1207+
}
12041208
match first_no_range_offset {
12051209
None => first_no_range_offset = Some(member.original_name_offset),
12061210
Some(first) if member.original_name_offset != first => {
@@ -1213,6 +1217,7 @@ fn resolve_base_entries<'a>(
12131217

12141218
let mut frames = Vec::new();
12151219
let mut no_range_emitted = false;
1220+
let no_range_start = 0usize;
12161221
for member in base_entries {
12171222
if member.has_minified_range() {
12181223
let line = if any_zero_zero_has_range {
@@ -1249,6 +1254,12 @@ fn resolve_base_entries<'a>(
12491254
}
12501255
}
12511256

1257+
// Sort no-range frames by original method name when all have line mappings;
1258+
// bare method entries preserve original mapping file order.
1259+
if !all_no_range_same_name && all_no_range_have_line_mapping {
1260+
frames[no_range_start..].sort_by(|a, b| a.method.cmp(b.method));
1261+
}
1262+
12521263
frames
12531264
}
12541265

src/mapper.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ fn resolve_base_entries<'s>(
350350
let mut no_range_count = 0usize;
351351
let mut first_no_range_name: Option<&str> = None;
352352
let mut all_no_range_same_name = true;
353+
let mut all_no_range_have_line_mapping = true;
353354
for member in base_entries {
354355
if member.has_minified_range {
355356
if member
@@ -360,6 +361,9 @@ fn resolve_base_entries<'s>(
360361
}
361362
} else {
362363
no_range_count += 1;
364+
if !member.has_line_mapping {
365+
all_no_range_have_line_mapping = false;
366+
}
363367
match first_no_range_name {
364368
None => first_no_range_name = Some(member.original),
365369
Some(first) if member.original != first => all_no_range_same_name = false,
@@ -369,6 +373,7 @@ fn resolve_base_entries<'s>(
369373
}
370374

371375
let mut no_range_emitted = false;
376+
let no_range_start = collected.frames.len();
372377
for member in base_entries {
373378
if member.has_minified_range {
374379
let line = if any_zero_zero_has_range {
@@ -406,6 +411,12 @@ fn resolve_base_entries<'s>(
406411
collected.rewrite_rules.extend(member.rewrite_rules.iter());
407412
}
408413
}
414+
415+
// Sort no-range frames by original method name when all have line mappings;
416+
// bare method entries preserve original mapping file order.
417+
if !all_no_range_same_name && all_no_range_have_line_mapping {
418+
collected.frames[no_range_start..].sort_by_key(|f| f.method);
419+
}
409420
}
410421

411422
/// A Proguard Remapper.

0 commit comments

Comments
 (0)