dk_runner/steps/semantic/
context.rs1use std::path::Path;
2use std::sync::Arc;
3
4use anyhow::Result;
5use uuid::Uuid;
6
7use dk_core::types::{CallEdge, Symbol};
8use dk_engine::repo::Engine;
9
10use super::checks::{ChangedFile, CheckContext};
11
12pub async fn build_check_context(
23 engine: &Arc<Engine>,
24 repo_id: Uuid,
25 changeset_files: &[String],
26 work_dir: &Path,
27) -> Result<CheckContext> {
28 let mut before_symbols: Vec<Symbol> = Vec::new();
29 let mut after_symbols: Vec<Symbol> = Vec::new();
30 let mut before_call_graph: Vec<CallEdge> = Vec::new();
31 let mut changed_files: Vec<ChangedFile> = Vec::new();
32
33 for file_path in changeset_files {
34 let file_symbols = engine
36 .symbol_store()
37 .find_by_file(repo_id, file_path)
38 .await
39 .unwrap_or_default();
40
41 for sym in &file_symbols {
43 let callee_edges = engine
44 .call_graph_store()
45 .find_callees(sym.id)
46 .await
47 .unwrap_or_default();
48 before_call_graph.extend(callee_edges);
49
50 let caller_edges = engine
51 .call_graph_store()
52 .find_callers(sym.id)
53 .await
54 .unwrap_or_default();
55 before_call_graph.extend(caller_edges);
56 }
57
58 before_symbols.extend(file_symbols);
59
60 let abs_path = work_dir.join(file_path);
62 let rel_path = Path::new(file_path);
63
64 if abs_path.exists() {
65 let bytes = tokio::fs::read(&abs_path).await?;
66 let content = String::from_utf8_lossy(&bytes).to_string();
67
68 if engine.parser().supports_file(rel_path) {
70 match engine.parser().parse_file(rel_path, &bytes) {
71 Ok(analysis) => {
72 after_symbols.extend(analysis.symbols);
73 }
74 Err(e) => {
75 tracing::warn!("Failed to parse {}: {e}", file_path);
76 }
77 }
78 }
79
80 changed_files.push(ChangedFile {
81 path: file_path.clone(),
82 content: Some(content),
83 });
84 } else {
85 changed_files.push(ChangedFile {
87 path: file_path.clone(),
88 content: None,
89 });
90 }
91 }
92
93 let before_deps = engine
95 .dep_store()
96 .find_by_repo(repo_id)
97 .await
98 .unwrap_or_default();
99
100 let after_deps = before_deps.clone();
103
104 let after_call_graph = Vec::new();
108
109 Ok(CheckContext {
110 before_symbols,
111 after_symbols,
112 before_call_graph,
113 after_call_graph,
114 before_deps,
115 after_deps,
116 changed_files,
117 })
118}