MCPcopy Create free account
hub / github.com/ScriptedAlchemy/tracedecay / get_code_cached

Method get_code_cached

src/context/builder.rs:108–159  ·  view source on GitHub ↗

Same as `get_code` but reads each file at most once per `cache`. Used by `extract_code_blocks` and `merge_adjacent_blocks` so a single `build_context` call doesn't re-read the same source file dozens of times — the old per-node `fs::read_to_string` was the dominant cost when many entry points lived in the same file.

(
        &self,
        node: &Node,
        cache: &mut HashMap<String, Option<String>>,
    )

Source from the content-addressed store, hash-verified

106 /// times — the old per-node `fs::read_to_string` was the dominant cost
107 /// when many entry points lived in the same file.
108 fn get_code_cached(
109 &self,
110 node: &Node,
111 cache: &mut HashMap<String, Option<String>>,
112 ) -> Option<String> {
113 debug_assert!(
114 !node.file_path.is_empty(),
115 "get_code called with empty file_path"
116 );
117 debug_assert!(!node.id.is_empty(), "get_code called with empty node id");
118 if node.start_line == 0 || node.end_line == 0 || node.start_line > node.end_line {
119 return None;
120 }
121
122 let content = if let Some(slot) = cache.get(&node.file_path) {
123 slot.clone()
124 } else {
125 let file_path = self.project_root.join(&node.file_path);
126 // Prevent path traversal: ensure the resolved path stays within
127 // the canonical project root. If the target itself is missing,
128 // allow the read attempt to fail naturally as `None`.
129 let allowed = match self.project_root.canonicalize() {
130 Ok(root) => match file_path.canonicalize() {
131 Ok(canonical) => canonical.starts_with(&root),
132 Err(_) => file_path.starts_with(&root),
133 },
134 Err(_) => false,
135 };
136 let loaded = if allowed {
137 fs::read_to_string(&file_path).ok()
138 } else {
139 None
140 };
141 cache.insert(node.file_path.clone(), loaded.clone());
142 loaded
143 };
144 let content = content?;
145
146 let lines: Vec<&str> = content.lines().collect();
147 let start = (node.start_line as usize).saturating_sub(1);
148 let end = node.end_line as usize;
149 if start >= lines.len() {
150 return None;
151 }
152 let end = end.min(lines.len());
153 let snippet: String = lines[start..end].join("\n");
154 if snippet.is_empty() {
155 None
156 } else {
157 Some(snippet)
158 }
159 }
160
161 // -----------------------------------------------------------------------
162 // Private helpers

Callers 3

get_codeMethod · 0.80
extract_code_blocksMethod · 0.80
merge_adjacent_blocksMethod · 0.80

Calls 3

insertMethod · 0.80
collectMethod · 0.80
is_emptyMethod · 0.45

Tested by

no test coverage detected