MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / astChunkFile

Function astChunkFile

src/context/ast-chunk.ts:118–268  ·  view source on GitHub ↗
(rel: string, content: string, maxLines = 80)

Source from the content-addressed store, hash-verified

116 * `maxLines` caps a single chunk; larger declarations are line-split.
117 */
118export async function astChunkFile(rel: string, content: string, maxLines = 80): Promise<Chunk[]> {
119 const lang = langForFile(rel);
120 if (!lang) return lineChunk(rel, content);
121 const boundary = BOUNDARY_TYPES[lang];
122 if (!boundary) return lineChunk(rel, content);
123
124 let parser;
125 try {
126 parser = await getParser(lang);
127 } catch {
128 return lineChunk(rel, content);
129 }
130 if (!parser) return lineChunk(rel, content);
131
132 let tree;
133 try {
134 tree = parser.parser.parse(content);
135 } catch {
136 return lineChunk(rel, content);
137 }
138
139 const lines = content.split('\n');
140 const root = tree.rootNode;
141 const chunks: Chunk[] = [];
142 const boundaries: Array<{ startLine: number; endLine: number; symbol?: string; qualifiedSymbol?: string }> = [];
143
144 // Container node types whose children we descend into to chunk members
145 // (methods, nested functions, nested classes) as their own units.
146 // - JS/TS: class_declaration, class_body
147 // - Python: class_definition (+ block body)
148 // - PHP: class_declaration, trait/interface declaration
149 // - Rust: impl_item, trait_item, mod_item (bodies are declaration_list)
150 // - Go: a struct is type_declaration but holds NO methods (methods are
151 // top-level funcs with receivers), so Go intentionally has no container
152 // to descend — its functions are already top-level boundaries.
153 const CONTAINER_RE = /^(class_declaration|abstract_class_declaration|class_definition|class_specifier|class_body|class|interface_declaration|trait_declaration|trait_item|impl_item|mod_item|module|namespace_definition|namespace|object|enum_declaration|enum_item|declaration_list)$/;
154 // Body node types that hold a container's members.
155 const BODY_RE = /^(body|class_body|declaration_list|field_declaration_list|enum_body|block|impl_item|trait_item)$/;
156
157 /**
158 * Recursively collect chunk boundaries.
159 *
160 * Strategy (depth-unbounded, but cost-bounded by maxLines):
161 * - A boundary node that fits in maxLines becomes ONE chunk, with its full
162 * text (decorators included — see decorator handling below).
163 * - A boundary node that is a CONTAINER and is LARGER than maxLines is split:
164 * we don't emit the whole container, we descend into its body and chunk each
165 * member (method / nested function / nested class) separately, qualifying
166 * each member's symbol with the container name (e.g. "UserService.login").
167 * This is what fixes deeply-nested React/Django/FastAPI code: a 400-line
168 * class no longer becomes one giant chunk or gets cut mid-method.
169 * - Decorators (Python @decorator, TS @Component) are part of the
170 * decorated_definition / are preceding siblings; tree-sitter's
171 * decorated_definition node already spans them, and for TS the decorators
172 * are children of the class/method node, so the node's start..end already
173 * includes them. We therefore chunk on the OUTERMOST node so the decorator
174 * travels with the thing it decorates.
175 */

Callers 3

fileOutlineFunction · 0.85
buildIndexFunction · 0.85
buildTaskContextFunction · 0.85

Calls 6

langForFileFunction · 0.85
lineChunkFunction · 0.85
getParserFunction · 0.85
collectFunction · 0.85
mkChunkFunction · 0.85
pushMethod · 0.45

Tested by

no test coverage detected