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