gitnexus 1.6.4-rc.47 → 1.6.4-rc.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -210,6 +210,95 @@ const TYPESCRIPT_SCOPE_QUERY = `
210
210
  key: (string (string_fragment) @declaration.name)
211
211
  value: (function_expression) @declaration.function)
212
212
 
213
+ ;; HOC-wrapped variable declarations: \`const X = HOC((args) => { ... })\`.
214
+ ;;
215
+ ;; Covers the dominant React UI idiom (\`React.forwardRef\`, \`React.memo\`,
216
+ ;; bare \`forwardRef\` / \`memo\` / \`observer\`), Hook callbacks
217
+ ;; (\`useCallback\`, \`useMemo\`), and library-wrapper factories (\`debounce\`,
218
+ ;; \`throttle\`, user-defined \`withErrorBoundary\` / \`createHook\`, etc.).
219
+ ;; All produce the same AST shape:
220
+ ;;
221
+ ;; lexical_declaration
222
+ ;; variable_declarator
223
+ ;; name: identifier "X" ← we want this name
224
+ ;; value: call_expression
225
+ ;; function: identifier | member_expression ← any callee
226
+ ;; arguments: arguments
227
+ ;; arrow_function | function_expression ← the actual code
228
+ ;;
229
+ ;; The pre-fix \`tsExtractFunctionName\` only handled \`variable_declarator\`
230
+ ;; and \`pair\` parents, so HOC-wrapped arrows fell through anonymous. The
231
+ ;; registry-primary \`query.ts\` had no pattern for this shape either —
232
+ ;; \`const Button = forwardRef((p, r) => { ... })\` registered as a
233
+ ;; \`Variable\` with no \`Function\` def, and every call inside the arrow
234
+ ;; body lost caller attribution: \`resolveCallerGraphId\` walked up past
235
+ ;; the empty arrow scope to the module's File fallback. Sourcerer-fe alone
236
+ ;; has ~296 such declarations (57 forwardRef + 21 memo + 161 useCallback
237
+ ;; + 57 useMemo) — all invisible to \`gitnexus_context\` /
238
+ ;; \`gitnexus_impact\` for outgoing edges before this fix.
239
+ ;;
240
+ ;; Anchor discipline: same as the \`lexical_declaration\` / \`pair\` blocks
241
+ ;; above — on the INNER \`arrow_function\` / \`function_expression\`, NOT
242
+ ;; the outer \`call_expression\`. The arrow's range matches its own
243
+ ;; \`@scope.function\` range, so \`pass2AttachDeclarations.atPosition\`
244
+ ;; resolves \`innermost\` to the arrow's own scope and
245
+ ;; \`rangesEqual(anchor.range, innermost.range)\` triggers the auto-hoist
246
+ ;; that promotes the binding to the parent scope (where \`const X\`
247
+ ;; lives).
248
+ ;;
249
+ ;; Trade-off — chained array-method form: \`const x = arr.find((y) => p(y))\`
250
+ ;; has the same syntactic shape and would also match, naming the
251
+ ;; \`.find\` callback as \`x\`. The resulting \`Function:x\` is mostly
252
+ ;; harmless: \`x\` is consumed as a value (\`if (x) { ... }\`), never
253
+ ;; invoked as a function, so it gets zero incoming \`CALLS\` edges. The
254
+ ;; one outgoing edge \`Function:x → p\` is a minor mis-attribution that
255
+ ;; could in principle be fixed by adding a \`function: [(identifier)
256
+ ;; (member_expression)]\` predicate that excludes property-identifiers
257
+ ;; matching a known array-method blocklist (\`map\` / \`filter\` / \`find\`
258
+ ;; / \`reduce\` / \`forEach\` / \`some\` / \`every\`). We don't do that here
259
+ ;; because (a) the false-positive cost is negligible, (b) the blocklist
260
+ ;; would need maintenance, and (c) any user-defined fluent-API method
261
+ ;; with a callback argument would still false-positive — there's no
262
+ ;; clean syntactic line.
263
+ ;;
264
+ ;; Trade-off — multi-arrow arguments: \`const x = call(arrow1, arrow2)\`
265
+ ;; would emit TWO matches with the same name \`x\`. tree-sitter-query
266
+ ;; iterates all arrow_function direct children of \`arguments\`, so each
267
+ ;; emits its own \`(name=x, function=...)\` pair. \`pass2AttachDeclarations\`
268
+ ;; pushes both \`Function:x\` defs into the same arrow scopes (each in
269
+ ;; its own arrow's \`ownedDefs\`) and hoists both bindings to the parent.
270
+ ;; The downstream registry's qualified-name dedup then collapses them
271
+ ;; via \`(filePath, type, qualifiedName)\` — second wins. Acceptable;
272
+ ;; multi-arrow-callback APIs are rare (\`new Promise(executor)\` is the
273
+ ;; main one and takes a single executor).
274
+ (lexical_declaration
275
+ (variable_declarator
276
+ name: (identifier) @declaration.name
277
+ value: (call_expression
278
+ arguments: (arguments
279
+ (arrow_function) @declaration.function))))
280
+
281
+ (lexical_declaration
282
+ (variable_declarator
283
+ name: (identifier) @declaration.name
284
+ value: (call_expression
285
+ arguments: (arguments
286
+ (function_expression) @declaration.function))))
287
+
288
+ (variable_declaration
289
+ (variable_declarator
290
+ name: (identifier) @declaration.name
291
+ value: (call_expression
292
+ arguments: (arguments
293
+ (arrow_function) @declaration.function))))
294
+
295
+ (variable_declaration
296
+ (variable_declarator
297
+ name: (identifier) @declaration.name
298
+ value: (call_expression
299
+ arguments: (arguments
300
+ (function_expression) @declaration.function))))
301
+
213
302
  ;; Method definitions — regular + private (#field) methods.
214
303
  (method_definition
215
304
  name: (property_identifier) @declaration.name) @declaration.method
@@ -37,11 +37,21 @@ import { emitTsScopeCaptures, interpretTsImport, interpretTsTypeBinding, tsBindi
37
37
  * - `{ addItem: (item) => ... }` (pair / property_assignment) → "addItem"
38
38
  * Covers Zustand stores, TanStack Query factories, React Context
39
39
  * providers, and most other HOF-heavy idioms (issue #1166).
40
+ * - `const X = HOC((args) => { ... })` (arguments → call_expression →
41
+ * variable_declarator) → "X". Covers `React.forwardRef`, `memo`,
42
+ * `useCallback`, `useMemo`, `observer`, `debounce`, and other HOC
43
+ * factories that wrap their behaviour-defining arrow. Without this
44
+ * branch, every shadcn/Radix UI component (`const Button =
45
+ * React.forwardRef(...)`) registered as an anonymous arrow with
46
+ * calls inside falling back to File-level attribution. The same
47
+ * applied to all `useCallback` / `useMemo` callbacks bound to a
48
+ * const — the sole way to give them a named caller anchor.
40
49
  *
41
50
  * Returns `null` for funcName when the arrow lives in a context that has
42
- * no static name — call arguments, computed keys, return-from-arrow
43
- * positions. The parent walk in findEnclosingFunctionId then continues
44
- * up to the next named ancestor (or to the file).
51
+ * no static name — bare call arguments (not bound to a const), computed
52
+ * keys, return-from-arrow positions. The parent walk in
53
+ * findEnclosingFunctionId then continues up to the next named ancestor
54
+ * (or to the file).
45
55
  */
46
56
  const tsExtractFunctionName = (node) => {
47
57
  if (node.type !== 'arrow_function' && node.type !== 'function_expression')
@@ -82,6 +92,36 @@ const tsExtractFunctionName = (node) => {
82
92
  // no static name — fall through anonymous.
83
93
  return { funcName: null, label: 'Function' };
84
94
  }
95
+ // HOC-wrapped variable declarations: `const Button = forwardRef((p, r) => { ... })`,
96
+ // `const handleClick = useCallback(() => doStuff(), [deps])`,
97
+ // `const Card = React.memo((props) => { ... })`. The arrow's `parent` is
98
+ // `arguments`, grandparent is `call_expression`, great-grandparent is
99
+ // `variable_declarator`. Walk the chain up and take the variable's name
100
+ // — the meaningful identifier the developer wrote on the LHS. Mirrors
101
+ // the four registry-primary patterns in `typescript/query.ts`. The
102
+ // wrapping callee (`forwardRef`, `memo`, `React.memo`, `useCallback`,
103
+ // user-defined HOCs) is intentionally NOT constrained: any function
104
+ // call whose result is bound to a const and whose first/positional
105
+ // argument is an arrow takes the const's name. Chained array-method
106
+ // calls (`const x = arr.find((y) => p(y))`) match too and produce a
107
+ // mostly-harmless `Function:x` (consumed as a value, never invoked),
108
+ // accepted as a small false-positive cost vs. the much larger gain of
109
+ // capturing the React UI-component idiom.
110
+ if (parent.type === 'arguments') {
111
+ const callExpr = parent.parent;
112
+ if (!callExpr || callExpr.type !== 'call_expression') {
113
+ return { funcName: null, label: 'Function' };
114
+ }
115
+ const declarator = callExpr.parent;
116
+ if (!declarator || declarator.type !== 'variable_declarator') {
117
+ return { funcName: null, label: 'Function' };
118
+ }
119
+ const nameNode = declarator.childForFieldName?.('name');
120
+ if (nameNode?.type === 'identifier') {
121
+ return { funcName: nameNode.text, label: 'Function' };
122
+ }
123
+ return { funcName: null, label: 'Function' };
124
+ }
85
125
  return { funcName: null, label: 'Function' };
86
126
  };
87
127
  export const BUILT_INS = new Set([
@@ -1,5 +1,5 @@
1
- export declare const TYPESCRIPT_QUERIES = "\n(class_declaration\n name: (type_identifier) @name) @definition.class\n\n(abstract_class_declaration\n name: (type_identifier) @name) @definition.class\n\n(interface_declaration\n name: (type_identifier) @name) @definition.interface\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n; TypeScript overload signatures (function_signature is a separate node type from function_declaration)\n(function_signature\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n; ES2022 #private methods (private_property_identifier not matched by property_identifier)\n(method_definition\n name: (private_property_identifier) @name) @definition.method\n\n; Abstract method signatures in abstract classes\n(abstract_method_signature\n name: (property_identifier) @name) @definition.method\n\n; Interface method signatures\n(method_signature\n name: (property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n; Object-property arrows / function expressions: `{ addItem: () => ... }`.\n; The pair's key field carries the meaningful name. Without these patterns,\n; calls inside the arrow are attributed to the file (issue #1166), and the\n; arrow itself is invisible to context() / impact() despite carrying real\n; behaviour (Zustand actions, TanStack queryFn, React Context providers).\n; String-key variant covers `\"add-item\": () => ...`; computed keys\n; (`[K]: () => ...`) intentionally fall through anonymous.\n(pair\n key: (property_identifier) @name\n value: (arrow_function)) @definition.function\n\n(pair\n key: (property_identifier) @name\n value: (function_expression)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (arrow_function)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (function_expression)) @definition.function\n\n; Variable/constant declarations (non-function values).\n; Overlap with @definition.function patterns is handled by parse-worker dedup.\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.const\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name))) @definition.const\n\n; var declarations (mutable, function-scoped)\n(variable_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.variable\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Generic awaited free call: await fn<T>(args)\n; tree-sitter-typescript parses \"await fn<T>(args)\" as a call_expression whose\n; \"function\" field is an await_expression (not a bare identifier), because the\n; grammar resolves the ambiguity between generics and comparisons by consuming\n; \"await fn\" as an expression before attaching <T> as type_arguments.\n(call_expression\n function: (await_expression\n (identifier) @call.name)\n (type_arguments)) @call\n\n; Generic awaited member call: await obj.fn<T>(args)\n(call_expression\n function: (await_expression\n (member_expression\n property: (property_identifier) @call.name))\n (type_arguments)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class properties \u2014 public_field_definition covers most TS class fields\n(public_field_definition\n name: (property_identifier) @name) @definition.property\n\n; Private class fields: #address: Address\n(public_field_definition\n name: (private_property_identifier) @name) @definition.property\n\n; Constructor parameter properties: constructor(public address: Address)\n(required_parameter\n (accessibility_modifier)\n pattern: (identifier) @name) @definition.property\n\n; Heritage queries - class extends\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (extends_clause\n value: (identifier) @heritage.extends))) @heritage\n\n; Heritage queries - class implements interface\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (implements_clause\n (type_identifier) @heritage.implements))) @heritage.impl\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n; fetch() \u2014 global function\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post/put/delete/patch('/path'), $.get/post/ajax({url:'/path'})\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Decorators: @Controller, @Get, @Post, etc.\n(decorator\n (call_expression\n function: (identifier) @decorator.name\n arguments: (arguments (string (string_fragment) @decorator.arg)?))) @decorator\n\n; Express/Hono route registration: app.get('/path', handler), router.post('/path', fn)\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
2
- export declare const JAVASCRIPT_QUERIES = "\n(class_declaration\n name: (identifier) @name) @definition.class\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n; ES2022 #private methods\n(method_definition\n name: (private_property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n; Object-property arrows / function expressions: `{ addItem: () => ... }`.\n; See TYPESCRIPT_QUERIES for rationale (issue #1166).\n(pair\n key: (property_identifier) @name\n value: (arrow_function)) @definition.function\n\n(pair\n key: (property_identifier) @name\n value: (function_expression)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (arrow_function)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (function_expression)) @definition.function\n\n; Variable/constant declarations (non-function values).\n; Overlap with @definition.function patterns is handled by parse-worker dedup.\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.const\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name))) @definition.const\n\n; var declarations (mutable, function-scoped)\n(variable_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.variable\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class fields \u2014 field_definition captures JS class fields (class User { address = ... })\n(field_definition\n property: (property_identifier) @name) @definition.property\n\n; Heritage queries - class extends (JavaScript uses different AST than TypeScript)\n; In tree-sitter-javascript, class_heritage directly contains the parent identifier\n(class_declaration\n name: (identifier) @heritage.class\n (class_heritage\n (identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post, $.get/post/ajax\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Express/Hono route registration\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
1
+ export declare const TYPESCRIPT_QUERIES = "\n(class_declaration\n name: (type_identifier) @name) @definition.class\n\n(abstract_class_declaration\n name: (type_identifier) @name) @definition.class\n\n(interface_declaration\n name: (type_identifier) @name) @definition.interface\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n; TypeScript overload signatures (function_signature is a separate node type from function_declaration)\n(function_signature\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n; ES2022 #private methods (private_property_identifier not matched by property_identifier)\n(method_definition\n name: (private_property_identifier) @name) @definition.method\n\n; Abstract method signatures in abstract classes\n(abstract_method_signature\n name: (property_identifier) @name) @definition.method\n\n; Interface method signatures\n(method_signature\n name: (property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n; Object-property arrows / function expressions: `{ addItem: () => ... }`.\n; The pair's key field carries the meaningful name. Without these patterns,\n; calls inside the arrow are attributed to the file (issue #1166), and the\n; arrow itself is invisible to context() / impact() despite carrying real\n; behaviour (Zustand actions, TanStack queryFn, React Context providers).\n; String-key variant covers `\"add-item\": () => ...`; computed keys\n; (`[K]: () => ...`) intentionally fall through anonymous.\n(pair\n key: (property_identifier) @name\n value: (arrow_function)) @definition.function\n\n(pair\n key: (property_identifier) @name\n value: (function_expression)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (arrow_function)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (function_expression)) @definition.function\n\n; HOC-wrapped variable declarations: `const X = HOC((args) => { ... })`.\n; Mirrors the registry-primary patterns in `languages/typescript/query.ts`\n; so the legacy Call-Resolution DAG and the registry-primary pipeline\n; produce the same set of `Function` nodes \u2014 required for the CI parity\n; gate. Covers React.forwardRef / memo / useCallback / useMemo / observer\n; / debounce / user-defined HOC factories. The `var X = HOC(...)` form is\n; mirrored too (registry-primary has it) so that codebases mixing `var` and\n; `const` see identical attribution on both pipelines. See\n; `tsExtractFunctionName` for the resolution logic and the `query.ts`\n; comment for the full anchor-discipline rationale and the chained-\n; array-method trade-off.\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (arrow_function))))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (function_expression))))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (arrow_function)))))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (function_expression)))))) @definition.function\n\n; `var X = HOC(...)` parity with registry-primary. Legacy code (and any\n; transpiler output that downlevels `const` to `var`) hits this shape.\n(variable_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (arrow_function))))) @definition.function\n\n(variable_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (function_expression))))) @definition.function\n\n; Variable/constant declarations (non-function values).\n; Overlap with @definition.function patterns is handled by parse-worker dedup.\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.const\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name))) @definition.const\n\n; var declarations (mutable, function-scoped)\n(variable_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.variable\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Generic awaited free call: await fn<T>(args)\n; tree-sitter-typescript parses \"await fn<T>(args)\" as a call_expression whose\n; \"function\" field is an await_expression (not a bare identifier), because the\n; grammar resolves the ambiguity between generics and comparisons by consuming\n; \"await fn\" as an expression before attaching <T> as type_arguments.\n(call_expression\n function: (await_expression\n (identifier) @call.name)\n (type_arguments)) @call\n\n; Generic awaited member call: await obj.fn<T>(args)\n(call_expression\n function: (await_expression\n (member_expression\n property: (property_identifier) @call.name))\n (type_arguments)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class properties \u2014 public_field_definition covers most TS class fields\n(public_field_definition\n name: (property_identifier) @name) @definition.property\n\n; Private class fields: #address: Address\n(public_field_definition\n name: (private_property_identifier) @name) @definition.property\n\n; Constructor parameter properties: constructor(public address: Address)\n(required_parameter\n (accessibility_modifier)\n pattern: (identifier) @name) @definition.property\n\n; Heritage queries - class extends\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (extends_clause\n value: (identifier) @heritage.extends))) @heritage\n\n; Heritage queries - class implements interface\n(class_declaration\n name: (type_identifier) @heritage.class\n (class_heritage\n (implements_clause\n (type_identifier) @heritage.implements))) @heritage.impl\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n; fetch() \u2014 global function\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post/put/delete/patch('/path'), $.get/post/ajax({url:'/path'})\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Decorators: @Controller, @Get, @Post, etc.\n(decorator\n (call_expression\n function: (identifier) @decorator.name\n arguments: (arguments (string (string_fragment) @decorator.arg)?))) @decorator\n\n; Express/Hono route registration: app.get('/path', handler), router.post('/path', fn)\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
2
+ export declare const JAVASCRIPT_QUERIES = "\n(class_declaration\n name: (identifier) @name) @definition.class\n\n(function_declaration\n name: (identifier) @name) @definition.function\n\n(method_definition\n name: (property_identifier) @name) @definition.method\n\n; ES2022 #private methods\n(method_definition\n name: (private_property_identifier) @name) @definition.method\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (arrow_function)))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (function_expression)))) @definition.function\n\n; Object-property arrows / function expressions: `{ addItem: () => ... }`.\n; See TYPESCRIPT_QUERIES for rationale (issue #1166).\n(pair\n key: (property_identifier) @name\n value: (arrow_function)) @definition.function\n\n(pair\n key: (property_identifier) @name\n value: (function_expression)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (arrow_function)) @definition.function\n\n(pair\n key: (string (string_fragment) @name)\n value: (function_expression)) @definition.function\n\n; HOC-wrapped variable declarations: `const X = HOC((args) => { ... })`.\n; See TYPESCRIPT_QUERIES section above for the full rationale (issue #1166\n; follow-up \u2014 covers forwardRef / memo / useCallback / useMemo / observer\n; / debounce / user-defined HOC factories). Both `const` and `var` forms\n; are mirrored so JS code that uses `var` (or transpiler output) gets the\n; same attribution as the registry-primary path.\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (arrow_function))))) @definition.function\n\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (function_expression))))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (arrow_function)))))) @definition.function\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (function_expression)))))) @definition.function\n\n; `var X = HOC(...)` parity with registry-primary.\n(variable_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (arrow_function))))) @definition.function\n\n(variable_declaration\n (variable_declarator\n name: (identifier) @name\n value: (call_expression\n arguments: (arguments\n (function_expression))))) @definition.function\n\n; Variable/constant declarations (non-function values).\n; Overlap with @definition.function patterns is handled by parse-worker dedup.\n(lexical_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.const\n\n(export_statement\n declaration: (lexical_declaration\n (variable_declarator\n name: (identifier) @name))) @definition.const\n\n; var declarations (mutable, function-scoped)\n(variable_declaration\n (variable_declarator\n name: (identifier) @name)) @definition.variable\n\n(import_statement\n source: (string) @import.source) @import\n\n; Re-export statements: export { X } from './y'\n(export_statement\n source: (string) @import.source) @import\n\n(call_expression\n function: (identifier) @call.name) @call\n\n(call_expression\n function: (member_expression\n property: (property_identifier) @call.name)) @call\n\n; Constructor calls: new Foo()\n(new_expression\n constructor: (identifier) @call.name) @call\n\n; Class fields \u2014 field_definition captures JS class fields (class User { address = ... })\n(field_definition\n property: (property_identifier) @name) @definition.property\n\n; Heritage queries - class extends (JavaScript uses different AST than TypeScript)\n; In tree-sitter-javascript, class_heritage directly contains the parent identifier\n(class_declaration\n name: (identifier) @heritage.class\n (class_heritage\n (identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment_expression\n left: (member_expression\n object: (_) @assignment.receiver\n property: (property_identifier) @assignment.property)\n right: (_)) @assignment\n\n; HTTP consumers: fetch('/path'), axios.get('/path'), $.get('/path'), etc.\n(call_expression\n function: (identifier) @_fetch_fn (#eq? @_fetch_fn \"fetch\")\n arguments: (arguments\n [(string (string_fragment) @route.url)\n (template_string) @route.template_url])) @route.fetch\n\n; axios.get/post, $.get/post/ajax\n(call_expression\n function: (member_expression\n property: (property_identifier) @http_client.method)\n arguments: (arguments\n (string (string_fragment) @http_client.url))) @http_client\n\n; Express/Hono route registration\n(call_expression\n function: (member_expression\n property: (property_identifier) @express_route.method)\n arguments: (arguments\n (string (string_fragment) @express_route.path))) @express_route\n";
3
3
  export declare const PYTHON_QUERIES = "\n(class_definition\n name: (identifier) @name) @definition.class\n\n(function_definition\n name: (identifier) @name) @definition.function\n\n(import_statement\n name: (dotted_name) @import.source) @import\n\n; import numpy as np \u2192 aliased_import captures the module name so the\n; import path is resolved and named-binding extraction stores \"np\" \u2192 \"numpy\".\n(import_statement\n name: (aliased_import\n name: (dotted_name) @import.source)) @import\n\n(import_from_statement\n module_name: (dotted_name) @import.source) @import\n\n(import_from_statement\n module_name: (relative_import) @import.source) @import\n\n(call\n function: (identifier) @call.name) @call\n\n(call\n function: (attribute\n attribute: (identifier) @call.name)) @call\n\n; Class attribute type annotations \u2014 PEP 526: address: Address or address: Address = Address()\n; Both bare annotations (address: Address) and annotated assignments (name: str = \"test\")\n; are parsed as (assignment left: ... type: ...) in tree-sitter-python.\n(expression_statement\n (assignment\n left: (identifier) @name\n type: (type)) @definition.property)\n\n; Plain variable assignments without type annotation: x = 5, MAX_SIZE = 100\n; Overlap with @definition.property (typed) is handled by parse-worker dedup.\n(expression_statement\n (assignment\n left: (identifier) @name)) @definition.variable\n\n; Heritage queries - Python class inheritance\n(class_definition\n name: (identifier) @heritage.class\n superclasses: (argument_list\n (identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment\n left: (attribute\n object: (_) @assignment.receiver\n attribute: (identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(augmented_assignment\n left: (attribute\n object: (_) @assignment.receiver\n attribute: (identifier) @assignment.property)\n right: (_)) @assignment\n\n; Python HTTP clients: requests.get('/path'), httpx.post('/path'), session.get('/path')\n(call\n function: (attribute\n attribute: (identifier) @http_client.method)\n arguments: (argument_list\n (string (string_content) @http_client.url))) @http_client\n\n; Python decorators: @app.route, @router.get, etc.\n(decorator\n (call\n function: (attribute\n object: (identifier) @decorator.receiver\n attribute: (identifier) @decorator.name)\n arguments: (argument_list\n (string (string_content) @decorator.arg)?))) @decorator\n";
