From a8692c02c38bb35ecf67d22525d35785471391ad Mon Sep 17 00:00:00 2001 From: "heesk0223@gmail.com" Date: Wed, 17 Jun 2026 14:14:52 +0900 Subject: [PATCH] feat(core): add symbol note query APIs --- .../frilvault-core/src/note/note_service.rs | 27 +++++++ .../src/tests/note_service_test.rs | 75 +++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/crates/frilvault-core/src/note/note_service.rs b/crates/frilvault-core/src/note/note_service.rs index d5e0239..f8fc60b 100644 --- a/crates/frilvault-core/src/note/note_service.rs +++ b/crates/frilvault-core/src/note/note_service.rs @@ -179,4 +179,31 @@ impl NoteService { }) .collect()) } + + pub fn list_symbol_notes( + &mut self, + source_file: impl AsRef, + ) -> FrilVaultResult> { + Ok(self + .list_notes(source_file)? + .into_iter() + .filter(|view| matches!(view.note.anchor, NoteAnchor::Symbol(_))) + .collect()) + } + + pub fn find_symbol_note( + &mut self, + source_file: impl AsRef, + symbol: &str, + ) -> FrilVaultResult> { + let symbol = symbol.to_lowercase(); + + Ok(self + .list_symbol_notes(source_file)? + .into_iter() + .find(|view| match &view.note.anchor { + NoteAnchor::Symbol(anchor) => anchor.name.to_lowercase() == symbol, + _ => false, + })) + } } diff --git a/crates/frilvault-core/src/tests/note_service_test.rs b/crates/frilvault-core/src/tests/note_service_test.rs index 2f543c8..baa7f1c 100644 --- a/crates/frilvault-core/src/tests/note_service_test.rs +++ b/crates/frilvault-core/src/tests/note_service_test.rs @@ -376,3 +376,78 @@ fn search_by_symbol_returns_empty_when_not_found() { fs::remove_dir_all(workspace_root).unwrap(); } + +#[test] +fn list_symbol_notes_returns_only_symbol_notes() { + let workspace_root = + std::env::temp_dir().join(format!("frilvault-test-{}", uuid::Uuid::new_v4())); + + fs::create_dir_all(&workspace_root).unwrap(); + + let mut service = create_test_note_service(&workspace_root); + + service + .add_note(AddNoteInput { + source_file: "src/main.rs".into(), + anchor: NoteAnchor::Line(LineAnchor { line: 1, column: 1 }), + content: "line".to_string(), + }) + .unwrap(); + + service + .add_note(AddNoteInput { + source_file: "src/main.rs".into(), + anchor: NoteAnchor::Symbol(SymbolAnchor { + name: "main".to_string(), + kind: SymbolKind::Function, + signature: None, + line_hint: None, + }), + content: "symbol".to_string(), + }) + .unwrap(); + + let results = service.list_symbol_notes("src/main.rs").unwrap(); + + assert_eq!(results.len(), 1); + + match &results[0].note.anchor { + NoteAnchor::Symbol(anchor) => { + assert_eq!(anchor.name, "main"); + } + _ => panic!("expected symbol note"), + } + + fs::remove_dir_all(workspace_root).unwrap(); +} + +#[test] +fn find_symbol_note_returns_matching_symbol() { + let workspace_root = + std::env::temp_dir().join(format!("frilvault-test-{}", uuid::Uuid::new_v4())); + + fs::create_dir_all(&workspace_root).unwrap(); + + let mut service = create_test_note_service(&workspace_root); + + service + .add_note(AddNoteInput { + source_file: "src/main.rs".into(), + anchor: NoteAnchor::Symbol(SymbolAnchor { + name: "Parser".to_string(), + kind: SymbolKind::Struct, + signature: None, + line_hint: None, + }), + content: "parser note".to_string(), + }) + .unwrap(); + + let result = service.find_symbol_note("src/main.rs", "Parser").unwrap(); + + assert!(result.is_some()); + + assert_eq!(result.unwrap().note.content, "parser note"); + + fs::remove_dir_all(workspace_root).unwrap(); +}