Skip to content

Commit b5eb062

Browse files
authored
feat(outline): Expose is_outline and prepare_frame_for_mapping (#64)
This is needed to reimplement outline support in symbolicator
1 parent baf2d05 commit b5eb062

File tree

3 files changed

+29
-90
lines changed

3 files changed

+29
-90
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cache/mod.rs

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -400,56 +400,32 @@ impl<'data> ProguardCache<'data> {
400400
})
401401
}
402402

403-
/// Determines if a frame refers to an outline method, either via the
404-
/// method-level flag or via any matching mapping entry for the frame line.
405-
fn is_outline_frame(
406-
&self,
407-
class: &str,
408-
method: &str,
409-
line: usize,
410-
parameters: Option<&str>,
411-
) -> bool {
403+
/// Determines if a frame refers to an outline method via the method-level flag.
404+
/// Outline metadata is consistent across all mapping entries for a method, so
405+
/// we only need to inspect the method metadata instead of individual lines.
406+
pub fn is_outline_frame(&self, class: &str, method: &str) -> bool {
412407
let Some(class) = self.get_class(class) else {
413408
return false;
414409
};
415410

416-
let candidates: &[raw::Member] = if let Some(params) = parameters {
417-
let Some(members) = self.get_class_members_by_params(class) else {
418-
return false;
419-
};
420-
let Some(range) = Self::find_range_by_binary_search(members, |m| {
421-
let Ok(obfuscated_name) = self.read_string(m.obfuscated_name_offset) else {
422-
return Ordering::Greater;
423-
};
424-
let p = self.read_string(m.params_offset).unwrap_or_default();
425-
(obfuscated_name, p).cmp(&(method, params))
426-
}) else {
427-
return false;
428-
};
429-
range
430-
} else {
431-
let Some(members) = self.get_class_members(class) else {
432-
return false;
433-
};
434-
let Some(range) = Self::find_range_by_binary_search(members, |m| {
435-
let Ok(obfuscated_name) = self.read_string(m.obfuscated_name_offset) else {
436-
return Ordering::Greater;
437-
};
438-
obfuscated_name.cmp(method)
439-
}) else {
440-
return false;
411+
let Some(members) = self.get_class_members(class) else {
412+
return false;
413+
};
414+
415+
let Some(candidates) = Self::find_range_by_binary_search(members, |m| {
416+
let Ok(obfuscated_name) = self.read_string(m.obfuscated_name_offset) else {
417+
return Ordering::Greater;
441418
};
442-
range
419+
obfuscated_name.cmp(method)
420+
}) else {
421+
return false;
443422
};
444423

445-
candidates.iter().any(|m| {
446-
m.is_outline()
447-
&& (m.endline == 0 || (line >= m.startline as usize && line <= m.endline as usize))
448-
})
424+
candidates.first().is_some_and(|member| member.is_outline())
449425
}
450426

451427
/// Applies any carried outline position to the frame line and returns the adjusted frame.
452-
fn prepare_frame_for_mapping<'a>(
428+
pub fn prepare_frame_for_mapping<'a>(
453429
&self,
454430
frame: &StackFrame<'a>,
455431
carried_outline_pos: &mut Option<usize>,
@@ -483,12 +459,7 @@ impl<'data> ProguardCache<'data> {
483459
None => match stacktrace::parse_frame(line) {
484460
None => writeln!(&mut stacktrace, "{line}")?,
485461
Some(frame) => {
486-
if self.is_outline_frame(
487-
frame.class,
488-
frame.method,
489-
frame.line,
490-
frame.parameters,
491-
) {
462+
if self.is_outline_frame(frame.class, frame.method) {
492463
carried_outline_pos = Some(frame.line);
493464
} else {
494465
let effective_frame =
@@ -520,12 +491,7 @@ impl<'data> ProguardCache<'data> {
520491
}
521492
},
522493
Some(frame) => {
523-
if self.is_outline_frame(
524-
frame.class,
525-
frame.method,
526-
frame.line,
527-
frame.parameters,
528-
) {
494+
if self.is_outline_frame(frame.class, frame.method) {
529495
carried_outline_pos = Some(frame.line);
530496
continue;
531497
}
@@ -549,7 +515,7 @@ impl<'data> ProguardCache<'data> {
549515
let mut carried_outline_pos: Option<usize> = None;
550516
let mut frames: Vec<StackFrame<'a>> = Vec::with_capacity(trace.frames.len());
551517
for f in trace.frames.iter() {
552-
if self.is_outline_frame(f.class, f.method, f.line, f.parameters) {
518+
if self.is_outline_frame(f.class, f.method) {
553519
carried_outline_pos = Some(f.line);
554520
continue;
555521
}

src/mapper.rs

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -359,32 +359,15 @@ impl<'s> ProguardMapper<'s> {
359359
})
360360
}
361361

362-
/// Determines if a frame refers to an outline method, either via the
363-
/// method-level flag or via any matching mapping entry for the frame line.
364-
fn is_outline_frame(
365-
&self,
366-
class: &str,
367-
method: &str,
368-
line: usize,
369-
parameters: Option<&str>,
370-
) -> bool {
362+
/// Determines if a frame refers to an outline method via the method-level flag.
363+
/// Outline metadata is consistent across all mappings for a method, so checking
364+
/// a single mapping entry is sufficient.
365+
fn is_outline_frame(&self, class: &str, method: &str) -> bool {
371366
self.classes
372367
.get(class)
373368
.and_then(|c| c.members.get(method))
374-
.map(|ms| {
375-
let mappings: &[_] = if let Some(params) = parameters {
376-
match ms.mappings_by_params.get(params) {
377-
Some(v) => &v[..],
378-
None => &[],
379-
}
380-
} else {
381-
&ms.all_mappings[..]
382-
};
383-
mappings.iter().any(|m| {
384-
m.is_outline && (m.endline == 0 || (line >= m.startline && line <= m.endline))
385-
})
386-
})
387-
.unwrap_or(false)
369+
.and_then(|ms| ms.all_mappings.first())
370+
.is_some_and(|m| m.is_outline)
388371
}
389372

390373
/// Applies any carried outline position to the frame line and returns the adjusted frame.
@@ -520,12 +503,7 @@ impl<'s> ProguardMapper<'s> {
520503
None => match stacktrace::parse_frame(line) {
521504
None => writeln!(&mut stacktrace, "{line}")?,
522505
Some(frame) => {
523-
if self.is_outline_frame(
524-
frame.class,
525-
frame.method,
526-
frame.line,
527-
frame.parameters,
528-
) {
506+
if self.is_outline_frame(frame.class, frame.method) {
529507
carried_outline_pos = Some(frame.line);
530508
} else {
531509
let effective_frame =
@@ -557,12 +535,7 @@ impl<'s> ProguardMapper<'s> {
557535
}
558536
},
559537
Some(frame) => {
560-
if self.is_outline_frame(
561-
frame.class,
562-
frame.method,
563-
frame.line,
564-
frame.parameters,
565-
) {
538+
if self.is_outline_frame(frame.class, frame.method) {
566539
carried_outline_pos = Some(frame.line);
567540
continue;
568541
}
@@ -587,7 +560,7 @@ impl<'s> ProguardMapper<'s> {
587560
let mut carried_outline_pos: Option<usize> = None;
588561
let mut frames_out = Vec::with_capacity(trace.frames.len());
589562
for f in trace.frames.iter() {
590-
if self.is_outline_frame(f.class, f.method, f.line, f.parameters) {
563+
if self.is_outline_frame(f.class, f.method) {
591564
carried_outline_pos = Some(f.line);
592565
continue;
593566
}

0 commit comments

Comments
 (0)