4
4
  export declare const JAVA_QUERIES = "\n; Classes, Interfaces, Enums, Annotations\n(class_declaration name: (identifier) @name) @definition.class\n(interface_declaration name: (identifier) @name) @definition.interface\n(enum_declaration name: (identifier) @name) @definition.enum\n(annotation_type_declaration name: (identifier) @name) @definition.annotation\n\n; Methods & Constructors\n(method_declaration name: (identifier) @name) @definition.method\n(constructor_declaration name: (identifier) @name) @definition.constructor\n\n; Fields \u2014 typed field declarations inside class bodies\n(field_declaration\n declarator: (variable_declarator\n name: (identifier) @name)) @definition.property\n\n; Imports - capture any import declaration child as source\n(import_declaration (_) @import.source) @import\n\n; Calls\n(method_invocation name: (identifier) @call.name) @call\n(method_invocation object: (_) name: (identifier) @call.name) @call\n(method_reference) @call\n\n; Constructor calls: new Foo()\n(object_creation_expression type: (type_identifier) @call.name) @call\n\n; Local variable declarations inside method bodies\n(local_variable_declaration\n declarator: (variable_declarator\n name: (identifier) @name)) @definition.variable\n\n; Heritage - extends class\n(class_declaration name: (identifier) @heritage.class\n (superclass (type_identifier) @heritage.extends)) @heritage\n\n; Heritage - implements interfaces\n(class_declaration name: (identifier) @heritage.class\n (super_interfaces (type_list (type_identifier) @heritage.implements))) @heritage.impl\n\n; Write access: obj.field = value\n(assignment_expression\n left: (field_access\n object: (_) @assignment.receiver\n field: (identifier) @assignment.property)\n right: (_)) @assignment\n";
