Skip to main content

code_moniker_workspace/changes/
overlay.rs

1use crate::code::CodeIndexSymbolProvider;
2use crate::snapshot::{
3	ChangeOverlay, ChangeOverlayReport, ChangeResource, CodeIndex, SourceCatalog, WorkspaceFailure,
4	WorkspaceResource, WorkspaceResult,
5};
6use crate::source::{CodeIndexMaterial, LocalResourceCache};
7
8use super::analyzer::ChangeAnalyzer;
9use super::diff::{self, ChangeFile, ChangeRoot, ChangeScan};
10
11pub trait ChangeOverlayPort {
12	fn build_change_overlay(
13		&mut self,
14		catalog: &SourceCatalog,
15		index: &CodeIndex,
16	) -> WorkspaceResult<ChangeOverlay>;
17}
18
19pub struct LocalChangeOverlay {
20	cache: LocalResourceCache,
21}
22
23impl LocalChangeOverlay {
24	pub fn new(cache: LocalResourceCache) -> Self {
25		Self { cache }
26	}
27}
28
29impl ChangeOverlayPort for LocalChangeOverlay {
30	fn build_change_overlay(
31		&mut self,
32		catalog: &SourceCatalog,
33		index: &CodeIndex,
34	) -> WorkspaceResult<ChangeOverlay> {
35		let material = self.cache.index_material(index.generation).ok_or_else(|| {
36			WorkspaceFailure::new(
37				WorkspaceResource::ChangeOverlay,
38				"code index material is unavailable",
39			)
40		})?;
41		let generation = self.cache.next_generation();
42		let change_index = diff::build_change_index(change_scan(&material));
43		let semantic = super::semantic::review::build_semantic_review(&change_scan(&material));
44		let mut overlay = ChangeOverlay::from_report(change_report(
45			generation,
46			catalog.generation,
47			index.generation,
48			change_index,
49			&material,
50		));
51		overlay.semantic = Some(std::sync::Arc::new(semantic));
52		Ok(overlay)
53	}
54}
55
56fn change_scan(material: &CodeIndexMaterial) -> ChangeScan<'_> {
57	ChangeScan {
58		roots: material
59			.source_catalog
60			.sources
61			.roots
62			.iter()
63			.map(|root| ChangeRoot {
64				label: &root.label,
65				path: &root.path,
66				ctx: &root.ctx,
67			})
68			.collect(),
69		files: material
70			.files
71			.iter()
72			.enumerate()
73			.map(|(file_idx, file)| ChangeFile {
74				file_idx,
75				source_root: file.source_root,
76				path: &file.path,
77				rel_path: &file.rel_path,
78				anchor: &file.anchor,
79				lang: file.lang,
80				graph: &file.graph,
81				source: &file.source,
82			})
83			.collect(),
84	}
85}
86
87fn change_report(
88	generation: crate::snapshot::ResourceGeneration,
89	catalog_generation: crate::snapshot::ResourceGeneration,
90	index_generation: crate::snapshot::ResourceGeneration,
91	change_index: diff::ChangeIndex,
92	material: &CodeIndexMaterial,
93) -> ChangeOverlayReport {
94	let provider = CodeIndexSymbolProvider::new(material);
95	let changes = ChangeAnalyzer::new(&provider).analyze(&change_index.entries);
96	ChangeOverlayReport {
97		generation,
98		catalog_generation,
99		index_generation,
100		scope: change_index.scope,
101		resources: change_index
102			.resources
103			.into_iter()
104			.map(|resource| ChangeResource {
105				available: resource.available(),
106				label: resource.label,
107				message: resource.message,
108			})
109			.collect(),
110		diagnostics: change_index.diagnostics,
111		changes,
112	}
113}