Skip to main content

code_moniker_workspace/
extract.rs

1use 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}