daipendency_extractor_rust/
extractor.rs1use super::{api, dependencies, metadata};
2use daipendency_extractor::{
3 DependencyResolutionError, ExtractionError, Extractor, LibraryMetadata, LibraryMetadataError,
4 Namespace,
5};
6use std::path::Path;
7use tree_sitter::{Language, Parser};
8
9pub struct RustExtractor;
10
11impl Default for RustExtractor {
12 fn default() -> Self {
13 Self::new()
14 }
15}
16
17impl RustExtractor {
18 pub fn new() -> Self {
19 Self
20 }
21}
22
23impl Extractor for RustExtractor {
24 fn get_parser_language(&self) -> Language {
25 tree_sitter_rust::LANGUAGE.into()
26 }
27
28 fn get_library_metadata(&self, path: &Path) -> Result<LibraryMetadata, LibraryMetadataError> {
29 metadata::extract_metadata(path)
30 }
31
32 fn extract_public_api(
33 &self,
34 metadata: &LibraryMetadata,
35 parser: &mut Parser,
36 ) -> Result<Vec<Namespace>, ExtractionError> {
37 api::build_public_api(&metadata.entry_point, &metadata.name, parser)
38 }
39
40 fn resolve_dependency_path(
41 &self,
42 dependency_name: &str,
43 dependant_path: &Path,
44 ) -> Result<std::path::PathBuf, DependencyResolutionError> {
45 dependencies::resolve_dependency_path(dependency_name, dependant_path)
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use assertables::{assert_contains, assert_ok};
52
53 use super::*;
54 use crate::test_helpers::{create_temp_dir, setup_parser};
55
56 #[test]
57 fn get_package_metadata() {
58 let temp_dir = create_temp_dir();
59 let cargo_toml = temp_dir.path().join("Cargo.toml");
60 std::fs::write(
61 &cargo_toml,
62 r#"[package]
63name = "test_crate"
64version = "0.1.0"
65"#,
66 )
67 .unwrap();
68
69 let analyser = RustExtractor::new();
70 let metadata = analyser.get_library_metadata(temp_dir.path()).unwrap();
71
72 assert_eq!(metadata.name, "test_crate");
73 }
74
75 #[test]
76 fn extract_public_api() {
77 let temp_dir = create_temp_dir();
78 let src_dir = temp_dir.path().join("src");
79 std::fs::create_dir(&src_dir).unwrap();
80 let lib_rs = src_dir.join("lib.rs");
81 std::fs::write(
82 &lib_rs,
83 r#"
84pub fn test_function() -> i32 {
85 42
86}
87"#,
88 )
89 .unwrap();
90
91 let analyser = RustExtractor::new();
92 let metadata = LibraryMetadata {
93 name: "test_crate".to_string(),
94 version: Some("0.1.0".to_string()),
95 documentation: String::new(),
96 entry_point: lib_rs,
97 };
98 let mut parser = setup_parser();
99
100 let namespaces = analyser.extract_public_api(&metadata, &mut parser).unwrap();
101
102 assert_eq!(namespaces.len(), 1);
103 let root = namespaces.iter().find(|n| n.name == "test_crate").unwrap();
104 assert_eq!(root.symbols.len(), 1);
105 assert_eq!(root.symbols[0].name, "test_function");
106 }
107
108 #[test]
109 fn resolve_dependency_path_success() {
110 let cargo_toml = Path::new(env!("CARGO_MANIFEST_DIR"));
111 let analyser = RustExtractor::new();
112 let dependency_name = "tree-sitter";
113
114 let result = analyser.resolve_dependency_path(dependency_name, &cargo_toml);
115
116 assert_ok!(&result);
117 assert_contains!(result.unwrap().to_str().unwrap(), dependency_name);
118 }
119}