Skip to main content

code_moniker_workspace/
environment.rs

1use std::path::{Path, PathBuf};
2
3use code_moniker_core::core::code_graph::CodeGraph;
4use code_moniker_core::core::moniker::Moniker;
5use code_moniker_core::core::uri::{UriConfig, to_uri};
6use code_moniker_core::lang::Lang;
7use std::sync::Arc;
8
9mod project_config;
10
11pub use project_config::{PROJECT_CONFIG_FILE, TelemetryConfig, load_telemetry_config};
12
13pub type ExtractContext = crate::extract::Context;
14pub type IdentityResolver = crate::source::LocalIdentityResolver;
15pub type IndexedSourceMaterial = crate::source::CodeIndexMaterial;
16pub type ResourceCache = crate::source::LocalResourceCache;
17pub type SourceFile = crate::sources::SourceFile;
18pub type SourceFileSet = crate::sources::SourceSet;
19pub type SourceRoot = crate::sources::SourceRoot;
20
21pub fn discover_sources(
22	paths: &[PathBuf],
23	project: Option<String>,
24) -> anyhow::Result<SourceFileSet> {
25	crate::sources::discover(paths, project)
26}
27
28pub fn discover_source_files(
29	root: &Path,
30	files: &[PathBuf],
31	project: Option<String>,
32) -> anyhow::Result<SourceFileSet> {
33	crate::sources::discover_files(root, files, project)
34}
35
36pub fn discover_source_catalog(
37	root: &Path,
38	project: Option<String>,
39) -> anyhow::Result<SourceFileSet> {
40	crate::sources::discover_catalog(root, project)
41}
42
43pub fn language_for_path(path: &Path) -> anyhow::Result<Lang> {
44	Ok(crate::lang::path_to_lang(path)?)
45}
46
47pub fn load_or_extract_source(
48	path: &Path,
49	anchor: &Path,
50	lang: Lang,
51	cache_dir: Option<&Path>,
52	ctx: &ExtractContext,
53) -> anyhow::Result<(CodeGraph, Option<String>)> {
54	Ok(crate::cache::load_or_extract_result(
55		path, anchor, lang, cache_dir, ctx,
56	)?)
57}
58
59pub fn cached_index_material(
60	cache: &ResourceCache,
61	generation: crate::snapshot::ResourceGeneration,
62) -> Option<std::sync::Arc<IndexedSourceMaterial>> {
63	cache.index_material(generation)
64}
65
66pub fn cached_index_diff(
67	cache: &ResourceCache,
68	generation: crate::snapshot::ResourceGeneration,
69) -> Option<(
70	crate::snapshot::ResourceGeneration,
71	Arc<crate::code::CodeIndexGraphDiff>,
72)> {
73	cache.index_diff(generation)
74}
75
76pub fn next_resource_generation(cache: &ResourceCache) -> crate::snapshot::ResourceGeneration {
77	cache.next_generation()
78}
79
80#[cfg(test)]
81pub fn extract_source(lang: Lang, source: &str, path: &Path) -> CodeGraph {
82	crate::extract::extract(lang, source, path)
83}
84
85pub fn extract_source_with(
86	lang: Lang,
87	source: &str,
88	path: &Path,
89	ctx: &ExtractContext,
90) -> CodeGraph {
91	crate::extract::extract_with(lang, source, path, ctx)
92}
93
94pub fn symbol_records_for_graph(
95	file_idx: usize,
96	source_id: crate::snapshot::SourceId,
97	graph: &CodeGraph,
98	source: &str,
99	lang: Lang,
100	scheme: &str,
101) -> Vec<crate::snapshot::SymbolRecord> {
102	let identity = crate::source::LocalIdentityResolver::new(scheme);
103	let lines = crate::lines::LineIndex::new(source);
104	graph
105		.defs()
106		.enumerate()
107		.map(|(def_idx, def)| crate::snapshot::SymbolRecord {
108			id: identity.symbol_id(file_idx, def_idx),
109			source: source_id,
110			identity: Arc::from(identity.moniker_uri(&def.moniker)),
111			name: crate::code::last_name(&def.moniker),
112			kind: crate::code::def_kind(def),
113			visibility: std::str::from_utf8(&def.visibility)
114				.unwrap_or("")
115				.to_string(),
116			signature: String::from_utf8_lossy(&def.signature).to_string(),
117			call_name: (!def.call_name.is_empty())
118				.then(|| String::from_utf8_lossy(&def.call_name).to_string()),
119			call_arity: def.call_arity,
120			navigable: crate::code::is_navigable_def(lang, def),
121			line_range: def
122				.position
123				.map(|(start, end)| lines.line_range(start, end)),
124			parent: def
125				.parent
126				.map(|parent_idx| identity.symbol_id(file_idx, parent_idx)),
127		})
128		.collect()
129}
130
131pub fn source_root_moniker(lang: Lang, path: &Path, ctx: &ExtractContext) -> Option<Moniker> {
132	crate::extract::source_root(lang, path, ctx)
133}
134
135pub fn line_range(source: &str, start: u32, end: u32) -> (u32, u32) {
136	crate::lines::line_range(source, start, end)
137}
138
139pub fn compact_moniker(moniker: &Moniker, scheme: &str) -> String {
140	render_compact_moniker(moniker).unwrap_or_else(|| to_uri(moniker, &UriConfig { scheme }))
141}
142
143fn render_compact_moniker(moniker: &Moniker) -> Option<String> {
144	let view = moniker.as_view();
145	let mut lang: Option<String> = None;
146	let mut packages: Vec<String> = Vec::new();
147	let mut dirs: Vec<String> = Vec::new();
148	let mut modules: Vec<String> = Vec::new();
149	let mut rest: Vec<(String, String)> = Vec::new();
150	for segment in view.segments() {
151		let kind = std::str::from_utf8(segment.kind).ok()?.to_string();
152		let name = std::str::from_utf8(segment.name).ok()?.to_string();
153		match kind.as_str() {
154			"lang" => lang = Some(name),
155			"package" => packages.push(name),
156			"dir" => dirs.push(name),
157			"module" => modules.push(name),
158			_ => rest.push((kind, name)),
159		}
160	}
161	let head = lang.unwrap_or_else(|| {
162		std::str::from_utf8(view.project())
163			.unwrap_or(".")
164			.to_string()
165	});
166	if packages.is_empty() && dirs.is_empty() && modules.is_empty() && rest.is_empty() {
167		return Some(head);
168	}
169	let mut out = String::new();
170	out.push_str(&head);
171	out.push(':');
172	let mut wrote_scope = false;
173	if !packages.is_empty() {
174		out.push_str(&packages.join("."));
175		wrote_scope = true;
176	} else if !dirs.is_empty() {
177		out.push_str(&dirs.join("/"));
178		wrote_scope = true;
179	}
180	let has_module = !modules.is_empty();
181	if has_module {
182		if wrote_scope {
183			out.push('/');
184		}
185		out.push_str(&modules.join("."));
186	}
187	for (idx, (kind, name)) in rest.iter().enumerate() {
188		if idx == 0 && has_module {
189			out.push('.');
190		} else if wrote_scope || has_module || idx > 0 {
191			out.push('/');
192		}
193		out.push_str(kind);
194		out.push(':');
195		out.push_str(name);
196	}
197	Some(out)
198}