5
5
  export declare const C_QUERIES = "\n; Functions (direct declarator)\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n\n; Functions returning pointers (pointer_declarator wraps function_declarator)\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(declaration declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n\n; Functions returning double pointers (nested pointer_declarator)\n(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name)))) @definition.function\n\n; Structs, Unions, Enums, Typedefs\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(union_specifier name: (type_identifier) @name) @definition.union\n(enum_specifier name: (type_identifier) @name) @definition.enum\n(type_definition declarator: (type_identifier) @name) @definition.typedef\n\n; Macros\n(preproc_function_def name: (identifier) @name) @definition.macro\n(preproc_def name: (identifier) @name) @definition.macro\n\n; Includes\n(preproc_include path: (_) @import.source) @import\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (field_expression field: (field_identifier) @call.name)) @call\n\n; Variable declarations: int x = 5; or int x;\n(declaration\n declarator: (init_declarator\n declarator: (identifier) @name)) @definition.variable\n";
@@ -83,6 +83,63 @@ export const TYPESCRIPT_QUERIES = `
83
83
  key: (string (string_fragment) @name)
84
84
  value: (function_expression)) @definition.function
85
85
 
86
+ ; HOC-wrapped variable declarations: \`const X = HOC((args) => { ... })\`.
87
+ ; Mirrors the registry-primary patterns in \`languages/typescript/query.ts\`
88
+ ; so the legacy Call-Resolution DAG and the registry-primary pipeline
89
+ ; produce the same set of \`Function\` nodes — required for the CI parity
90
+ ; gate. Covers React.forwardRef / memo / useCallback / useMemo / observer
91
+ ; / debounce / user-defined HOC factories. The \`var X = HOC(...)\` form is
92
+ ; mirrored too (registry-primary has it) so that codebases mixing \`var\` and
93
+ ; \`const\` see identical attribution on both pipelines. See
94
+ ; \`tsExtractFunctionName\` for the resolution logic and the \`query.ts\`
95
+ ; comment for the full anchor-discipline rationale and the chained-
96
+ ; array-method trade-off.
97
+ (lexical_declaration
98
+ (variable_declarator
99
+ name: (identifier) @name
100
+ value: (call_expression
101
+ arguments: (arguments
102
+ (arrow_function))))) @definition.function
103
+
104
+ (lexical_declaration
105
+ (variable_declarator
106
+ name: (identifier) @name
107
+ value: (call_expression
108
+ arguments: (arguments
109
+ (function_expression))))) @definition.function
110
+
111
+ (export_statement
112
+ declaration: (lexical_declaration
113
+ (variable_declarator
114
+ name: (identifier) @name
115
+ value: (call_expression
116
+ arguments: (arguments
117
+ (arrow_function)))))) @definition.function
118
+
119
+ (export_statement
120
+ declaration: (lexical_declaration
121
+ (variable_declarator
122
+ name: (identifier) @name
123
+ value: (call_expression
124
+ arguments: (arguments
125
+ (function_expression)))))) @definition.function
126
+
127
+ ; \`var X = HOC(...)\` parity with registry-primary. Legacy code (and any
128
+ ; transpiler output that downlevels \`const\` to \`var\`) hits this shape.
129
+ (variable_declaration
130
+ (variable_declarator
131
+ name: (identifier) @name
132
+ value: (call_expression
133
+ arguments: (arguments
134
+ (arrow_function))))) @definition.function
135
+
136
+ (variable_declaration
137
+ (variable_declarator
138
+ name: (identifier) @name
139
+ value: (call_expression
140
+ arguments: (arguments
141
+ (function_expression))))) @definition.function
142
+
86
143
  ; Variable/constant declarations (non-function values).
87
144
  ; Overlap with @definition.function patterns is handled by parse-worker dedup.
88
145
  (lexical_declaration
@@ -258,6 +315,57 @@ export const JAVASCRIPT_QUERIES = `
258
315
  key: (string (string_fragment) @name)
