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

Method visit_binding

src/extraction/nix_extractor.rs:198–435  ·  view source on GitHub ↗

Visit a binding node. Classify as Function, Module, or Const based on the value.

(state: &mut ExtractionState, node: TsNode<'_>)

Source from the content-addressed store, hash-verified

196
197 /// Visit a binding node. Classify as Function, Module, or Const based on the value.
198 fn visit_binding(state: &mut ExtractionState, node: TsNode<'_>) {
199 // Extract name from attrpath child
200 let name = Self::extract_binding_name(state, node);
201 let Some(name) = name else {
202 return;
203 };
204
205 // Get the expression (value) child
206 let expr = node.child_by_field_name("expression");
207
208 let docstring = Self::extract_docstring(state, node);
209 let start_line = node.start_position().row as u32;
210 let end_line = node.end_position().row as u32;
211 let start_column = node.start_position().column as u32;
212 let end_column = node.end_position().column as u32;
213
214 // Enhancement 3: Flake output schema awareness.
215 // In flake.nix files, known output attrs are forced to Module classification.
216 let force_module = Self::is_flake_file(state) && Self::is_flake_output_attr(&name);
217
218 // Enhancement 1: Check if the expression is a builder call (derivation).
219 // We store the builder info before classifying to avoid borrow issues.
220 let builder_info: Option<(String, usize)> = expr.and_then(|e| {
221 Self::is_builder_call(state, e).map(|(_callee, attrset)| {
222 // Store the attrset node id so we can find it again
223 (String::new(), attrset.id())
224 })
225 });
226 let is_builder = builder_info.is_some();
227
228 // Classify based on value expression type
229 let classification = if force_module {
230 Some(BindingKind::Module)
231 } else {
232 expr.map(|e| Self::classify_expression(e))
233 };
234
235 match classification {
236 Some(BindingKind::Function) => {
237 let kind = NodeKind::Function;
238 let qualified_name = format!("{}::{}", state.qualified_prefix(), name);
239 let id = generate_node_id(&state.file_path, &kind, &name, start_line);
240 let signature = Self::extract_function_signature(state, node);
241 let metrics = if let Some(expr_node) = expr {
242 if expr_node.child_count() > 0 {
243 count_complexity(expr_node, &NIX_COMPLEXITY, &state.source)
244 } else {
245 ComplexityMetrics::default()
246 }
247 } else {
248 ComplexityMetrics::default()
249 };
250
251 let graph_node = Node {
252 id: id.clone(),
253 kind,
254 name: name.clone(),
255 qualified_name,

Callers

nothing calls this directly

Calls 8

generate_node_idFunction · 0.85
count_complexityFunction · 0.85
pushMethod · 0.80
kindMethod · 0.80
idMethod · 0.45
parent_node_idMethod · 0.45
node_textMethod · 0.45
is_emptyMethod · 0.45

Tested by

no test coverage detected