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.
- package/CHANGELOG.md +260 -1
- package/README.md +232 -312
- package/SECURITY.md +37 -59
- package/bin/graph-indexer.mjs +251 -0
- package/integrations/claude-code/.claude-plugin/plugin.json +8 -0
- package/integrations/claude-code/.mcp.json +8 -0
- package/integrations/claude-code/agents/code-structure.md +22 -0
- package/integrations/claude-code/hooks/gi-hook.mjs +99 -0
- package/integrations/claude-code/hooks/hooks.json +16 -0
- package/integrations/opencode/graph-indexer.js +124 -0
- package/package.json +32 -109
- package/src/cli/helper.mjs +67 -0
- package/src/cli/hook.mjs +356 -0
- package/src/cli/init.mjs +255 -0
- package/src/cli/resident.mjs +175 -0
- package/src/index/discover.mjs +130 -0
- package/src/index/fingerprint.mjs +30 -0
- package/src/index/graph.mjs +61 -0
- package/src/index/indexer.mjs +476 -0
- package/src/index/modules.mjs +331 -0
- package/src/index/resolver.mjs +954 -0
- package/src/mcp/render.mjs +60 -0
- package/src/mcp/server.mjs +147 -0
- package/src/mcp/tools.mjs +973 -0
- package/src/parse/arity.mjs +152 -0
- package/src/parse/extract.mjs +1031 -0
- package/src/parse/lang/csharp.mjs +106 -0
- package/src/parse/lang/ecma.mjs +438 -0
- package/src/parse/lang/go.mjs +194 -0
- package/src/parse/lang/jvm.mjs +118 -0
- package/src/parse/lang/kotlin.mjs +97 -0
- package/src/parse/lang/misc.mjs +115 -0
- package/src/parse/lang/native.mjs +126 -0
- package/src/parse/lang/python.mjs +153 -0
- package/src/parse/lang/rust.mjs +157 -0
- package/src/parse/lang/scripting.mjs +219 -0
- package/src/parse/languages.mjs +48 -0
- package/src/parse/runtime.mjs +56 -0
- package/src/query/check.mjs +343 -0
- package/src/query/facts.mjs +323 -0
- package/src/query/intel.mjs +680 -0
- package/src/query/read.mjs +81 -0
- package/src/query/testcmd.mjs +119 -0
- package/src/query/textsearch.mjs +160 -0
- package/src/search/search.mjs +210 -0
- package/src/search/tokenize.mjs +188 -0
- package/src/store/db.mjs +169 -0
- package/src/util/paths.mjs +24 -0
- package/vendor/grammars/bash.wasm.gz +0 -0
- package/vendor/grammars/c.wasm.gz +0 -0
- package/vendor/grammars/c_sharp.wasm.gz +0 -0
- package/vendor/grammars/cpp.wasm.gz +0 -0
- package/vendor/grammars/css.wasm.gz +0 -0
- package/vendor/grammars/go.wasm.gz +0 -0
- package/vendor/grammars/java.wasm.gz +0 -0
- package/vendor/grammars/javascript.wasm.gz +0 -0
- package/vendor/grammars/kotlin.wasm.gz +0 -0
- package/vendor/grammars/manifest.json +148 -0
- package/vendor/grammars/php.wasm.gz +0 -0
- package/vendor/grammars/python.wasm.gz +0 -0
- package/vendor/grammars/ruby.wasm.gz +0 -0
- package/vendor/grammars/rust.wasm.gz +0 -0
- package/vendor/grammars/scala.wasm.gz +0 -0
- package/vendor/grammars/tsx.wasm.gz +0 -0
- package/vendor/grammars/typescript.wasm.gz +0 -0
- package/vendor/web-tree-sitter/web-tree-sitter.js +3980 -0
- package/vendor/web-tree-sitter/web-tree-sitter.wasm +0 -0
- package/cli-ui.mjs +0 -78
- package/colbert.mjs +0 -168
- package/config.mjs +0 -494
- package/daemon-ctl.mjs +0 -175
- package/daemon-lock.mjs +0 -69
- package/embedders/python/mlx_embed_server.py +0 -61
- package/embedders/python/requirements-mlx.txt +0 -5
- package/embedders/setup-mlx.mjs +0 -110
- package/embeddings.mjs +0 -571
- package/engine/binary.mjs +0 -437
- package/engine/memory.mjs +0 -1003
- package/engine/sqlite.mjs +0 -1136
- package/enrichment.mjs +0 -521
- package/git-signals.mjs +0 -248
- package/indexer.mjs +0 -546
- package/init.mjs +0 -1809
- package/layout.mjs +0 -123
- package/mcp/centrality.mjs +0 -117
- package/mcp/format.mjs +0 -61
- package/mcp/resolver.mjs +0 -116
- package/mcp/symbolgraph.mjs +0 -137
- package/mcp/taint.mjs +0 -225
- package/mcp/tools.mjs +0 -1582
- package/mcp/topology.mjs +0 -676
- package/mcp-server.mjs +0 -197
- package/parse/extractor.mjs +0 -628
- package/parse/imports.mjs +0 -365
- package/parse/interprocedural.mjs +0 -134
- package/parse/languages.mjs +0 -253
- package/parse/metadata.mjs +0 -701
- package/parse/routes.mjs +0 -327
- package/parse/scip.mjs +0 -391
- package/parse/taint-patterns.mjs +0 -119
- package/prompts/CORE.md +0 -91
- package/prompts/DOMAIN_TEMPLATE.md +0 -46
- package/prompts/INTEGRATION.md +0 -123
- package/prompts/frameworks/ANDROID.md +0 -17
- package/prompts/frameworks/ASPNET_CORE.md +0 -19
- package/prompts/frameworks/FASTAPI_DJANGO.md +0 -20
- package/prompts/frameworks/LARAVEL_SYMFONY.md +0 -22
- package/prompts/frameworks/NODE_EXPRESS_NESTJS.md +0 -19
- package/prompts/frameworks/RAILS.md +0 -20
- package/prompts/frameworks/REACT.md +0 -20
- package/prompts/frameworks/SPRING_BOOT.md +0 -20
- package/prompts/languages/BASH.md +0 -22
- package/prompts/languages/C.md +0 -21
- package/prompts/languages/CSHARP.md +0 -24
- package/prompts/languages/CSS_SCSS.md +0 -22
- package/prompts/languages/GO.md +0 -24
- package/prompts/languages/JAVA.md +0 -23
- package/prompts/languages/JAVASCRIPT_TYPESCRIPT.md +0 -24
- package/prompts/languages/KOTLIN.md +0 -24
- package/prompts/languages/PHP.md +0 -23
- package/prompts/languages/PYTHON.md +0 -23
- package/prompts/languages/RUBY.md +0 -23
- package/prompts/languages/RUST.md +0 -21
- package/prompts/languages/SWIFT.md +0 -21
- package/seal.mjs +0 -400
- package/search-core.mjs +0 -777
- package/search-sparse.mjs +0 -183
- package/storage.mjs +0 -73
- package/watch-daemon.mjs +0 -289
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter and argument counting across languages, from tree-sitter nodes: how many arguments a
|
|
3
|
+
* definition accepts ({ min, max }, max = Infinity for variadics) and how many a call passes
|
|
4
|
+
* ({ n, open }, open = a spread/splat makes n a lower bound). Used by the edit checker to spot
|
|
5
|
+
* call sites that no longer match a changed signature, without compiling anything.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const PARAM_LIST_TYPES = new Set(['formal_parameters', 'parameters', 'parameter_list', 'function_value_parameters', 'method_parameters',
|
|
9
|
+
'lambda_parameters', 'block_parameters', 'parameter_clause']);
|
|
10
|
+
const SKIP_PARAM = /^(comment|line_comment|block_comment|self_parameter|this|attribute_item|attribute|annotation|marker_annotation|decorator|keyword_separator|positional_separator|type_parameters|block_parameter)$/;
|
|
11
|
+
const VARIADIC = /(rest_pattern|rest_parameter|spread|variadic|splat|list_splat_pattern|dictionary_splat_pattern|varargs)/;
|
|
12
|
+
const OPTIONAL = /(optional_parameter|default_parameter|typed_default_parameter|optional_parameter_declaration|keyword_parameter)/;
|
|
13
|
+
const CALL_TYPES = new Set(['call_expression', 'call', 'method_invocation', 'invocation_expression', 'new_expression', 'object_creation_expression',
|
|
14
|
+
'function_call_expression', 'member_call_expression', 'scoped_call_expression', 'nullsafe_member_call_expression', 'method_call_expression', 'macro_invocation']);
|
|
15
|
+
const ARG_LIST_TYPES = new Set(['arguments', 'argument_list', 'value_arguments', 'actual_parameters']);
|
|
16
|
+
const SPREAD_ARG = /^(spread_element|list_splat|dictionary_splat|splat_argument|hash_splat_argument|variadic_argument)$/;
|
|
17
|
+
|
|
18
|
+
function paramsNodeOf(def) {
|
|
19
|
+
const direct = def.childForFieldName('parameters');
|
|
20
|
+
if (direct) return direct;
|
|
21
|
+
const value = def.childForFieldName('value');
|
|
22
|
+
const vp = value?.childForFieldName?.('parameters');
|
|
23
|
+
if (vp) return vp;
|
|
24
|
+
if (value && (value.type === 'arrow_function') && value.childForFieldName('parameter')) return value.childForFieldName('parameter');
|
|
25
|
+
for (const c of def.namedChildren) {
|
|
26
|
+
if (PARAM_LIST_TYPES.has(c.type)) return c;
|
|
27
|
+
// C/C++: declarator → function_declarator → parameters
|
|
28
|
+
if (/declarator$/.test(c.type)) { const p = c.childForFieldName('parameters') ?? c.namedChildren.find(x => PARAM_LIST_TYPES.has(x.type)); if (p) return p; }
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Python decorators that turn a def into something other than a plain function: properties, and
|
|
35
|
+
* classes (CapWords by convention, e.g. a caching descriptor). How the result is called is up to
|
|
36
|
+
* that object, so the def's parameters say nothing about its call sites.
|
|
37
|
+
*/
|
|
38
|
+
function isDescriptorDecorator(d) {
|
|
39
|
+
const last = d.split('.').pop();
|
|
40
|
+
return /(property|setter|getter|deleter)$/i.test(last) || /^_*[A-Z]/.test(last);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Accepted argument count of a function/method definition node.
|
|
45
|
+
* @param {object} def tree-sitter node of the definition
|
|
46
|
+
* @param {{ method?: boolean, lang?: string, isStatic?: boolean, decorators?: string[] }} ctx
|
|
47
|
+
* @returns {{ min: number, max: number } | null}
|
|
48
|
+
*/
|
|
49
|
+
export function paramArity(def, { method = false, lang = '', isStatic = false, decorators = [] } = {}) {
|
|
50
|
+
const params = paramsNodeOf(def);
|
|
51
|
+
if (!params) return null;
|
|
52
|
+
if (params.type === 'identifier') return { min: 1, max: 1 }; // `x => …`
|
|
53
|
+
let min = 0, max = 0, first = true, keywordOnly = false;
|
|
54
|
+
const py = lang === 'python';
|
|
55
|
+
if (py && decorators.some(isDescriptorDecorator)) return null;
|
|
56
|
+
for (const p of params.namedChildren) {
|
|
57
|
+
const t = p.type;
|
|
58
|
+
if (t === 'keyword_separator') { keywordOnly = true; continue; }
|
|
59
|
+
if (SKIP_PARAM.test(t)) continue;
|
|
60
|
+
const text = p.text;
|
|
61
|
+
// the receiver: Python self/cls (not for staticmethods), TS `this: T`
|
|
62
|
+
if (first && py && method && !isStatic && !decorators.some(d => /staticmethod/.test(d)) && /^(self|cls)\b/.test(text)) { first = false; continue; }
|
|
63
|
+
first = false;
|
|
64
|
+
if (/^this\s*[:?]/.test(text)) continue;
|
|
65
|
+
if (VARIADIC.test(t) || /^(\.\.\.|\*\*?)/.test(text) || /^params\s/.test(text) || /\bvararg\b/.test(text) || /\.\.\.\s*\w*$/.test(text) && lang === 'go') { max = Infinity; continue; }
|
|
66
|
+
// Go: `a, b int` declares two parameters
|
|
67
|
+
const names = t === 'parameter_declaration' && lang === 'go' ? p.namedChildren.filter(c => c.type === 'identifier').length || 1 : 1;
|
|
68
|
+
const optional = OPTIONAL.test(t) || !!p.childForFieldName('value') || !!p.childForFieldName('default_value')
|
|
69
|
+
|| p.namedChildren.some(c => c.type === 'equals_value_clause')
|
|
70
|
+
|| (['kotlin', 'scala', 'swift'].includes(lang) && /[^=]=[^=>]/.test(text));
|
|
71
|
+
max += names;
|
|
72
|
+
if (!optional && !(keywordOnly && py && /=/.test(text))) min += names;
|
|
73
|
+
}
|
|
74
|
+
return { min, max };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Node of the call whose callee name sits at (row, column), with its argument list. */
|
|
78
|
+
export function callAt(tree, row, column) {
|
|
79
|
+
let n = tree.rootNode.descendantForPosition({ row, column });
|
|
80
|
+
for (let g = 0; n && g < 6; g++, n = n.parent) {
|
|
81
|
+
if (CALL_TYPES.has(n.type)) return n;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Arguments passed by a call node: { n, open } or null when they cannot be counted. */
|
|
87
|
+
export function callArgc(call) {
|
|
88
|
+
let args = call.childForFieldName('arguments');
|
|
89
|
+
if (!args) args = call.namedChildren.find(c => ARG_LIST_TYPES.has(c.type)) ?? null;
|
|
90
|
+
if (!args) {
|
|
91
|
+
// Kotlin: call_suffix → value_arguments (+ trailing lambda)
|
|
92
|
+
const suffix = call.namedChildren.find(c => c.type === 'call_suffix');
|
|
93
|
+
if (suffix) {
|
|
94
|
+
const va = suffix.namedChildren.find(c => c.type === 'value_arguments');
|
|
95
|
+
const lam = suffix.namedChildren.some(c => c.type === 'annotated_lambda') ? 1 : 0;
|
|
96
|
+
if (!va && !lam) return null;
|
|
97
|
+
const n = (va ? va.namedChildren.filter(c => c.type === 'value_argument').length : 0) + lam;
|
|
98
|
+
return { n, open: va ? va.namedChildren.some(c => /\*/.test(c.text.slice(0, 1))) : false };
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
let n = 0, open = false;
|
|
103
|
+
for (const c of args.namedChildren) {
|
|
104
|
+
if (/comment/.test(c.type)) continue;
|
|
105
|
+
if (SPREAD_ARG.test(c.type) || /^\.\.\./.test(c.text) || /\.\.\.$/.test(c.text)) { open = true; continue; }
|
|
106
|
+
if (c.type === 'block' || c.type === 'do_block') continue; // Ruby block argument
|
|
107
|
+
n++;
|
|
108
|
+
}
|
|
109
|
+
return { n, open };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Accepted argument count read from a stored signature (`public List<T> find(String q, T... xs)`):
|
|
114
|
+
* for languages whose overloads are separate methods, to bind a call to the one it can reach.
|
|
115
|
+
* Parameters with a default value are optional; `...`, `vararg` and `params` make it open-ended.
|
|
116
|
+
* @returns {{ min: number, max: number } | null}
|
|
117
|
+
*/
|
|
118
|
+
export function sigArity(sig, name) {
|
|
119
|
+
if (!sig) return null;
|
|
120
|
+
const m = new RegExp(`(?:^|[^\\w$])${name.replace(/[$]/g, '\\$')}\\s*(?:<[^()]*>)?\\s*\\(`).exec(sig);
|
|
121
|
+
if (!m) return null;
|
|
122
|
+
let depth = 0, cur = '', min = 0, max = 0, done = false;
|
|
123
|
+
const param = (p) => {
|
|
124
|
+
p = p.trim();
|
|
125
|
+
if (!p) return;
|
|
126
|
+
if (/\.\.\.|^vararg\s|^params\s/.test(p)) { max = Infinity; return; }
|
|
127
|
+
max++;
|
|
128
|
+
if (!/[^=!<>]=[^=]/.test(p)) min++;
|
|
129
|
+
};
|
|
130
|
+
for (let i = m.index + m[0].length; i < sig.length; i++) {
|
|
131
|
+
const ch = sig[i];
|
|
132
|
+
if (ch === ')' && depth === 0) { param(cur); done = true; break; }
|
|
133
|
+
if ('([{<'.includes(ch)) depth++;
|
|
134
|
+
else if (')]}>'.includes(ch)) depth--;
|
|
135
|
+
if (ch === ',' && depth === 0) { param(cur); cur = ''; } else cur += ch;
|
|
136
|
+
}
|
|
137
|
+
return done ? { min, max } : null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Does a call passing `a` arguments fit a definition accepting `r`? */
|
|
141
|
+
export function fits(a, r) {
|
|
142
|
+
if (!a || !r) return true;
|
|
143
|
+
if (a.n > r.max) return false;
|
|
144
|
+
if (!a.open && a.n < r.min) return false;
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function describeArity(r) {
|
|
149
|
+
if (!r) return '?';
|
|
150
|
+
if (r.max === Infinity) return `${r.min}+`;
|
|
151
|
+
return r.min === r.max ? String(r.min) : `${r.min}–${r.max}`;
|
|
152
|
+
}
|