@@ -148,6 +148,7 @@ impl ProguardMapping {
148148 } ;
149149 let qualified = & rest[ ..paren_start] ;
150150 let location = & rest[ paren_start..] ;
151+ let ( class_prefix, qualified) = split_container_prefix ( qualified) ;
151152
152153 // Split into class + method on last '.'
153154 let Some ( dot_pos) = qualified. rfind ( '.' ) else {
@@ -180,7 +181,7 @@ impl ProguardMapping {
180181 None => format ! ( "({source_file})" ) ,
181182 } ;
182183
183- format ! ( "{prefix}at {original_class}.{method_name}{location_str}" )
184+ format ! ( "{prefix}at {class_prefix}{ original_class}.{method_name}{location_str}" )
184185 }
185186
186187 fn retrace_exception_line ( & self , line : & str ) -> String {
@@ -200,9 +201,13 @@ impl ProguardMapping {
200201 . split_once ( ": " )
201202 . map ( |( c, m) | ( c, format ! ( ": {m}" ) ) )
202203 . unwrap_or ( ( class_and_rest, String :: new ( ) ) ) ;
204+ let ( class_prefix, obf_class) = split_container_prefix ( obf_class) ;
203205
204206 if let Some ( class) = self . classes . get ( obf_class) {
205- format ! ( "{prefix}{before_class}{}{suffix}" , class. original_name)
207+ format ! (
208+ "{prefix}{before_class}{class_prefix}{}{suffix}" ,
209+ class. original_name
210+ )
206211 } else {
207212 line. to_string ( )
208213 }
@@ -277,6 +282,14 @@ fn parse_class_line(line: &str) -> Option<(String, String)> {
277282 Some ( ( original. trim ( ) . to_string ( ) , obfuscated. trim ( ) . to_string ( ) ) )
278283}
279284
285+ fn split_container_prefix ( qualified : & str ) -> ( & str , & str ) {
286+ if let Some ( slash_pos) = qualified. rfind ( '/' ) {
287+ ( & qualified[ ..=slash_pos] , & qualified[ slash_pos + 1 ..] )
288+ } else {
289+ ( "" , qualified)
290+ }
291+ }
292+
280293/// Parse member lines (methods and fields) and add to class mapping
281294fn parse_member_line ( line : & str , class : & mut ClassMapping ) {
282295 // Try to parse as method with line numbers: "startLine:endLine:returnType method(params) -> obfuscated"
@@ -589,6 +602,28 @@ java.lang.RuntimeException: oops
589602 assert_eq ! ( output, "\t at core.file.FileIO.load(FileIO.java)" ) ;
590603 }
591604
605+ #[ test]
606+ fn retrace_stacktrace_with_container_prefix ( ) {
607+ let mapping = parse_test_mapping ( SAMPLE_MAPPING ) ;
608+ let input = "\t at tweaks-3.3.6-obfuscated.jar//a.a.a.c(SourceFile:92)" ;
609+ let output = mapping. retrace ( input) ;
610+ assert_eq ! (
611+ output,
612+ "\t at tweaks-3.3.6-obfuscated.jar//core.file.FileIO.reload(FileIO.java:92)"
613+ ) ;
614+ }
615+
616+ #[ test]
617+ fn retrace_caused_by_with_container_prefix ( ) {
618+ let mapping = parse_test_mapping ( SAMPLE_MAPPING ) ;
619+ let input = "Caused by: tweaks-3.3.6-obfuscated.jar//a.a.a: some message" ;
620+ let output = mapping. retrace ( input) ;
621+ assert_eq ! (
622+ output,
623+ "Caused by: tweaks-3.3.6-obfuscated.jar//core.file.FileIO: some message"
624+ ) ;
625+ }
626+
592627 #[ test]
593628 fn parse_many_combines_split_mapping_files ( ) {
594629 const PART_ONE : & str = r#"core.file.FileIO -> a.a.a:
0 commit comments