@@ -406,7 +406,10 @@ impl CacheDir {
406406 }
407407
408408 /// Read a symbol's raw content from the consolidated file, falling back to individual shards
409- pub fn read_symbol_raw ( & self , symbol_hash : & str ) -> std:: result:: Result < String , crate :: error:: McpDiffError > {
409+ pub fn read_symbol_raw (
410+ & self ,
411+ symbol_hash : & str ,
412+ ) -> std:: result:: Result < String , crate :: error:: McpDiffError > {
410413 // Try consolidated file first
411414 let idx_path = self . symbols_idx_path ( ) ;
412415 if idx_path. exists ( ) {
@@ -418,8 +421,10 @@ impl CacheDir {
418421 // Fall back to individual shard files
419422 let path = self . symbol_path ( symbol_hash) ;
420423 if path. exists ( ) {
421- return std:: fs:: read_to_string ( & path) . map_err ( |e| crate :: error:: McpDiffError :: GitError {
422- message : format ! ( "Failed to read symbol file: {}" , e) ,
424+ return std:: fs:: read_to_string ( & path) . map_err ( |e| {
425+ crate :: error:: McpDiffError :: GitError {
426+ message : format ! ( "Failed to read symbol file: {}" , e) ,
427+ }
423428 } ) ;
424429 }
425430
@@ -430,40 +435,49 @@ impl CacheDir {
430435
431436 /// Load the symbols.idx into a HashMap (last entry per hash wins, deduplicating stale entries).
432437 /// Cached via OnceCell so the index is only parsed once per CacheDir lifetime.
433- fn load_symbol_dat_index ( & self ) -> std:: result:: Result < & std:: collections:: HashMap < String , ( u64 , usize ) > , crate :: error:: McpDiffError > {
434- self . symbol_dat_index . get_or_try_init ( || {
435- use std:: io:: BufRead ;
436-
437- let idx_path = self . symbols_idx_path ( ) ;
438- let idx_file = std:: fs:: File :: open ( & idx_path) . map_err ( |e| crate :: error:: McpDiffError :: GitError {
439- message : format ! ( "Failed to open symbols.idx: {}" , e) ,
440- } ) ?;
438+ fn load_symbol_dat_index (
439+ & self ,
440+ ) -> std:: result:: Result <
441+ & std:: collections:: HashMap < String , ( u64 , usize ) > ,
442+ crate :: error:: McpDiffError ,
443+ > {
444+ self . symbol_dat_index
445+ . get_or_try_init ( || {
446+ use std:: io:: BufRead ;
447+
448+ let idx_path = self . symbols_idx_path ( ) ;
449+ let idx_file = std:: fs:: File :: open ( & idx_path) . map_err ( |e| {
450+ crate :: error:: McpDiffError :: GitError {
451+ message : format ! ( "Failed to open symbols.idx: {}" , e) ,
452+ }
453+ } ) ?;
441454
442- let reader = std:: io:: BufReader :: new ( idx_file) ;
443- let mut map = std:: collections:: HashMap :: new ( ) ;
455+ let reader = std:: io:: BufReader :: new ( idx_file) ;
456+ let mut map = std:: collections:: HashMap :: new ( ) ;
444457
445- for line in reader. lines ( ) {
446- let line = line. map_err ( |e| crate :: error:: McpDiffError :: GitError {
447- message : format ! ( "Failed to read index line: {}" , e) ,
448- } ) ?;
449- let trimmed = line. trim ( ) ;
450- if trimmed. is_empty ( ) {
451- continue ;
452- }
453- if let Ok ( entry) = serde_json:: from_str :: < serde_json:: Value > ( trimmed) {
454- if let ( Some ( h) , Some ( o) , Some ( l) ) = (
455- entry. get ( "h" ) . and_then ( |v| v. as_str ( ) ) ,
456- entry. get ( "o" ) . and_then ( |v| v. as_u64 ( ) ) ,
457- entry. get ( "l" ) . and_then ( |v| v. as_u64 ( ) ) ,
458- ) {
459- // Last entry wins — deduplicates stale entries from incremental appends
460- map. insert ( h. to_string ( ) , ( o, l as usize ) ) ;
458+ for line in reader. lines ( ) {
459+ let line = line. map_err ( |e| crate :: error:: McpDiffError :: GitError {
460+ message : format ! ( "Failed to read index line: {}" , e) ,
461+ } ) ?;
462+ let trimmed = line. trim ( ) ;
463+ if trimmed. is_empty ( ) {
464+ continue ;
465+ }
466+ if let Ok ( entry) = serde_json:: from_str :: < serde_json:: Value > ( trimmed) {
467+ if let ( Some ( h) , Some ( o) , Some ( l) ) = (
468+ entry. get ( "h" ) . and_then ( |v| v. as_str ( ) ) ,
469+ entry. get ( "o" ) . and_then ( |v| v. as_u64 ( ) ) ,
470+ entry. get ( "l" ) . and_then ( |v| v. as_u64 ( ) ) ,
471+ ) {
472+ // Last entry wins — deduplicates stale entries from incremental appends
473+ map. insert ( h. to_string ( ) , ( o, l as usize ) ) ;
474+ }
461475 }
462476 }
463- }
464477
465- Ok ( map)
466- } ) . map_err ( |e : crate :: error:: McpDiffError | e)
478+ Ok ( map)
479+ } )
480+ . map_err ( |e : crate :: error:: McpDiffError | e)
467481 }
468482
469483 /// Invalidate the cached symbol dat index (call after writing new entries)
@@ -473,35 +487,48 @@ impl CacheDir {
473487
474488 /// Read a symbol from the consolidated .dat file using the cached HashMap index.
475489 /// O(1) lookup per read instead of O(n) linear scan.
476- fn read_symbol_from_dat ( & self , symbol_hash : & str ) -> std:: result:: Result < String , crate :: error:: McpDiffError > {
490+ fn read_symbol_from_dat (
491+ & self ,
492+ symbol_hash : & str ,
493+ ) -> std:: result:: Result < String , crate :: error:: McpDiffError > {
477494 use std:: io:: { Read , Seek , SeekFrom } ;
478495
479496 let index = self . load_symbol_dat_index ( ) ?;
480497
481- let & ( offset, len) = index. get ( symbol_hash) . ok_or_else ( || {
482- crate :: error:: McpDiffError :: FileNotFound {
483- path : format ! ( "symbol:{} (not in index)" , symbol_hash) ,
484- }
485- } ) ?;
498+ let & ( offset, len) =
499+ index
500+ . get ( symbol_hash)
501+ . ok_or_else ( || crate :: error:: McpDiffError :: FileNotFound {
502+ path : format ! ( "symbol:{} (not in index)" , symbol_hash) ,
503+ } ) ?;
486504
487505 let mut dat_file = std:: fs:: File :: open ( self . symbols_dat_path ( ) ) . map_err ( |e| {
488- crate :: error:: McpDiffError :: GitError { message : format ! ( "Failed to open symbols.dat: {}" , e) }
506+ crate :: error:: McpDiffError :: GitError {
507+ message : format ! ( "Failed to open symbols.dat: {}" , e) ,
508+ }
489509 } ) ?;
490510 dat_file. seek ( SeekFrom :: Start ( offset) ) . map_err ( |e| {
491- crate :: error:: McpDiffError :: GitError { message : format ! ( "Failed to seek in symbols.dat: {}" , e) }
511+ crate :: error:: McpDiffError :: GitError {
512+ message : format ! ( "Failed to seek in symbols.dat: {}" , e) ,
513+ }
492514 } ) ?;
493515 let mut buf = vec ! [ 0u8 ; len] ;
494- dat_file. read_exact ( & mut buf) . map_err ( |e| {
495- crate :: error:: McpDiffError :: GitError { message : format ! ( "Failed to read from symbols.dat: {}" , e) }
496- } ) ?;
516+ dat_file
517+ . read_exact ( & mut buf)
518+ . map_err ( |e| crate :: error:: McpDiffError :: GitError {
519+ message : format ! ( "Failed to read from symbols.dat: {}" , e) ,
520+ } ) ?;
497521
498- String :: from_utf8 ( buf) . map_err ( |e| {
499- crate :: error :: McpDiffError :: GitError { message : format ! ( "Invalid UTF-8 in symbol: {}" , e) }
522+ String :: from_utf8 ( buf) . map_err ( |e| crate :: error :: McpDiffError :: GitError {
523+ message : format ! ( "Invalid UTF-8 in symbol: {}" , e) ,
500524 } )
501525 }
502526
503527 /// Read a symbol and parse it as CachedContent, with fallback to individual shards
504- pub fn read_symbol_cached ( & self , symbol_hash : & str ) -> crate :: error:: Result < crate :: commands:: toon_parser:: CachedContent > {
528+ pub fn read_symbol_cached (
529+ & self ,
530+ symbol_hash : & str ,
531+ ) -> crate :: error:: Result < crate :: commands:: toon_parser:: CachedContent > {
505532 let raw = self . read_symbol_raw ( symbol_hash) ?;
506533 let is_json = raw. trim_start ( ) . starts_with ( '{' ) ;
507534 let json = if is_json {
@@ -1012,6 +1039,7 @@ impl CacheDir {
10121039 /// Check if symbol index exists
10131040 pub fn has_symbol_index ( & self ) -> bool {
10141041 self . symbol_index_path ( ) . exists ( )
1042+ || self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) . exists ( )
10151043 }
10161044
10171045 /// Path to the function signature index file (JSONL format)
@@ -1072,10 +1100,10 @@ impl CacheDir {
10721100 file_path : & str ,
10731101 new_entries : Vec < SymbolIndexEntry > ,
10741102 ) -> Result < ( ) > {
1075- use std:: io:: { BufRead , Write } ;
10761103 use flate2:: read:: GzDecoder ;
10771104 use flate2:: write:: GzEncoder ;
10781105 use flate2:: Compression ;
1106+ use std:: io:: { BufRead , Write } ;
10791107
10801108 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
10811109 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -1192,8 +1220,8 @@ impl CacheDir {
11921220 risk_filter : Option < & str > ,
11931221 limit : usize ,
11941222 ) -> Result < Vec < SymbolIndexEntry > > {
1195- use std:: io:: BufRead ;
11961223 use flate2:: read:: GzDecoder ;
1224+ use std:: io:: BufRead ;
11971225
11981226 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
11991227 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -1279,8 +1307,8 @@ impl CacheDir {
12791307 risk_filter : Option < & str > ,
12801308 limit : usize ,
12811309 ) -> Result < Vec < SymbolIndexEntry > > {
1282- use std:: io:: BufRead ;
12831310 use flate2:: read:: GzDecoder ;
1311+ use std:: io:: BufRead ;
12841312
12851313 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
12861314 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -1344,8 +1372,8 @@ impl CacheDir {
13441372 /// Returns all entries from the symbol index without filtering.
13451373 /// Use this for batch analysis operations.
13461374 pub fn load_all_symbol_entries ( & self ) -> Result < Vec < SymbolIndexEntry > > {
1347- use std:: io:: BufRead ;
13481375 use flate2:: read:: GzDecoder ;
1376+ use std:: io:: BufRead ;
13491377
13501378 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
13511379 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -1392,8 +1420,8 @@ impl CacheDir {
13921420 where
13931421 F : Fn ( & SymbolIndexEntry ) -> bool ,
13941422 {
1395- use std:: io:: BufRead ;
13961423 use flate2:: read:: GzDecoder ;
1424+ use std:: io:: BufRead ;
13971425
13981426 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
13991427 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -1439,8 +1467,8 @@ impl CacheDir {
14391467 where
14401468 F : Fn ( & SymbolIndexEntry ) -> bool ,
14411469 {
1442- use std:: io:: BufRead ;
14431470 use flate2:: read:: GzDecoder ;
1471+ use std:: io:: BufRead ;
14441472
14451473 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
14461474 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -1481,9 +1509,11 @@ impl CacheDir {
14811509
14821510 /// Build a HashMap from symbol hash to (name, risk) by streaming the index.
14831511 /// Used for call graph resolution without loading the full index.
1484- pub fn build_symbol_name_map ( & self ) -> Result < std:: collections:: HashMap < String , ( String , String ) > > {
1485- use std:: io:: BufRead ;
1512+ pub fn build_symbol_name_map (
1513+ & self ,
1514+ ) -> Result < std:: collections:: HashMap < String , ( String , String ) > > {
14861515 use flate2:: read:: GzDecoder ;
1516+ use std:: io:: BufRead ;
14871517
14881518 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
14891519 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -1512,7 +1542,10 @@ impl CacheDir {
15121542 Err ( _) => continue ,
15131543 } ;
15141544
1515- map. insert ( entry. hash . clone ( ) , ( entry. symbol . clone ( ) , entry. risk . clone ( ) ) ) ;
1545+ map. insert (
1546+ entry. hash . clone ( ) ,
1547+ ( entry. symbol . clone ( ) , entry. risk . clone ( ) ) ,
1548+ ) ;
15161549 }
15171550
15181551 Ok ( map)
@@ -2165,8 +2198,8 @@ impl CacheDir {
21652198
21662199 // Get unique files from symbol index (streaming — only collect file paths, not full entries)
21672200 let unique_files: HashSet < String > = {
2168- use std:: io:: BufRead ;
21692201 use flate2:: read:: GzDecoder ;
2202+ use std:: io:: BufRead ;
21702203
21712204 // Try .jsonl.gz first (compressed), fall back to .jsonl (uncompressed)
21722205 let compressed_path = self . symbol_index_path ( ) . with_extension ( "jsonl.gz" ) ;
@@ -2187,7 +2220,9 @@ impl CacheDir {
21872220 if let Some ( reader) = reader {
21882221 for line in reader. lines ( ) {
21892222 let line = line?;
2190- if line. trim ( ) . is_empty ( ) { continue ; }
2223+ if line. trim ( ) . is_empty ( ) {
2224+ continue ;
2225+ }
21912226 // Quick JSON extraction of just the "f" field
21922227 if let Ok ( entry) = serde_json:: from_str :: < SymbolIndexEntry > ( & line) {
21932228 files. insert ( entry. file ) ;
0 commit comments