code_moniker_workspace/changes/
overlay.rs1use 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}