MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / hook_binary_operator

Method hook_binary_operator

codegraph-kernel/src/rlang.rs:410–475  ·  view source on GitHub ↗
(&mut self, node: Node<'t>)

Source from the content-addressed store, hash-verified

408 }
409
410 fn hook_binary_operator(&mut self, node: Node<'t>) -> bool {
411 stack_guard!();
412 let op = match node.child_by_field_name("operator") {
413 Some(o) => self.text(o),
414 None => return false,
415 };
416 let lhs = node.child_by_field_name("lhs");
417 let rhs = node.child_by_field_name("rhs");
418
419 // name <- function(…) — ANY scope (r.ts:267-279). Body walked through
420 // the hook-aware visit (visitFunctionBody never runs for R).
421 if is_assign_left(op) {
422 if let (Some(lhs), Some(rhs)) = (lhs, rhs) {
423 if lhs.kind() == "identifier" && rhs.kind() == "function_definition" {
424 let params_text = rhs.child_by_field_name("parameters").map(|p| self.text(p));
425 let name = self.text(lhs).to_string();
426 let fn_row = self.create_node("function", &name, node, params_text);
427 let body = rhs.child_by_field_name("body");
428 if let (Some(row), Some(body)) = (fn_row, body) {
429 self.stack.push(Scope { row, kind: "function", name });
430 self.visit(body);
431 self.stack.pop();
432 }
433 return true;
434 }
435 }
436 }
437
438 let top_level = node.parent().map(|p| p.kind() == "program").unwrap_or(false);
439
440 // Top-level value assignments → variable/constant (r.ts:284-296);
441 // the class-definition idiom suppresses the twin variable node but the
442 // rhs is ALWAYS visited.
443 if top_level && is_assign_left(op) {
444 if let (Some(lhs), Some(rhs)) = (lhs, rhs) {
445 if lhs.kind() == "identifier" {
446 let rhs_callee = if rhs.kind() == "call" { self.callee_name(rhs) } else { None };
447 let suppressed = rhs_callee
448 .map(|c| is_class_fn(c) || is_generic_fn(c))
449 .unwrap_or(false);
450 if !suppressed {
451 let name = self.text(lhs);
452 let kind = if constant_name_re().is_match(name) { "constant" } else { "variable" };
453 self.create_node(kind, name, node, None);
454 }
455 self.visit(rhs);
456 return true;
457 }
458 }
459 }
460
461 // value -> name / value ->> name (r.ts:298-303).
462 if top_level && is_assign_right(op) {
463 if let (Some(lhs), Some(rhs)) = (lhs, rhs) {
464 if rhs.kind() == "identifier" {
465 let name = self.text(rhs);
466 let kind = if constant_name_re().is_match(name) { "constant" } else { "variable" };
467 self.create_node(kind, name, node, None);

Callers 1

hookMethod · 0.80

Calls 9

is_assign_leftFunction · 0.85
is_class_fnFunction · 0.85
is_generic_fnFunction · 0.85
constant_name_reFunction · 0.85
is_assign_rightFunction · 0.85
callee_nameMethod · 0.80
textMethod · 0.65
create_nodeMethod · 0.45
visitMethod · 0.45

Tested by

no test coverage detected