graph-indexer 2.1.1 → 3.0.0

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.
Files changed (129) hide show
  1. package/CHANGELOG.md +260 -1
  2. package/README.md +232 -312
  3. package/SECURITY.md +37 -59
  4. package/bin/graph-indexer.mjs +251 -0
  5. package/integrations/claude-code/.claude-plugin/plugin.json +8 -0
  6. package/integrations/claude-code/.mcp.json +8 -0
  7. package/integrations/claude-code/agents/code-structure.md +22 -0
  8. package/integrations/claude-code/hooks/gi-hook.mjs +99 -0
  9. package/integrations/claude-code/hooks/hooks.json +16 -0
  10. package/integrations/opencode/graph-indexer.js +124 -0
  11. package/package.json +32 -109
  12. package/src/cli/helper.mjs +67 -0
  13. package/src/cli/hook.mjs +356 -0
  14. package/src/cli/init.mjs +255 -0
  15. package/src/cli/resident.mjs +175 -0
  16. package/src/index/discover.mjs +130 -0
  17. package/src/index/fingerprint.mjs +30 -0
  18. package/src/index/graph.mjs +61 -0
  19. package/src/index/indexer.mjs +476 -0
  20. package/src/index/modules.mjs +331 -0
  21. package/src/index/resolver.mjs +954 -0
  22. package/src/mcp/render.mjs +60 -0
  23. package/src/mcp/server.mjs +147 -0
  24. package/src/mcp/tools.mjs +973 -0
  25. package/src/parse/arity.mjs +152 -0
  26. package/src/parse/extract.mjs +1031 -0
  27. package/src/parse/lang/csharp.mjs +106 -0
  28. package/src/parse/lang/ecma.mjs +438 -0
  29. package/src/parse/lang/go.mjs +194 -0
  30. package/src/parse/lang/jvm.mjs +118 -0
  31. package/src/parse/lang/kotlin.mjs +97 -0
  32. package/src/parse/lang/misc.mjs +115 -0
  33. package/src/parse/lang/native.mjs +126 -0
  34. package/src/parse/lang/python.mjs +153 -0
  35. package/src/parse/lang/rust.mjs +157 -0
  36. package/src/parse/lang/scripting.mjs +219 -0
  37. package/src/parse/languages.mjs +48 -0
  38. package/src/parse/runtime.mjs +56 -0
  39. package/src/query/check.mjs +343 -0
  40. package/src/query/facts.mjs +323 -0
  41. package/src/query/intel.mjs +680 -0
  42. package/src/query/read.mjs +81 -0
  43. package/src/query/testcmd.mjs +119 -0
  44. package/src/query/textsearch.mjs +160 -0
  45. package/src/search/search.mjs +210 -0
  46. package/src/search/tokenize.mjs +188 -0
  47. package/src/store/db.mjs +169 -0
  48. package/src/util/paths.mjs +24 -0
  49. package/vendor/grammars/bash.wasm.gz +0 -0
  50. package/vendor/grammars/c.wasm.gz +0 -0
  51. package/vendor/grammars/c_sharp.wasm.gz +0 -0
  52. package/vendor/grammars/cpp.wasm.gz +0 -0
  53. package/vendor/grammars/css.wasm.gz +0 -0
  54. package/vendor/grammars/go.wasm.gz +0 -0
  55. package/vendor/grammars/java.wasm.gz +0 -0
  56. package/vendor/grammars/javascript.wasm.gz +0 -0
  57. package/vendor/grammars/kotlin.wasm.gz +0 -0
  58. package/vendor/grammars/manifest.json +148 -0
  59. package/vendor/grammars/php.wasm.gz +0 -0
  60. package/vendor/grammars/python.wasm.gz +0 -0
  61. package/vendor/grammars/ruby.wasm.gz +0 -0
  62. package/vendor/grammars/rust.wasm.gz +0 -0
  63. package/vendor/grammars/scala.wasm.gz +0 -0
  64. package/vendor/grammars/tsx.wasm.gz +0 -0
  65. package/vendor/grammars/typescript.wasm.gz +0 -0
  66. package/vendor/web-tree-sitter/web-tree-sitter.js +3980 -0
  67. package/vendor/web-tree-sitter/web-tree-sitter.wasm +0 -0
  68. package/cli-ui.mjs +0 -78
  69. package/colbert.mjs +0 -168
  70. package/config.mjs +0 -494
  71. package/daemon-ctl.mjs +0 -175
  72. package/daemon-lock.mjs +0 -69
  73. package/embedders/python/mlx_embed_server.py +0 -61
  74. package/embedders/python/requirements-mlx.txt +0 -5
  75. package/embedders/setup-mlx.mjs +0 -110
  76. package/embeddings.mjs +0 -571
  77. package/engine/binary.mjs +0 -437
  78. package/engine/memory.mjs +0 -1003
  79. package/engine/sqlite.mjs +0 -1136
  80. package/enrichment.mjs +0 -521
  81. package/git-signals.mjs +0 -248
  82. package/indexer.mjs +0 -546
  83. package/init.mjs +0 -1809
  84. package/layout.mjs +0 -123
  85. package/mcp/centrality.mjs +0 -117
  86. package/mcp/format.mjs +0 -61
  87. package/mcp/resolver.mjs +0 -116
  88. package/mcp/symbolgraph.mjs +0 -137
  89. package/mcp/taint.mjs +0 -225
  90. package/mcp/tools.mjs +0 -1582
  91. package/mcp/topology.mjs +0 -676
  92. package/mcp-server.mjs +0 -197
  93. package/parse/extractor.mjs +0 -628
  94. package/parse/imports.mjs +0 -365
  95. package/parse/interprocedural.mjs +0 -134
  96. package/parse/languages.mjs +0 -253
  97. package/parse/metadata.mjs +0 -701
  98. package/parse/routes.mjs +0 -327
  99. package/parse/scip.mjs +0 -391
  100. package/parse/taint-patterns.mjs +0 -119
  101. package/prompts/CORE.md +0 -91
  102. package/prompts/DOMAIN_TEMPLATE.md +0 -46
  103. package/prompts/INTEGRATION.md +0 -123
  104. package/prompts/frameworks/ANDROID.md +0 -17
  105. package/prompts/frameworks/ASPNET_CORE.md +0 -19
  106. package/prompts/frameworks/FASTAPI_DJANGO.md +0 -20
  107. package/prompts/frameworks/LARAVEL_SYMFONY.md +0 -22
  108. package/prompts/frameworks/NODE_EXPRESS_NESTJS.md +0 -19
  109. package/prompts/frameworks/RAILS.md +0 -20
  110. package/prompts/frameworks/REACT.md +0 -20
  111. package/prompts/frameworks/SPRING_BOOT.md +0 -20
  112. package/prompts/languages/BASH.md +0 -22
  113. package/prompts/languages/C.md +0 -21
  114. package/prompts/languages/CSHARP.md +0 -24
  115. package/prompts/languages/CSS_SCSS.md +0 -22
  116. package/prompts/languages/GO.md +0 -24
  117. package/prompts/languages/JAVA.md +0 -23
  118. package/prompts/languages/JAVASCRIPT_TYPESCRIPT.md +0 -24
  119. package/prompts/languages/KOTLIN.md +0 -24
  120. package/prompts/languages/PHP.md +0 -23
  121. package/prompts/languages/PYTHON.md +0 -23
  122. package/prompts/languages/RUBY.md +0 -23
  123. package/prompts/languages/RUST.md +0 -21
  124. package/prompts/languages/SWIFT.md +0 -21
  125. package/seal.mjs +0 -400
  126. package/search-core.mjs +0 -777
  127. package/search-sparse.mjs +0 -183
  128. package/storage.mjs +0 -73
  129. package/watch-daemon.mjs +0 -289
