| 58 | |
| 59 | impl LeanExtractor { |
| 60 | pub fn extract_lean(file_path: &str, source: &str) -> ExtractionResult { |
| 61 | let start = Instant::now(); |
| 62 | let mut state = ExtractionState::new(file_path, source); |
| 63 | |
| 64 | let file_node = Node { |
| 65 | id: state.file_node_id.clone(), |
| 66 | kind: NodeKind::File, |
| 67 | name: file_path.to_string(), |
| 68 | qualified_name: file_path.to_string(), |
| 69 | file_path: file_path.to_string(), |
| 70 | start_line: 0, |
| 71 | attrs_start_line: 0, |
| 72 | end_line: source.lines().count().saturating_sub(1) as u32, |
| 73 | start_column: 0, |
| 74 | end_column: 0, |
| 75 | signature: None, |
| 76 | docstring: None, |
| 77 | visibility: Visibility::Pub, |
| 78 | is_async: false, |
| 79 | branches: 0, |
| 80 | loops: 0, |
| 81 | returns: 0, |
| 82 | max_nesting: 0, |
| 83 | unsafe_blocks: 0, |
| 84 | unchecked_calls: 0, |
| 85 | assertions: 0, |
| 86 | updated_at: state.timestamp, |
| 87 | parent_id: None, |
| 88 | }; |
| 89 | state.nodes.push(file_node); |
| 90 | state |
| 91 | .scope_stack |
| 92 | .push((file_path.to_string(), state.file_node_id.clone())); |
| 93 | |
| 94 | if let Ok(tree) = Self::parse(source) { |
| 95 | Self::visit(&mut state, tree.root_node()); |
| 96 | } |
| 97 | |
| 98 | ExtractionResult { |
| 99 | nodes: state.nodes, |
| 100 | edges: state.edges, |
| 101 | unresolved_refs: Vec::new(), |
| 102 | errors: Vec::new(), |
| 103 | duration_ms: start.elapsed().as_millis() as u64, |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | fn parse(source: &str) -> Result<Tree, String> { |
| 108 | let mut parser = Parser::new(); |