module
Noir::KotlinCalleeExtractor
Overview
Tree-sitter-backed Kotlin 1-hop callee extractor. Parallels
Noir::JavaCalleeExtractor for JVM analyzers — both Spring (Kotlin)
and Ktor route through this module. Kotlin's call_expression
wraps either a simple_identifier (bare call), a
navigation_expression (a.b.c selector chain, optionally rooted on
this/super), or an inner call_expression (the foo(...) { }
trailing-lambda shape). 1-hop extraction reduces to:
- For Spring Kotlin: find the (class_name, method_name)
function_declarationin the already-parsed root and walk itsfunction_body. - For Ktor: walk the verb DSL call's lambda
statementsnode. - For each
call_expression, reconstruct a textual callee:foo()→fooservice.save(x)→service.savethis.foo()→this.foosuper.foo()→super.fooFoo.bar()(static) →Foo.bargetFoo().bar()→ "" (chained on a call — outer dropped as noise, innergetFoostill emitted via the recursive walk)
Cross-file definition resolution (e.g. userService.save →
UserServiceImpl.save in another file) is intentionally out of
scope for this first cut. Callee#path therefore points at the
call site, matching the honest scope on every other analyzer.
Extended Modules
Defined in:
miniparsers/kotlin_callee_extractor.crConstant Summary
-
ROUTING_DSL_NAMES =
Set {"get", "post", "put", "delete", "patch", "head", "options", "route", "routing", "authenticate", "rateLimit", "install", "intercept", "host", "port"} -
Routing DSL verbs + scoping helpers. When
skip_routingis on (Ktor handler body), acall_expressionwhose root name is in this set is treated as a NESTED ROUTE — we skip both emitting it and descending into its trailing lambda so the nested route's callees don't leak into the parent route's list.
Instance Method Summary
-
#callees_in_lambda(body : LibTreeSitter::TSNode, source : String, file_path : String, skip_routing : Bool = true) : Array(Tuple(String, String, Int32))
Ktor / http4k entry: given a handler body node, return every 1-hop callee inside it.
-
#callees_in_method(root : LibTreeSitter::TSNode, source : String, file_path : String, class_name : String, method_name : String) : Array(Tuple(String, String, Int32))
Spring Kotlin entry: find the (class_name, method_name)
function_declarationinrootand return every 1-hopcall_expressioncallee inside its body as{name, file_path, file_line_1_based}.
Instance Method Detail
Ktor / http4k entry: given a handler body node, return every
1-hop callee inside it. skip_routing controls whether Ktor's
routing DSL (route { ... }, sibling verb calls, etc.) is
treated as a NESTED ROUTE boundary — Ktor needs this on so a
nested route's callees don't leak into the parent; http4k uses
an entirely different routing idiom ("/x" bind GET to h) and
turns the skip off so a real handler call named get isn't
silently dropped.
Spring Kotlin entry: find the (class_name, method_name)
function_declaration in root and return every 1-hop
call_expression callee inside its body as
{name, file_path, file_line_1_based}. Empty array when the
function can't be located or its body is missing.