259
316
  value: (function_expression)) @definition.function
260
317
 
318
+ ; HOC-wrapped variable declarations: \`const X = HOC((args) => { ... })\`.
319
+ ; See TYPESCRIPT_QUERIES section above for the full rationale (issue #1166
320
+ ; follow-up — covers forwardRef / memo / useCallback / useMemo / observer
321
+ ; / debounce / user-defined HOC factories). Both \`const\` and \`var\` forms
322
+ ; are mirrored so JS code that uses \`var\` (or transpiler output) gets the
323
+ ; same attribution as the registry-primary path.
324
+ (lexical_declaration
325
+ (variable_declarator
326
+ name: (identifier) @name
327
+ value: (call_expression
328
+ arguments: (arguments
329
+ (arrow_function))))) @definition.function
330
+
331
+ (lexical_declaration
332
+ (variable_declarator
333
+ name: (identifier) @name
334
+ value: (call_expression
335
+ arguments: (arguments
336
+ (function_expression))))) @definition.function
337
+
338
+ (export_statement
339
+ declaration: (lexical_declaration
340
+ (variable_declarator
341
+ name: (identifier) @name
342
+ value: (call_expression
343
+ arguments: (arguments
344
+ (arrow_function)))))) @definition.function
345
+
346
+ (export_statement
347
+ declaration: (lexical_declaration
348
+ (variable_declarator
349
+ name: (identifier) @name
350
+ value: (call_expression
351
+ arguments: (arguments
352
+ (function_expression)))))) @definition.function
353
+
354
+ ; \`var X = HOC(...)\` parity with registry-primary.
355
+ (variable_declaration
356
+ (variable_declarator
357
+ name: (identifier) @name
358
+ value: (call_expression
359
+ arguments: (arguments
360
+ (arrow_function))))) @definition.function
361
+
362
+ (variable_declaration
363
+ (variable_declarator
364
+ name: (identifier) @name
365
+ value: (call_expression
366
+ arguments: (arguments
367
+ (function_expression))))) @definition.function
368
+
261
369
  ; Variable/constant declarations (non-function values).
262
370
  ; Overlap with @definition.function patterns is handled by parse-worker dedup.
263
371
  (lexical_declaration
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.4-rc.47",
3
+ "version": "1.6.4-rc.48",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",