-
Notifications
You must be signed in to change notification settings - Fork 0
🧹 Add struct and class extraction to metadata pipeline #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e19465c
6b9f0bd
f2b61ab
7cf27fb
c3b3012
7350523
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,13 @@ pub fn extract_basic_metadata<D: Doc>( | |
| } | ||
| } | ||
|
|
||
| // Extract class and struct definitions | ||
| if let Ok(class_matches) = extract_classes(&root_node, &document.language) { | ||
| for (name, info) in class_matches { | ||
| metadata.defined_symbols.insert(name, info); | ||
| } | ||
| } | ||
|
Comment on lines
+70
to
+75
|
||
|
|
||
| // Extract import statements | ||
| if let Ok(imports) = extract_imports(&root_node, &document.language) { | ||
| for (name, info) in imports { | ||
|
|
@@ -117,6 +124,62 @@ fn extract_functions<D: Doc>(root_node: &Node<D>) -> ServiceResult<RapidMap<Stri | |
| Ok(functions) | ||
| } | ||
|
|
||
| /// Extract class and struct definitions using language-specific ast-grep patterns | ||
| #[cfg(feature = "matching")] | ||
| fn extract_classes<D: Doc>( | ||
| root_node: &Node<D>, | ||
| language: &SupportLang, | ||
| ) -> ServiceResult<RapidMap<String, SymbolInfo>> { | ||
| let mut classes = thread_utilities::get_map(); | ||
|
|
||
| // Select language-specific patterns paired with their SymbolKind | ||
| let patterns: Vec<(&str, SymbolKind)> = match language { | ||
| SupportLang::Rust => vec![ | ||
| ("struct $NAME { $$$BODY }", SymbolKind::Struct), // braced struct | ||
| ("struct $NAME($$$FIELDS)", SymbolKind::Struct), // tuple struct | ||
| ("struct $NAME", SymbolKind::Struct), // unit struct | ||
| ], | ||
| SupportLang::Go => vec![ | ||
| ("type $NAME struct { $$$BODY }", SymbolKind::Struct), // Go struct | ||
| ], | ||
| SupportLang::JavaScript | SupportLang::TypeScript => vec![ | ||
| ("class $NAME { $$$BODY }", SymbolKind::Class), // JS/TS class | ||
| ("interface $NAME { $$$BODY }", SymbolKind::Interface), // TS interface | ||
| ], | ||
| SupportLang::Python => vec![ | ||
| ("class $NAME: $$$BODY", SymbolKind::Class), // simple Python class | ||
| ("class $NAME($$$PARAMS): $$$BODY", SymbolKind::Class), // Python class with bases | ||
| ], | ||
| _ => vec![ | ||
| // Generic fallbacks for C++, Java, C#, etc. | ||
| ("struct $NAME { $$$BODY }", SymbolKind::Struct), | ||
| ("class $NAME { $$$BODY }", SymbolKind::Class), | ||
| ("interface $NAME { $$$BODY }", SymbolKind::Interface), | ||
| ], | ||
| }; | ||
|
|
||
| for (pattern, kind) in &patterns { | ||
| for node_match in root_node.find_all(*pattern) { | ||
| if let Some(name_node) = node_match.get_env().get_match("NAME") { | ||
| let symbol_name = name_node.text().to_string(); | ||
| let position = name_node.start_pos(); | ||
|
|
||
| let symbol_info = SymbolInfo { | ||
| name: symbol_name.clone(), | ||
| kind: kind.clone(), | ||
| position, | ||
| scope: "global".to_string(), // Simplified for now | ||
| visibility: Visibility::Public, // Simplified for now | ||
| }; | ||
|
Comment on lines
+167
to
+173
|
||
|
|
||
| classes.insert(symbol_name, symbol_info); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Ok(classes) | ||
| } | ||
|
|
||
| /// Extract import statements using language-specific patterns | ||
| #[cfg(feature = "matching")] | ||
| fn extract_imports<D: Doc>( | ||
|
|
@@ -254,6 +317,7 @@ pub fn node_kind_to_symbol_kind(node_kind: &str) -> SymbolKind { | |
| match node_kind { | ||
| "function_declaration" | "function_definition" => SymbolKind::Function, | ||
| "class_declaration" | "class_definition" => SymbolKind::Class, | ||
| "struct_declaration" | "struct_definition" => SymbolKind::Struct, | ||
| "interface_declaration" => SymbolKind::Interface, | ||
| "variable_declaration" | "let_declaration" => SymbolKind::Variable, | ||
| "const_declaration" | "constant" => SymbolKind::Constant, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| const https = require('https'); | ||
|
|
||
| const options = { | ||
| hostname: 'api.github.com', | ||
| path: '/repos/knitli/thread/pulls/comments?pull_number=127', | ||
| method: 'GET', | ||
| headers: { | ||
| 'User-Agent': 'node.js' | ||
| } | ||
| }; | ||
|
|
||
| const req = https.request(options, (res) => { | ||
| let data = ''; | ||
| res.on('data', (chunk) => { | ||
| data += chunk; | ||
| }); | ||
| res.on('end', () => { | ||
| const comments = JSON.parse(data); | ||
| comments.forEach(c => { | ||
| console.log(`Comment ID: ${c.id}`); | ||
| console.log(`Path: ${c.path}`); | ||
| console.log(`Line: ${c.line || c.original_line}`); | ||
| console.log(`Body: ${c.body}`); | ||
| console.log('-------------------'); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| req.on('error', (e) => { | ||
| console.error(e); | ||
| }); | ||
|
|
||
| req.end(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (testing): Strengthen the test to explicitly assert that struct symbols (e.g.,
UserandRole) are present, not just any one of the union of names.Because the assertion passes if any of those names are present, the test can still succeed even if struct/class extraction is broken as long as functions are found. To verify the new behavior, add a distinct assertion that checks specifically for
User/Role(e.g., keep the existing function check and add a separateany/containsjust for struct names) so the test fails if struct extraction regresses.