@@ -0,0 +1,106 @@
1
+ /** C# extraction spec. */
2
+
3
+ const T = (cap) => `[(identifier) @${cap} (generic_name (identifier) @${cap}) (qualified_name name: (identifier) @${cap}) (qualified_name name: (generic_name (identifier) @${cap})) (nullable_type (identifier) @${cap})]`;
4
+
5
+ const QUERY = `
6
+ (class_declaration name: (identifier) @name) @def.class
7
+ (interface_declaration name: (identifier) @name) @def.interface
8
+ (struct_declaration name: (identifier) @name) @def.struct
9
+ (enum_declaration name: (identifier) @name) @def.enum
10
+ (record_declaration name: (identifier) @name) @def.class
11
+ (delegate_declaration name: (identifier) @name) @def.type
12
+ (method_declaration returns: (_) @type name: (identifier) @name) @def.method
13
+ (method_declaration name: (identifier) @name) @def.method
14
+ (constructor_declaration name: (identifier) @name) @def.constructor
15
+ (property_declaration type: (_) @type name: (identifier) @name) @def.property
16
+ (property_declaration name: (identifier) @name) @def.property
17
+ (field_declaration (variable_declaration type: (_) @type (variable_declarator name: (identifier) @name))) @def.field
18
+ (field_declaration (variable_declaration (variable_declarator name: (identifier) @name))) @def.field
19
+ (enum_member_declaration name: (identifier) @name) @def.constant
20
+
21
+ (invocation_expression function: (identifier) @name) @ref.call
22
+ (invocation_expression function: (generic_name (identifier) @name)) @ref.call
23
+ (invocation_expression function: (member_access_expression expression: (_) @recv name: [(identifier) @name (generic_name (identifier) @name)])) @ref.call
24
+ (object_creation_expression type: ${T('name')}) @ref.new
25
+ (base_list ${T('name')}) @ref.inherit
26
+ (base_list (primary_constructor_base_type type: ${T('name')})) @ref.inherit
27
+ (attribute name: ${T('name')}) @ref.decorator
28
+ (variable_declaration type: ${T('name')}) @ref.type
29
+ (parameter type: ${T('name')}) @ref.type
30
+ (method_declaration returns: ${T('name')}) @ref.type
31
+ (property_declaration type: ${T('name')}) @ref.type
32
+ (type_argument_list ${T('name')}) @ref.type
33
+ (typeof_expression type: ${T('name')}) @ref.type
34
+ (argument (identifier) @name) @ref.value
35
+
36
+ [(lambda_expression) (anonymous_method_expression)] @scope
37
+ (return_statement (_) @ret)
38
+ (using_directive) @import
39
+
40
+ (variable_declaration type: (_) @bind.type (variable_declarator name: (identifier) @bind.name)) @bind
41
+ (variable_declaration (variable_declarator name: (identifier) @bind.name (object_creation_expression type: ${T('bind.new')}))) @bind
42
+ (variable_declaration (variable_declarator name: (identifier) @bind.name (_) @bind.expr)) @bind
43
+ (parameter type: (_) @bind.type name: (identifier) @bind.name) @bind
44
+ (foreach_statement type: (_) @bind.type left: (identifier) @bind.name right: (_) @bind.elem) @bind
45
+ (field_declaration (variable_declaration type: (_) @field.type (variable_declarator name: (identifier) @field.name))) @field
46
+ (property_declaration type: (_) @field.type name: (identifier) @field.name) @field
47
+ `;
48
+
49
+ const BUILTIN = new Set(['string', 'String', 'int', 'long', 'bool', 'double', 'float', 'decimal', 'object', 'Object',
50
+ 'void', 'dynamic', 'List', 'Dictionary', 'IEnumerable', 'IList', 'ICollection', 'Task', 'Guid', 'DateTime',
51
+ 'TimeSpan', 'Exception', 'Func', 'Action', 'IReadOnlyList', 'IReadOnlyCollection', 'HashSet', 'Nullable',
52
+ 'CancellationToken', 'Array', 'Type', 'byte', 'char', 'short', 'uint', 'ulong']);
53
+
54
+ function usingImport(node) {
55
+ const text = node.text.replace(/^global\s+/, '').replace(/^using\s+(static\s+)?/, '').replace(/;\s*$/, '').trim();
56
+ const alias = /^(\w+)\s*=\s*(.+)$/.exec(text);
57
+ if (alias) return [{ source: alias[2].trim(), imported: '*', local: alias[1] }];
58
+ return [{ source: text, imported: '*', local: null, wildcard: true }];
59
+ }
60
+
61
+ function modifiers(node) { return node.namedChildren.filter(c => c.type === 'modifier').map(c => c.text).join(' '); }
62
+
63
+ function fileInfo(root) {
64
+ const ns = [];
65
+ (function walk(n, depth) {
66
+ if (depth > 3) return;
67
+ for (const c of n.namedChildren) {
68
+ if (c.type === 'namespace_declaration' || c.type === 'file_scoped_namespace_declaration') ns.push(c.childForFieldName('name')?.text);
69
+ else if (c.type === 'declaration_list') walk(c, depth + 1);
70
+ }
71
+ })(root, 0);
72
+ return { package: ns.filter(Boolean)[0] ?? null };
73
+ }
74
+
75
+ export const csharp = {
76
+ id: 'csharp',
77
+ grammar: 'c_sharp',
78
+ extensions: ['.cs'],
79
+ family: 'dotnet',
80
+ query: QUERY,
81
+ implicitThis: true,
82
+ selfNames: ['this'],
83
+ externalReceivers: new Set(['Console', 'Math', 'String', 'Task', 'Enumerable', 'Guid', 'DateTime', 'Convert',
84
+ 'Assert', 'Mock', 'JsonSerializer', 'File', 'Path', 'Directory', 'Environment', 'Debug', 'Trace', '_logger', 'logger', 'Logger']),
85
+ builtinCalls: new Set(['nameof', 'typeof', 'ToString', 'Equals', 'GetHashCode', 'GetType']),
86
+ testFile: /(^|\/)(tests?|Tests?|[\w.]*\.Tests?)\/|Tests?\.cs$/,
87
+ commentTypes: ['comment'],
88
+ parseImport: usingImport,
89
+ isExported: (node) => /\b(public|internal)\b/.test(modifiers(node)) || node.parent?.parent?.type === 'interface_declaration',
90
+ visibility: (node) => { const m = modifiers(node); return /\bprivate\b/.test(m) ? 'private' : /\bprotected\b/.test(m) ? 'protected' : /\bpublic\b/.test(m) ? 'public' : null; },
91
+ isPrimitiveType: (t) => BUILTIN.has(t),
92
+ transparentTypes: new Set(['Task', 'ValueTask', 'Nullable']),
93
+ elementTypes: new Set(['List', 'IList', 'IEnumerable', 'ICollection', 'IReadOnlyList', 'IReadOnlyCollection', 'HashSet', 'ISet', 'Queue', 'Stack',
94
+ 'LinkedList', 'Collection', 'ObservableCollection', 'ImmutableList', 'ImmutableArray', 'IAsyncEnumerable', 'IQueryable', 'Span', 'ReadOnlySpan', 'Memory']),
95
+ elementMethods: new Set(['First', 'FirstOrDefault', 'Last', 'LastOrDefault', 'Single', 'SingleOrDefault', 'ElementAt', 'ElementAtOrDefault', 'Find', 'Dequeue', 'Peek', 'Pop']),
96
+ mapTypes: new Set(['Dictionary', 'IDictionary', 'IReadOnlyDictionary', 'ConcurrentDictionary', 'SortedDictionary', 'ImmutableDictionary']),
97
+ mapMethods: new Set(['GetValueOrDefault', 'GetOrAdd']),
98
+ mapValueMethods: new Set(['Values']),
99
+ decoratorsOf(node) {
100
+ return node.namedChildren.filter(c => c.type === 'attribute_list')
101
+ .flatMap(l => l.namedChildren.filter(a => a.type === 'attribute').map(a => a.childForFieldName('name')?.text))
102
+ .filter(Boolean).slice(0, 8);
103
+ },
104
+ fileInfo,
105
+ bodyField: 'body',
106
+ };
@@ -0,0 +1,438 @@
1
+ /**
2
+ * JavaScript / TypeScript / TSX extraction specs.
3
+ *
4
+ * Captures follow the engine convention (see ../extract.mjs):
5
+ * @def.<kind> + @name [+ @owner] a definition
6
+ * @ref.<kind> + @name [+ @recv] a reference (call/new/type/inherit/decorator/value)
7
+ * @import an import/export-from statement (parsed by the hook)
8
+ * @import.require + @src a CommonJS require() call
9
+ * @bind + @bind.name + @bind.(type|new|call|expr|elem) local variable → type evidence
10
+ * @field + @field.name + @field.(type|new|expr) class field → type evidence
11
+ * (`expr` = the initialiser expression, `elem` = a collection whose element the name is bound to)
12
+ */
13
+
14
+ const DEFS_COMMON = `
15
+ (function_declaration name: (identifier) @name) @def.function
16
+ (generator_function_declaration name: (identifier) @name) @def.function
17
+ (class_declaration name: (_) @name) @def.class
18
+ (class name: (_) @name) @def.class
19
+ (class "class" @name !name) @def.class
20
+ (method_definition name: (_) @name) @def.method
21
+ (lexical_declaration (variable_declarator name: (identifier) @name value: [(arrow_function) (function_expression) (generator_function)]) @def.function)
22
+ (variable_declaration (variable_declarator name: (identifier) @name value: [(arrow_function) (function_expression) (generator_function)]) @def.function)
23
+ (variable_declarator name: (identifier) @name value: (class)) @def.class
24
+ (lexical_declaration (variable_declarator name: (identifier) @name value: (_) @_v) @def.variable (#not-match? @_v "^(async\\\\s*)?(function|\\\\(|[A-Za-z_$][A-Za-z0-9_$]*\\\\s*=>)"))
25
+ (variable_declaration (variable_declarator name: (identifier) @name value: (_) @_v) @def.variable (#not-match? @_v "^(async\\\\s*)?(function|\\\\(|[A-Za-z_$][A-Za-z0-9_$]*\\\\s*=>)"))
26
+ (assignment_expression
27
+ left: (member_expression
28
+ object: (member_expression object: (identifier) @owner property: (property_identifier) @_proto)
29
+ property: (property_identifier) @name)
30
+ right: [(function_expression) (arrow_function)]
31
+ (#eq? @_proto "prototype")) @def.method
32
+ (expression_statement (assignment_expression
33
+ left: (member_expression object: (identifier) @owner property: (property_identifier) @name)
34
+ right: [(function_expression) (arrow_function)])) @def.function
35
+ (expression_statement (assignment_expression
36
+ left: (member_expression object: (member_expression object: (identifier) @_m property: (property_identifier) @_e) property: (property_identifier) @name)
37
+ right: [(function_expression) (arrow_function)]
38
+ (#eq? @_m "module") (#eq? @_e "exports"))) @def.function
39
+ (pair key: (property_identifier) @name value: [(function_expression) (arrow_function)]) @def.method
40
+ (export_statement "default" value: [(function_expression) (arrow_function) (object) (call_expression) (binary_expression) (class)] @name) @def.function
41
+ (export_statement "default" declaration: [(function_declaration !name) (class_declaration !name)] @name) @def.function
42
+ `;
43
+
44
+ const DEFS_JS = `
45
+ (field_definition property: (_) @name value: [(arrow_function) (function_expression)]) @def.method
46
+ (field_definition property: (_) @name value: (class)) @def.class
47
+ (field_definition property: (_) @name) @def.field
48
+ `;
49
+
50
+ const DEFS_TS = `
51
+ (function_signature name: (identifier) @name) @def.function
52
+ (abstract_class_declaration name: (type_identifier) @name) @def.class
53
+ (interface_declaration name: (type_identifier) @name) @def.interface
54
+ (type_alias_declaration name: (type_identifier) @name) @def.type
55
+ (enum_declaration name: (identifier) @name) @def.enum
56
+ (internal_module name: (_) @name) @def.module
57
+ (module name: (_) @name) @def.module
58
+ (method_signature name: (_) @name) @def.method
59
+ (abstract_method_signature name: (_) @name) @def.method
60
+ (public_field_definition name: (_) @name value: [(arrow_function) (function_expression)]) @def.method
61
+ (public_field_definition name: (_) @name value: (class)) @def.class
62
+ (public_field_definition name: (_) @name) @def.field
63
+ (required_parameter (accessibility_modifier) pattern: (identifier) @name) @def.field
64
+ (required_parameter "readonly" pattern: (identifier) @name) @def.field
65
+ (optional_parameter (accessibility_modifier) pattern: (identifier) @name) @def.field
66
+ (property_signature name: (_) @name) @def.field
67
+ (function_declaration name: (identifier) @name return_type: (type_annotation (_) @type)) @def.function
68
+ (function_signature name: (identifier) @name return_type: (type_annotation (_) @type)) @def.function
69
+ (method_definition name: (_) @name return_type: (type_annotation (_) @type)) @def.method
70
+ (method_signature name: (_) @name return_type: (type_annotation (_) @type)) @def.method
71
+ (abstract_method_signature name: (_) @name return_type: (type_annotation (_) @type)) @def.method
72
+ (lexical_declaration (variable_declarator name: (identifier) @name value: (arrow_function return_type: (type_annotation (_) @type))) @def.function)
73
+ (public_field_definition name: (_) @name type: (type_annotation (_) @type)) @def.field
74
+ (property_signature name: (_) @name type: (type_annotation (_) @type)) @def.field
75
+ (class_declaration name: (_) @name (class_heritage (extends_clause) @type)) @def.class
76
+ (abstract_class_declaration name: (_) @name (class_heritage (extends_clause) @type)) @def.class
77
+ (class name: (_) @name (class_heritage (extends_clause) @type)) @def.class
78
+ (class "class" @name !name (class_heritage (extends_clause) @type)) @def.class
79
+ (variable_declarator name: (identifier) @name value: (class (class_heritage (extends_clause) @type))) @def.class
80
+ (required_parameter (accessibility_modifier) pattern: (identifier) @name type: (type_annotation (_) @type)) @def.field
81
+ (required_parameter "readonly" pattern: (identifier) @name type: (type_annotation (_) @type)) @def.field
82
+ (optional_parameter (accessibility_modifier) pattern: (identifier) @name type: (type_annotation (_) @type)) @def.field
83
+ `;
84
+
85
+ const REFS_COMMON = `
86
+ (call_expression function: (identifier) @name) @ref.call
87
+ (call_expression function: (member_expression object: (_) @recv property: (_) @name)) @ref.call
88
+ (call_expression function: (await_expression (identifier) @name)) @ref.call
89
+ (call_expression function: (await_expression (member_expression object: (_) @recv property: (_) @name))) @ref.call
90
+ (new_expression constructor: (identifier) @name) @ref.new
91
+ (new_expression constructor: (member_expression object: (_) @recv property: (_) @name)) @ref.new
92
+ (decorator (identifier) @name) @ref.decorator
93
+ (decorator (call_expression function: (identifier) @name)) @ref.decorator
94
+ (decorator (call_expression function: (member_expression object: (_) @recv property: (_) @name))) @ref.decorator
95
+ (arguments (identifier) @name) @ref.value
96
+ (pair value: (identifier) @name) @ref.value
97
+ (array (identifier) @name) @ref.value
98
+ (shorthand_property_identifier) @name @ref.value
99
+ (member_expression object: (_) @recv property: (property_identifier) @name) @ref.read
100
+ (member_expression object: (identifier) @name) @ref.value
101
+ (binary_expression operator: "instanceof" right: (identifier) @name) @ref.type
102
+ (computed_property_name (identifier) @name) @ref.value
103
+ (computed_property_name (member_expression object: (_) @recv property: (property_identifier) @name)) @ref.read
104
+ (unary_expression operator: "typeof" argument: (identifier) @name) @ref.value
105
+ (arrow_function body: (identifier) @name) @ref.value
106
+ (ternary_expression consequence: (identifier) @name) @ref.value
107
+ (ternary_expression alternative: (identifier) @name) @ref.value
108
+ (return_statement (identifier) @name) @ref.value
109
+ (variable_declarator value: (identifier) @name) @ref.value
110
+ (assignment_expression right: (identifier) @name) @ref.value
111
+ `;
112
+
113
+ const REFS_JSX = `
114
+ (jsx_opening_element name: (identifier) @name) @ref.call
115
+ (jsx_self_closing_element name: (identifier) @name) @ref.call
116
+ (jsx_opening_element name: (member_expression object: (_) @recv property: (_) @name)) @ref.call
117
+ (jsx_self_closing_element name: (member_expression object: (_) @recv property: (_) @name)) @ref.call
118
+ `;
119
+
120
+ const REFS_JS = `
121
+ (class_heritage (identifier) @name) @ref.inherit
122
+ (class_heritage (member_expression object: (_) @recv property: (_) @name)) @ref.inherit
123
+ `;
124
+
125
+ const REFS_TS = `
126
+ (extends_clause value: (identifier) @name) @ref.inherit
127
+ (extends_clause value: (member_expression object: (_) @recv property: (_) @name)) @ref.inherit
128
+ (implements_clause (type_identifier) @name) @ref.inherit
129
+ (implements_clause (generic_type name: (type_identifier) @name)) @ref.inherit
130
+ (extends_type_clause type: (type_identifier) @name) @ref.inherit
131
+ (extends_type_clause type: (generic_type name: (type_identifier) @name)) @ref.inherit
132
+ (type_identifier) @name @ref.type
133
+ (nested_type_identifier module: (_) @recv name: (type_identifier) @name) @ref.type
134
+ (type_query (identifier) @name) @ref.value
135
+ (type_query (member_expression object: (_) @recv property: (property_identifier) @name)) @ref.type
136
+ `;
137
+
138
+ const IMPORTS_COMMON = `
139
+ (import_statement) @import
140
+ (export_statement source: (string)) @import
141
+ (call_expression function: (identifier) @_req arguments: (arguments . (string) @src) (#eq? @_req "require")) @import.require
142
+
143
+ [(arrow_function) (function_expression) (generator_function)] @scope
144
+ (return_statement (_) @ret)
145
+ (arrow_function body: [(call_expression) (new_expression) (member_expression) (identifier) (await_expression) (parenthesized_expression) (this) (subscript_expression)] @ret)
146
+ `;
147
+
148
+ // `xs.forEach(x => …)`: the first callback parameter of an element-wise method is an element (a
149
+ // map's value for `m.forEach(v => …)`).
150
+ const callbackParam = (param) => `(call_expression
151
+ function: (member_expression object: (_) @bind.each property: (property_identifier) @_m)
152
+ arguments: (arguments . (arrow_function ${param}))
153
+ (#match? @_m "^(forEach|map|filter|find|findLast|findIndex|findLastIndex|some|every|flatMap)$")) @bind`;
154
+
155
+ const BINDINGS_COMMON = `
156
+ (variable_declarator name: (identifier) @bind.name value: (_) @bind.expr) @bind
157
+ (for_in_statement left: (identifier) @bind.name "of" right: (_) @bind.elem) @bind
158
+ ${callbackParam('parameter: (identifier) @bind.name')}
159
+ (assignment_expression left: (member_expression object: (this) property: (property_identifier) @field.name) right: (_) @field.expr) @field
160
+ `;
161
+
162
+ const BINDINGS_TS = `
163
+ ${callbackParam('parameters: (formal_parameters . (required_parameter pattern: (identifier) @bind.name))')}
164
+ (call_expression function: [(identifier) (member_expression)] @cb.fn arguments: (arguments [(arrow_function) (function_expression)] @cb.arg)) @cb
165
+ (variable_declarator name: (identifier) @bind.name type: (type_annotation (_) @bind.type)) @bind
166
+ (required_parameter pattern: (identifier) @bind.name type: (type_annotation (_) @bind.type)) @bind
167
+ (optional_parameter pattern: (identifier) @bind.name type: (type_annotation (_) @bind.type)) @bind
168
+ (variable_declarator name: (object_pattern (pair_pattern key: (property_identifier) @bind.key value: (identifier) @bind.name)) value: (_) @bind.expr) @bind
169
+ (variable_declarator name: (object_pattern (shorthand_property_identifier_pattern) @bind.name @bind.key) value: (_) @bind.expr) @bind
170
+ (required_parameter pattern: (object_pattern (pair_pattern key: (property_identifier) @bind.key value: (identifier) @bind.name)) type: (type_annotation (_) @bind.of)) @bind
171
+ (required_parameter pattern: (object_pattern (shorthand_property_identifier_pattern) @bind.name @bind.key) type: (type_annotation (_) @bind.of)) @bind
172
+ (public_field_definition name: (property_identifier) @field.name type: (type_annotation (_) @field.type)) @field
173
+ (public_field_definition name: (property_identifier) @field.name value: (_) @field.expr) @field
174
+ (required_parameter (accessibility_modifier) pattern: (identifier) @field.name type: (type_annotation (_) @field.type)) @field
175
+ (required_parameter "readonly" pattern: (identifier) @field.name type: (type_annotation (_) @field.type)) @field
176
+ (optional_parameter (accessibility_modifier) pattern: (identifier) @field.name type: (type_annotation (_) @field.type)) @field
177
+ `;
178
+
179
+ const BINDINGS_JS = `
180
+ ${callbackParam('parameters: (formal_parameters . (identifier) @bind.name)')}
181
+ (field_definition property: (property_identifier) @field.name value: (_) @field.expr) @field
182
+ `;
183
+
184
+ // Wrappers whose members are reached through the wrapped type (after await / by convention).
185
+ const TRANSPARENT_TYPES = new Set(['Promise', 'PromiseLike', 'Awaited', 'Readonly', 'Partial', 'Required', 'NonNullable', 'DeepPartial', 'DeepReadonly', 'Mutable', 'Pick', 'Omit']);
186
+ /**
187
+ * What a type alias has the members of: `type E = Pick<Entry, 'a'>`, `type E = Entry & { b: B }`,
188
+ * `type E = Readonly<Entry>` — each named type it is made of (through the wrappers above).
189
+ */
190
+ function aliasBases(node) {
191
+ if (node.type !== 'type_alias_declaration') return [];
192
+ const value = node.childForFieldName('value');
193
+ const out = [];
194
+ const visit = (n, depth = 0) => {
195
+ if (!n || depth > 4) return;
196
+ if (n.type === 'intersection_type' || n.type === 'parenthesized_type') { for (const c of n.namedChildren) visit(c, depth + 1); return; }
197
+ if (n.type === 'type_identifier') { out.push(n.text); return; }
198
+ if (n.type === 'nested_type_identifier') { out.push(n.childForFieldName('name')?.text); return; }
199
+ if (n.type === 'generic_type') {
200
+ const head = n.childForFieldName('name');
201
+ const name = head?.type === 'nested_type_identifier' ? head.childForFieldName('name')?.text : head?.text;
202
+ if (TRANSPARENT_TYPES.has(name)) visit(n.childForFieldName('type_arguments')?.namedChildren[0], depth + 1);
203
+ else if (name) out.push(name);
204
+ }
205
+ };
206
+ visit(value);
207
+ return out.filter(Boolean);
208
+ }
209
+
210
+ // Collections: `x[i]`, `for (const e of x)` and `x.forEach(e => …)` see the element type.
211
+ const ELEMENT_TYPES = new Set(['Array', 'ReadonlyArray', 'Set', 'ReadonlySet', 'Iterable', 'IterableIterator', 'Iterator', 'AsyncIterable', 'AsyncIterableIterator', 'Generator', 'AsyncGenerator']);
212
+ // Types whose members never live in the repository.
213
+ // (`any` / `unknown` are not here: a value of that type may well be an instance of a repository class)
214
+ const PRIMITIVE_TYPES = new Set(['string', 'number', 'boolean', 'bigint', 'symbol', 'object', 'void', 'never', 'undefined', 'null',
215
+ 'String', 'Number', 'Boolean', 'Object', 'Function', 'Date', 'RegExp', 'Map', 'WeakMap', 'WeakSet', 'Record', 'Error', 'Buffer',
216
+ 'ArrayBuffer', 'Uint8Array', 'DataView', 'URL', 'URLSearchParams', 'Headers', 'Request', 'Response', 'AbortController', 'AbortSignal']);
217
+
218
+ // Ubiquitous globals whose members never resolve into the repository.
219
+ const EXTERNAL_RECEIVERS = new Set([
220
+ 'console', 'JSON', 'Math', 'Object', 'Array', 'Promise', 'Reflect', 'Number', 'String', 'Symbol',
221
+ 'Date', 'process', 'window', 'document', 'globalThis', 'Buffer', 'Intl', 'navigator', 'performance',
222
+ 'localStorage', 'sessionStorage', 'location', 'history', 'Error', 'Map', 'Set', 'WeakMap', 'RegExp',
223
+ 'module', 'exports', 'require', 'jest', 'vi', 'expect', 'assert', 'chai', 'sinon',
224
+ ]);
225
+ const BUILTIN_CALLS = new Set([
226
+ 'require', 'setTimeout', 'setInterval', 'clearTimeout', 'clearInterval', 'setImmediate', 'parseInt',
227
+ 'parseFloat', 'isNaN', 'isFinite', 'encodeURIComponent', 'decodeURIComponent', 'encodeURI', 'decodeURI',
228
+ 'String', 'Number', 'Boolean', 'Symbol', 'BigInt', 'queueMicrotask', 'structuredClone', 'fetch', 'eval',
229
+ 'describe', 'it', 'test', 'expect', 'beforeEach', 'afterEach', 'beforeAll', 'afterAll', 'suite', 'context',
230
+ ]);
231
+
232
+ // a top-level integration/ directory holds integration-test apps (nestjs, many monorepos)
233
+ const TEST_FILE_RE = /(^|\/)(__tests__|__mocks__|tests?|spec|e2e)\/|^integration\/|\.(test|spec|e2e-spec|cy)\.[cm]?[jt]sx?$/;
234
+
235
+ function stripQuotes(s) { return s.replace(/^['"`]|['"`]$/g, ''); }
236
+
237
+ /** Parse an ES import / export-from statement node into import records. */
238
+ function parseImportNode(node) {
239
+ const out = [];
240
+ const srcNode = node.childForFieldName('source');
241
+ if (!srcNode) return out;
242
+ const source = stripQuotes(srcNode.text);
243
+ if (node.type === 'import_statement') {
244
+ let any = false;
245
+ for (const child of node.namedChildren) {
246
+ if (child.type === 'import_clause') {
247
+ for (const c of child.namedChildren) {
248
+ if (c.type === 'identifier') { out.push({ source, imported: 'default', local: c.text }); any = true; }
249
+ else if (c.type === 'namespace_import') {
250
+ const id = c.namedChildren.find(n => n.type === 'identifier');
251
+ if (id) { out.push({ source, imported: '*', local: id.text }); any = true; }
252
+ } else if (c.type === 'named_imports') {
253
+ for (const spec of c.namedChildren) {
254
+ if (spec.type !== 'import_specifier') continue;
255
+ const name = spec.childForFieldName('name')?.text;
256
+ const alias = spec.childForFieldName('alias')?.text;
257
+ if (name) { out.push({ source, imported: stripQuotes(name), local: alias || stripQuotes(name) }); any = true; }
258
+ }
259
+ }
260
+ }
261
+ } else if (child.type === 'import_require_clause') {
262
+ const id = child.namedChildren.find(n => n.type === 'identifier');
263
+ if (id) { out.push({ source, imported: '*', local: id.text }); any = true; }
264
+ }
265
+ }
266
+ if (!any) out.push({ source, imported: null, local: null }); // side-effect import
267
+ } else if (node.type === 'export_statement') {
268
+ const clause = node.namedChildren.find(n => n.type === 'export_clause');
269
+ const nsExport = node.namedChildren.find(n => n.type === 'namespace_export');
270
+ if (clause) {
271
+ for (const spec of clause.namedChildren) {
272
+ if (spec.type !== 'export_specifier') continue;
273
+ const name = spec.childForFieldName('name')?.text;
274
+ const alias = spec.childForFieldName('alias')?.text;
275
+ if (name) out.push({ source, imported: stripQuotes(name), local: null, reexport: stripQuotes(alias || name) });
276
+ }
277
+ } else if (nsExport) {
278
+ const id = nsExport.namedChildren[0];
279
+ out.push({ source, imported: '*', local: null, reexport: id ? stripQuotes(id.text) : '*' });
280
+ } else {
281
+ out.push({ source, imported: '*', local: null, reexport: '*' });
282
+ }
283
+ }
284
+ return out;
285
+ }
286
+
287
+ /** const x = require('m') / const { a, b: c } = require('m') / require('m') */
288
+ function parseRequire(callNode, srcNode) {
289
+ const source = stripQuotes(srcNode.text);
290
+ let p = callNode.parent;
291
+ if (p?.type === 'await_expression') p = p.parent;
292
+ if (p?.type === 'variable_declarator') {
293
+ const nameNode = p.childForFieldName('name');
294
+ if (nameNode?.type === 'identifier') return [{ source, imported: '*', local: nameNode.text }];
295
+ if (nameNode?.type === 'object_pattern') {
296
+ const out = [];
297
+ for (const c of nameNode.namedChildren) {
298
+ if (c.type === 'shorthand_property_identifier_pattern') out.push({ source, imported: c.text, local: c.text });
299
+ else if (c.type === 'pair_pattern') {
300
+ const k = c.childForFieldName('key')?.text, v = c.childForFieldName('value');
301
+ if (k && v?.type === 'identifier') out.push({ source, imported: k, local: v.text });
302
+ }
303
+ }
304
+ if (out.length) return out;
305
+ }
306
+ }
307
+ return [{ source, imported: null, local: null }];
308
+ }
309
+
310
+ // what names a class expression (`const X = class {}`, a field, a default export) is the definition
311
+ const CLASS_HOLDERS = new Set(['variable_declarator', 'public_field_definition', 'field_definition', 'export_statement']);
312
+ const isAnonymousClass = (node) => node.type === 'class' && !node.childForFieldName('name');
313
+
314
+ /**
315
+ * The name of an anonymous class expression: what importers call it when it is a CommonJS export
316
+ * (`module.exports = class …`, `exports.Foo = class …`), else `<anonymous>` (`return class extends
317
+ * ModuleRef {…}`, `{ useClass: class {…} }`), a name no code can refer to. It is a symbol of its
318
+ * own so that `this` in its methods is an instance of it and its bases.
319
+ */
320
+ function anonymousClassName(node, relPath) {
321
+ const p = node.parent;
322
+ const left = p?.type === 'assignment_expression' && p.childForFieldName('right')?.id === node.id ? p.childForFieldName('left') : null;
323
+ const target = left?.type === 'member_expression' ? left.text.replace(/\s+/g, '') : '';
324
+ if (target === 'module.exports') return fileStem(relPath) || '<anonymous>';
325
+ if (/^(module\.)?exports\.[A-Za-z_$][\w$]*$/.test(target)) return target.slice(target.lastIndexOf('.') + 1);
326
+ return '<anonymous>';
327
+ }
328
+
329
+ /** What importers call a module's default export: its file name in camel case (`index` → its directory). */
330
+ function fileStem(relPath) {
331
+ const base = String(relPath ?? '').split('/').pop().replace(/\.[^.]+$/, '');
332
+ const stem = base === 'index' ? String(relPath).split('/').slice(-2, -1)[0] ?? base : base;
333
+ return stem.replace(/[-_.](\w)/g, (_, c) => c.toUpperCase()) || null;
334
+ }
335
+
336
+ /** `Array.from(xs)` and `[...xs]` hold the elements of xs: the node of xs, else null. */
337
+ function collectionSource(node) {
338
+ const only = (list) => { const kids = list?.namedChildren.filter(n => n.type !== 'comment') ?? []; return kids.length === 1 ? kids[0] : null; };
339
+ if (node.type === 'call_expression' && node.childForFieldName('function')?.text.replace(/\s+/g, '') === 'Array.from') {
340
+ const arg = only(node.childForFieldName('arguments')); // a second argument maps the elements
341
+ return arg && arg.type !== 'spread_element' ? arg : null;
342
+ }
343
+ if (node.type === 'array') {
344
+ const el = only(node);
345
+ return el?.type === 'spread_element' ? el.namedChildren[0] ?? null : null;
346
+ }
347
+ return null;
348
+ }
349
+
350
+ /** `const x = require('y')` / `const x = require('y').z` / `const {a} = require('y')` are imports, not definitions. */
351
+ function isRequireBinding(node) {
352
+ const decl = node.type === 'variable_declarator' ? node : node.namedChildren?.find(c => c.type === 'variable_declarator');
353
+ const v = decl?.childForFieldName('value');
354
+ return !!v && /^(await\s+)?require\s*\(/.test(v.text);
355
+ }
356
+
357
+ function isModuleLevel(node) {
358
+ // a variable declarator is module-level if its declaration sits in program / export_statement
359
+ let decl = node.type === 'variable_declarator' ? node.parent : node;
360
+ const p = decl?.parent;
361
+ return p?.type === 'program' || (p?.type === 'export_statement' && p.parent?.type === 'program');
362
+ }
363
+
364
+ function isExported(defNode) {
365
+ let n = defNode;
366
+ if (n.type === 'variable_declarator') n = n.parent;
367
+ const p = n.parent;
368
+ if (p?.type === 'export_statement') return true;
369
+ // `module.exports.x = ...`, `exports.x = ...`
370
+ if (defNode.type === 'expression_statement') return /^(module\.)?exports\./.test(defNode.text);
371
+ return false;
372
+ }
373
+
374
+ function visibility(defNode) {
375
+ for (const c of defNode.children) {
376
+ if (c.type === 'accessibility_modifier') return c.text; // public/private/protected
377
+ }
378
+ const name = defNode.childForFieldName('name');
379
+ if (name?.type === 'private_property_identifier') return 'private';
380
+ return null;
381
+ }
382
+
383
+ function makeSpec(id, grammar, extensions, { ts, jsx }) {
384
+ return {
385
+ id,
386
+ grammar,
387
+ extensions,
388
+ family: 'ecma',
389
+ query: [
390
+ DEFS_COMMON, ts ? DEFS_TS : DEFS_JS,
391
+ REFS_COMMON, ts ? REFS_TS : REFS_JS, jsx ? REFS_JSX : '',
392
+ IMPORTS_COMMON, BINDINGS_COMMON, ts ? BINDINGS_TS : BINDINGS_JS,
393
+ ].join('\n'),
394
+ implicitThis: false,
395
+ implicitBases: aliasBases,
396
+ selfNames: ['this'],
397
+ externalReceivers: EXTERNAL_RECEIVERS,
398
+ builtinCalls: BUILTIN_CALLS,
399
+ transparentTypes: TRANSPARENT_TYPES,
400
+ elementTypes: ELEMENT_TYPES,
401
+ isPrimitiveType: (t) => PRIMITIVE_TYPES.has(t),
402
+ elementMethods: new Set(['at', 'find', 'findLast', 'pop', 'shift']),
403
+ mapTypes: new Set(['Map', 'ReadonlyMap', 'WeakMap', 'Record']),
404
+ mapMethods: new Set(['get']),
405
+ mapValueMethods: new Set(['values']),
406
+ cleanType: (t) => t.replace(/^extends\s+/, ''),
407
+ testFile: TEST_FILE_RE,
408
+ commentTypes: ['comment'],
409
+ containerKinds: new Set(['class', 'interface', 'module', 'enum', 'function', 'method']),
410
+ parseImport: parseImportNode,
411
+ collectionSource,
412
+ filterDef: (d) => !((d.kind === 'variable') && isRequireBinding(d.node))
413
+ && !(isAnonymousClass(d.node) && CLASS_HOLDERS.has(d.node.parent?.type)), // named by its holder
414
+ // `export default class extends Base {…}` is a class (its methods' `this`), not a function
415
+ refineKind: (kind, d) => (d.node.type === 'export_statement' && (d.nameNode.type === 'class' || d.nameNode.type === 'class_declaration') ? 'class' : kind),
416
+ normalizeName: (name, d, relPath) => {
417
+ if (d.node.type === 'export_statement') {
418
+ // default export → its own name, else named after its file (what importers call it)
419
+ d.isDefault = true;
420
+ const inner = d.nameNode;
421
+ let own = inner.childForFieldName?.('name')?.text;
422
+ if (!own && inner.type === 'binary_expression') own = inner.childForFieldName('right')?.childForFieldName?.('name')?.text;
423
+ return own || fileStem(relPath);
424
+ }
425
+ if (isAnonymousClass(d.node)) return anonymousClassName(d.node, relPath);
426
+ return name;
427
+ },
428
+ parseRequire,
429
+ isModuleLevel,
430
+ isExported,
431
+ visibility,
432
+ bodyField: 'body',
433
+ };
434
+ }
435
+
436
+ export const javascript = makeSpec('javascript', 'javascript', ['.js', '.jsx', '.mjs', '.cjs'], { ts: false, jsx: true });
437
+ export const typescript = makeSpec('typescript', 'typescript', ['.ts', '.mts', '.cts'], { ts: true, jsx: false });
438
+ export const tsx = makeSpec('tsx', 'tsx', ['.tsx'], { ts: true, jsx: true });