Skip to content

Import Traversal

Last verified end to end: 2026-10-01 (query_code schema version 1).

Import traversal starts with an indexed project declaration, not an import spelling. Convert that declaration to its file with file-of, then follow either a forward (imports-of) or reverse (importers-of) project-local file edge. This keeps the result honest: Bifrost reports the files connected by a resolved import, not a guess that every importer calls a particular member. Rust also follows pub use re-exports, including chained, glob, and module re-exports, to the file that defines the item. That edge can point past the file that holds the re-export.

For a project-local callable named target and an importing callable named consume, these RQL pipelines have the following roles:

; The declaration that contains a structural call match.
(enclosing-decl
(language <language> (call :callee (name "target"))))
; The file that declares target.
(file-of
(language <language> (callable :name "target")))
; The direct project-local file imported by consume's file.
(imports-of
(file-of (language <language> (callable :name "consume"))))
; Every project file that directly imports target's file.
(importers-of
(file-of (language <language> (callable :name "target"))))

For MCP or saved JSON queries, replace the last expression with the same structural match and ordered steps:

{
"languages": ["<language>"],
"match": {"kind": "callable", "name": "target"},
"steps": [
{"op": "file_of"},
{"op": "importers_of"}
]
}

<language> is the query_code filter label shown below. cpp deliberately covers both C and C++.

For example, the Ruby form is directly runnable as RQL or JSON:

(importers-of
(file-of (language ruby (callable :name "target"))))
{"languages":["ruby"],"match":{"kind":"callable","name":"target"},"steps":[{"op":"file_of"},{"op":"importers_of"}]}

Every adapter provides structured import-file analysis. The reverse pipeline above returns the importer, and the forward pipeline returns the target file, for each row of this table.

Query labelTarget declarationDirect importer
pythondef target(): pass in target.pyfrom target import target
javapublic static void target() {} in example/Target.javaimport example.Target;
javascriptexport function target() {} in target.jsimport { target } from './target.js';
typescriptexport function target(): void {} in target.tsimport { target } from './target';
gofunc Target() {} in target/target.goimport "example.com/project/target"
cppinline int target() { return 0; } in target.h#include "target.h"
rustpub fn target() {} in src/shared.rsuse crate::shared::target;
scaladef target(): Unit = () in example/Target.scalaimport example.Target
csharppublic static void target() {} in Target.csusing Example;
rubydef target; end in target.rbrequire_relative 'target'
phpnamespace Ex; function target() {} in target.phprequire_once __DIR__ . '/target.php';
kotlinpackage example and fun target() {} in example/Target.ktimport example.target

The query does not need to duplicate each language’s import grammar. The language adapter obtains the structured import facts, and the shared pipeline only sees project files and resolved file edges. For Rust, the adapter follows structured pub use routes across Cargo crates. It records the item’s defining file as an import target, in addition to the module file that the use path names. A single file edge still does not say that the importer calls or otherwise uses a particular declaration.

Boundary: External Libraries And Member Uses

Section titled “Boundary: External Libraries And Member Uses”

The table intentionally uses project-local targets. An import of an out-of-scope package can be observed structurally with an import pattern, but it has no indexed project declaration or file to start this traversal. Bifrost does not create a synthetic declaration for that package, its types, or its methods.

PHP edges come from namespace use declarations and from include, include_once, require, and require_once expressions whose paths can be folded from plain string literals, __DIR__, dirname(__FILE__), dirname(__DIR__), and string concatenation. A bare relative literal is resolved from the including file’s directory. These file edges are a workspace-local approximation of PHP’s include resolution rules. Dynamic expressions such as require $path do not create an edge; import traversal reports the affected workspace-relative files with the incomplete dynamic_import_target diagnostic.

Likewise, a reverse edge says that a file imports the target file, not that it calls target. Use Reference Traversal to traverse an indexed declaration to exact reference sites or semantic users. Because reference sites compose with file-of, a proven symbol edge can also feed imports-of or importers-of without turning the import relationship into a synthetic symbol identity.