code_moniker_workspace/
extract.rs1use std::path::Path;
2
3use code_moniker_core::core::code_graph::CodeGraph;
4use code_moniker_core::core::moniker::{Moniker, MonikerBuilder};
5use code_moniker_core::lang::{Lang, ts};
6
7use crate::cbuild::CBuildContext;
8use crate::tsconfig::TsResolution;
9
10#[derive(Debug, Clone, Default)]
11pub struct Context {
12 pub c: CBuildContext,
13 pub ts: TsResolution,
14 pub project: Option<String>,
15}
16
17pub fn extract(lang: Lang, source: &str, path: &Path) -> CodeGraph {
18 extract_with(lang, source, path, &Context::default())
19}
20
21pub fn extract_with(lang: Lang, source: &str, path: &Path, ctx: &Context) -> CodeGraph {
22 let uri = path.to_str().unwrap_or("single-file");
23 let project = ctx.project.as_deref().map(str::as_bytes).unwrap_or(b".");
24 let anchor = anchor_moniker(project, srcset(path).map(str::as_bytes));
25 let deep = true;
26 let mut graph = match lang {
27 Lang::Ts => {
28 let presets = ts::Presets {
29 path_aliases: ctx.ts.aliases.clone(),
30 ..ts::Presets::default()
31 };
32 ts::extract(uri, source, &anchor, deep, &presets)
33 }
34 Lang::Rs => code_moniker_core::lang::rs::extract_sdk(
35 uri,
36 source,
37 &anchor,
38 deep,
39 &code_moniker_core::lang::rs::Presets::default(),
40 ),
41 Lang::Java => code_moniker_core::lang::java::extract_sdk(
42 uri,
43 source,
44 &anchor,
45 deep,
46 &code_moniker_core::lang::java::Presets::default(),
47 ),
48 Lang::Python => code_moniker_core::lang::python::extract(
49 uri,
50 source,
51 &anchor,
52 deep,
53 &code_moniker_core::lang::python::Presets::default(),
54 ),
55 Lang::Go => code_moniker_core::lang::go::extract(
56 uri,
57 source,
58 &anchor,
59 deep,
60 &code_moniker_core::lang::go::Presets::default(),
61 ),
62 Lang::C => {
63 let presets = ctx.c.extraction_presets();
64 code_moniker_core::lang::c::extract(uri, source, &anchor, deep, &presets)
65 }
66 Lang::Cs => code_moniker_core::lang::cs::extract(
67 uri,
68 source,
69 &anchor,
70 deep,
71 &code_moniker_core::lang::cs::Presets::default(),
72 ),
73 Lang::Sql => code_moniker_core::lang::sql::extract(
74 uri,
75 source,
76 &anchor,
77 deep,
78 &code_moniker_core::lang::sql::Presets::default(),
79 ),
80 };
81 graph.shrink_to_fit();
82 graph
83}
84
85fn anchor_moniker(project: &[u8], srcset: Option<&[u8]>) -> Moniker {
86 let mut b = MonikerBuilder::new();
87 b.project(project);
88 if let Some(srcset) = srcset {
89 b.segment(b"srcset", srcset);
90 }
91 b.build()
92}
93
94fn srcset(path: &Path) -> Option<&'static str> {
95 let parts: Vec<_> = path
96 .components()
97 .filter_map(|component| component.as_os_str().to_str())
98 .collect();
99 for window in parts.windows(2) {
100 match window {
101 ["src", "main"] => return Some("main"),
102 ["src", "test"] | ["src", "tests"] => return Some("test"),
103 _ => {}
104 }
105 }
106 None
107}
108
109pub fn file_uri(path: &Path) -> String {
110 let abs = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
111 format!("file://{}", abs.display())
112}