graph-indexer 2.1.0 → 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 +31 -105
- 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,126 @@
|
|
|
1
|
+
/** C and C++ extraction specs. */
|
|
2
|
+
|
|
3
|
+
const C_DEFS = `
|
|
4
|
+
(function_definition declarator: (function_declarator declarator: (identifier) @name)) @def.function
|
|
5
|
+
(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @def.function
|
|
6
|
+
(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name)))) @def.function
|
|
7
|
+
(struct_specifier name: (type_identifier) @name body: (_)) @def.struct
|
|
8
|
+
(union_specifier name: (type_identifier) @name body: (_)) @def.struct
|
|
9
|
+
(enum_specifier name: (type_identifier) @name body: (_)) @def.enum
|
|
10
|
+
(type_definition declarator: (type_identifier) @name) @def.type
|
|
11
|
+
(type_definition declarator: (pointer_declarator declarator: (type_identifier) @name)) @def.type
|
|
12
|
+
(type_definition declarator: (function_declarator declarator: (parenthesized_declarator (pointer_declarator declarator: (type_identifier) @name)))) @def.type
|
|
13
|
+
(preproc_function_def name: (identifier) @name) @def.macro
|
|
14
|
+
(preproc_def name: (identifier) @name) @def.constant
|
|
15
|
+
(enumerator name: (identifier) @name) @def.constant
|
|
16
|
+
(field_declaration declarator: (field_identifier) @name) @def.field
|
|
17
|
+
(field_declaration declarator: (pointer_declarator declarator: (field_identifier) @name)) @def.field
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const C_REFS = `
|
|
21
|
+
(return_statement (_) @ret)
|
|
22
|
+
(call_expression function: (identifier) @name) @ref.call
|
|
23
|
+
(call_expression function: (field_expression argument: (_) @recv field: (field_identifier) @name)) @ref.call
|
|
24
|
+
(type_identifier) @name @ref.type
|
|
25
|
+
(argument_list (identifier) @name) @ref.value
|
|
26
|
+
(init_declarator value: (identifier) @name) @ref.value
|
|
27
|
+
(initializer_list (identifier) @name) @ref.value
|
|
28
|
+
(preproc_include) @import
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const CPP_DEFS = `
|
|
32
|
+
(function_definition declarator: (function_declarator declarator: (identifier) @name)) @def.function
|
|
33
|
+
(function_definition declarator: (function_declarator declarator: (field_identifier) @name)) @def.method
|
|
34
|
+
(function_definition declarator: (function_declarator declarator: (qualified_identifier scope: (_) @owner name: (identifier) @name))) @def.method
|
|
35
|
+
(function_definition declarator: (function_declarator declarator: (qualified_identifier scope: (_) @owner name: (destructor_name) @name))) @def.method
|
|
36
|
+
(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @def.function
|
|
37
|
+
(function_definition declarator: (reference_declarator (function_declarator declarator: (identifier) @name))) @def.function
|
|
38
|
+
(field_declaration declarator: (function_declarator declarator: (field_identifier) @name)) @def.method
|
|
39
|
+
(declaration declarator: (function_declarator declarator: (identifier) @name)) @def.function
|
|
40
|
+
(class_specifier name: (type_identifier) @name body: (_)) @def.class
|
|
41
|
+
(struct_specifier name: (type_identifier) @name body: (_)) @def.struct
|
|
42
|
+
(union_specifier name: (type_identifier) @name body: (_)) @def.struct
|
|
43
|
+
(enum_specifier name: (type_identifier) @name body: (_)) @def.enum
|
|
44
|
+
(namespace_definition name: (_) @name) @def.module
|
|
45
|
+
(alias_declaration name: (type_identifier) @name) @def.type
|
|
46
|
+
(type_definition declarator: (type_identifier) @name) @def.type
|
|
47
|
+
(preproc_function_def name: (identifier) @name) @def.macro
|
|
48
|
+
(field_declaration declarator: (field_identifier) @name) @def.field
|
|
49
|
+
(enumerator name: (identifier) @name) @def.constant
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
const CPP_REFS = `
|
|
53
|
+
(lambda_expression) @scope
|
|
54
|
+
(return_statement (_) @ret)
|
|
55
|
+
(call_expression function: (identifier) @name) @ref.call
|
|
56
|
+
(call_expression function: (field_expression argument: (_) @recv field: (field_identifier) @name)) @ref.call
|
|
57
|
+
(call_expression function: (qualified_identifier scope: (_) @recv name: (identifier) @name)) @ref.call
|
|
58
|
+
(call_expression function: (template_function name: (identifier) @name)) @ref.call
|
|
59
|
+
(new_expression type: (type_identifier) @name) @ref.new
|
|
60
|
+
(base_class_clause (type_identifier) @name) @ref.inherit
|
|
61
|
+
(base_class_clause (qualified_identifier name: (type_identifier) @name)) @ref.inherit
|
|
62
|
+
(type_identifier) @name @ref.type
|
|
63
|
+
(argument_list (identifier) @name) @ref.value
|
|
64
|
+
(preproc_include) @import
|
|
65
|
+
(declaration type: (type_identifier) @bind.type declarator: (identifier) @bind.name) @bind
|
|
66
|
+
(declaration type: (type_identifier) @bind.type declarator: (init_declarator declarator: (identifier) @bind.name)) @bind
|
|
67
|
+
(parameter_declaration type: (type_identifier) @bind.type declarator: [(identifier) @bind.name (pointer_declarator declarator: (identifier) @bind.name) (reference_declarator (identifier) @bind.name)]) @bind
|
|
68
|
+
(field_declaration type: (type_identifier) @field.type declarator: [(field_identifier) @field.name (pointer_declarator declarator: (field_identifier) @field.name)]) @field
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
const C_BUILTINS = new Set(['printf', 'fprintf', 'sprintf', 'snprintf', 'malloc', 'calloc', 'realloc', 'free', 'memcpy',
|
|
72
|
+
'memset', 'memmove', 'memcmp', 'strlen', 'strcpy', 'strncpy', 'strcmp', 'strncmp', 'strcat', 'strchr', 'strstr',
|
|
73
|
+
'assert', 'sizeof', 'exit', 'abort', 'puts', 'putchar', 'fopen', 'fclose', 'fread', 'fwrite', 'fgets', 'fputs',
|
|
74
|
+
'atoi', 'atof', 'strtol', 'strtod', 'va_start', 'va_end', 'va_arg', 'isdigit', 'isspace', 'isalpha', 'tolower',
|
|
75
|
+
'toupper', 'abs', 'fabs', 'floor', 'ceil', 'pow', 'sqrt', 'static_cast', 'dynamic_cast', 'reinterpret_cast',
|
|
76
|
+
'const_cast', 'move', 'forward', 'make_shared', 'make_unique']);
|
|
77
|
+
|
|
78
|
+
function parseInclude(node) {
|
|
79
|
+
const p = node.childForFieldName('path');
|
|
80
|
+
if (!p) return [];
|
|
81
|
+
if (p.type === 'system_lib_string') return [{ source: p.text.replace(/^<|>$/g, ''), imported: '*', local: null, system: true }];
|
|
82
|
+
return [{ source: p.text.replace(/^"|"$/g, ''), imported: '*', local: null }];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function cVisibility(node) {
|
|
86
|
+
return node.namedChildren.some(c => c.type === 'storage_class_specifier' && c.text === 'static') ? 'private' : null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const common = {
|
|
90
|
+
implicitThis: false,
|
|
91
|
+
selfNames: ['this'],
|
|
92
|
+
externalReceivers: new Set(['std']),
|
|
93
|
+
builtinCalls: C_BUILTINS,
|
|
94
|
+
testFile: /(^|\/)(tests?|test_\w+)\/|_test\.(c|cc|cpp)$|(^|\/)test_[^/]*\.(c|cc|cpp)$/,
|
|
95
|
+
commentTypes: ['comment'],
|
|
96
|
+
parseImport: parseInclude,
|
|
97
|
+
isExported: (node) => cVisibility(node) !== 'private',
|
|
98
|
+
visibility: cVisibility,
|
|
99
|
+
isPrimitiveType: (t) => /^(int|char|void|float|double|long|short|unsigned|signed|bool|size_t|u?int\d+_t|string|auto)$/.test(t),
|
|
100
|
+
bodyField: 'body',
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const c = {
|
|
104
|
+
...common,
|
|
105
|
+
id: 'c',
|
|
106
|
+
grammar: 'c',
|
|
107
|
+
extensions: ['.c', '.h'],
|
|
108
|
+
family: 'c',
|
|
109
|
+
query: C_DEFS + C_REFS,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const cpp = {
|
|
113
|
+
...common,
|
|
114
|
+
id: 'cpp',
|
|
115
|
+
grammar: 'cpp',
|
|
116
|
+
extensions: ['.cc', '.cpp', '.cxx', '.hpp', '.hh', '.hxx', '.h++', '.c++', '.ipp', '.inl'],
|
|
117
|
+
family: 'c',
|
|
118
|
+
implicitThis: true,
|
|
119
|
+
query: CPP_DEFS + CPP_REFS,
|
|
120
|
+
cleanType: (t) => t.replace(/\b(std|boost)::/g, ''),
|
|
121
|
+
transparentTypes: new Set(['unique_ptr', 'shared_ptr', 'weak_ptr', 'optional', 'reference_wrapper', 'atomic']),
|
|
122
|
+
elementTypes: new Set(['vector', 'list', 'deque', 'set', 'unordered_set', 'multiset', 'array', 'span', 'forward_list']),
|
|
123
|
+
elementMethods: new Set(['at', 'front', 'back', 'top']),
|
|
124
|
+
mapTypes: new Set(['map', 'unordered_map', 'multimap', 'unordered_multimap']),
|
|
125
|
+
mapMethods: new Set(['at']),
|
|
126
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/** Python extraction spec. See ../extract.mjs for the capture convention. */
|
|
2
|
+
|
|
3
|
+
const QUERY = `
|
|
4
|
+
(function_definition name: (identifier) @name return_type: (type) @type) @def.function
|
|
5
|
+
(function_definition name: (identifier) @name) @def.function
|
|
6
|
+
(class_definition name: (identifier) @name) @def.class
|
|
7
|
+
(module (expression_statement (assignment left: (identifier) @name)) @def.variable)
|
|
8
|
+
(class_definition body: (block (expression_statement (assignment left: (identifier) @name type: (type) @type)) @def.field))
|
|
9
|
+
(class_definition body: (block (expression_statement (assignment left: (identifier) @name)) @def.field))
|
|
10
|
+
(expression_statement (assignment left: (attribute object: (identifier) @_self attribute: (identifier) @name) (#eq? @_self "self")) @def.field)
|
|
11
|
+
|
|
12
|
+
(call function: (identifier) @name) @ref.call
|
|
13
|
+
(call function: (attribute object: (_) @recv attribute: (identifier) @name)) @ref.call
|
|
14
|
+
(class_definition superclasses: (argument_list (identifier) @name)) @ref.inherit
|
|
15
|
+
(class_definition superclasses: (argument_list (attribute object: (_) @recv attribute: (identifier) @name))) @ref.inherit
|
|
16
|
+
(decorator (identifier) @name) @ref.decorator
|
|
17
|
+
(decorator (attribute object: (_) @recv attribute: (identifier) @name)) @ref.decorator
|
|
18
|
+
(decorator (call function: (identifier) @name)) @ref.decorator
|
|
19
|
+
(decorator (call function: (attribute object: (_) @recv attribute: (identifier) @name))) @ref.decorator
|
|
20
|
+
(type (identifier) @name) @ref.type
|
|
21
|
+
(type (attribute object: (_) @recv attribute: (identifier) @name)) @ref.type
|
|
22
|
+
(type (generic_type (identifier) @name)) @ref.type
|
|
23
|
+
(type (generic_type (type_parameter (type (identifier) @name)))) @ref.type
|
|
24
|
+
(type (string (string_content) @name)) @ref.type
|
|
25
|
+
(argument_list (identifier) @name) @ref.value
|
|
26
|
+
(keyword_argument value: (identifier) @name) @ref.value
|
|
27
|
+
(list (identifier) @name) @ref.value
|
|
28
|
+
(pair value: (identifier) @name) @ref.value
|
|
29
|
+
(assignment right: (identifier) @name) @ref.value
|
|
30
|
+
(attribute object: (_) @recv attribute: (identifier) @name) @ref.read
|
|
31
|
+
|
|
32
|
+
[(lambda) (list_comprehension) (set_comprehension) (dictionary_comprehension) (generator_expression)] @scope
|
|
33
|
+
(return_statement (_) @ret)
|
|
34
|
+
(import_statement) @import
|
|
35
|
+
(import_from_statement) @import
|
|
36
|
+
|
|
37
|
+
(assignment left: (identifier) @bind.name right: (_) @bind.expr) @bind
|
|
38
|
+
(assignment left: (identifier) @bind.name type: (type) @bind.type) @bind
|
|
39
|
+
(typed_parameter (identifier) @bind.name type: (type) @bind.type) @bind
|
|
40
|
+
(typed_default_parameter name: (identifier) @bind.name type: (type) @bind.type) @bind
|
|
41
|
+
(for_statement left: (identifier) @bind.name right: (_) @bind.elem) @bind
|
|
42
|
+
(for_in_clause left: (identifier) @bind.name right: (_) @bind.elem) @bind
|
|
43
|
+
(with_item value: (as_pattern (_) @bind.expr alias: (as_pattern_target (identifier) @bind.name))) @bind
|
|
44
|
+
(assignment left: (attribute object: (identifier) @_self attribute: (identifier) @field.name) right: (_) @field.expr (#eq? @_self "self")) @field
|
|
45
|
+
(assignment left: (attribute object: (identifier) @_self attribute: (identifier) @field.name) type: (type) @field.type (#eq? @_self "self")) @field
|
|
46
|
+
(class_definition body: (block (expression_statement (assignment left: (identifier) @field.name type: (type) @field.type)) @field))
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const BUILTIN_CALLS = new Set([
|
|
50
|
+
'print', 'len', 'range', 'isinstance', 'issubclass', 'hasattr', 'getattr', 'setattr', 'delattr', 'super',
|
|
51
|
+
'str', 'int', 'float', 'bool', 'list', 'dict', 'set', 'tuple', 'frozenset', 'bytes', 'bytearray', 'type',
|
|
52
|
+
'object', 'enumerate', 'zip', 'map', 'filter', 'sorted', 'reversed', 'min', 'max', 'sum', 'any', 'all',
|
|
53
|
+
'abs', 'round', 'repr', 'hash', 'id', 'iter', 'next', 'open', 'callable', 'vars', 'dir', 'format',
|
|
54
|
+
'staticmethod', 'classmethod', 'property', 'NotImplementedError', 'ValueError', 'TypeError', 'KeyError',
|
|
55
|
+
'RuntimeError', 'Exception', 'AttributeError', 'IndexError', 'StopIteration', 'AssertionError', 'OSError',
|
|
56
|
+
'IOError', 'ImportError', 'NameError', 'ZeroDivisionError', 'PermissionError', 'FileNotFoundError',
|
|
57
|
+
]);
|
|
58
|
+
const EXTERNAL_RECEIVERS = new Set(['os', 'sys', 're', 'json', 'math', 'time', 'datetime', 'logging', 'logger',
|
|
59
|
+
'log', 'typing', 'collections', 'itertools', 'functools', 'asyncio', 'subprocess', 'shutil', 'pathlib', 'random',
|
|
60
|
+
'np', 'pd', 'torch', 'tf', 'pytest', 'unittest', 'mock', 'warnings', 'inspect', 'copy', 'pickle', 'uuid', 'base64',
|
|
61
|
+
'hashlib', 'threading', 'contextlib', 'dataclasses', 'enum', 'abc', 'io', 'tempfile', 'glob', 'string', 'decimal']);
|
|
62
|
+
const PRIMITIVES = new Set(['str', 'int', 'float', 'bool', 'bytes', 'None', 'Any', 'object', 'list', 'dict', 'set',
|
|
63
|
+
'tuple', 'List', 'Dict', 'Set', 'Tuple', 'Optional', 'Union', 'Callable', 'Iterable', 'Iterator', 'Sequence',
|
|
64
|
+
'Mapping', 'Type', 'Generator', 'AsyncGenerator', 'Awaitable', 'Coroutine', 'Literal', 'ClassVar', 'Self']);
|
|
65
|
+
|
|
66
|
+
function stripDocString(t) {
|
|
67
|
+
return t.replace(/^[rRbBuUfF]*("""|'''|"|')/, '').replace(/("""|'''|"|')$/, '')
|
|
68
|
+
.split('\n').map(l => l.trim()).filter(Boolean).join(' ');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function docOf(defNode) {
|
|
72
|
+
const body = defNode.childForFieldName('body');
|
|
73
|
+
const first = body?.namedChild(0);
|
|
74
|
+
if (first?.type === 'expression_statement') {
|
|
75
|
+
const s = first.namedChild(0);
|
|
76
|
+
if (s?.type === 'string') return stripDocString(s.text);
|
|
77
|
+
}
|
|
78
|
+
return null; // fall back to comments above
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function dotted(node) { return node ? node.text.replace(/\s+/g, '') : null; }
|
|
82
|
+
|
|
83
|
+
function parseImport(node) {
|
|
84
|
+
const out = [];
|
|
85
|
+
if (node.type === 'import_statement') {
|
|
86
|
+
for (const c of node.namedChildren) {
|
|
87
|
+
if (c.type === 'dotted_name') {
|
|
88
|
+
const mod = dotted(c);
|
|
89
|
+
out.push({ source: mod, imported: '*', local: mod });
|
|
90
|
+
} else if (c.type === 'aliased_import') {
|
|
91
|
+
const mod = dotted(c.childForFieldName('name'));
|
|
92
|
+
out.push({ source: mod, imported: '*', local: c.childForFieldName('alias')?.text || mod });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} else if (node.type === 'import_from_statement') {
|
|
96
|
+
const modNode = node.childForFieldName('module_name');
|
|
97
|
+
const source = dotted(modNode) || '.';
|
|
98
|
+
let any = false;
|
|
99
|
+
for (const c of node.namedChildren) {
|
|
100
|
+
if (c === modNode || c.id === modNode?.id) continue;
|
|
101
|
+
if (c.type === 'dotted_name') { const n = dotted(c); out.push({ source, imported: n, local: n.split('.').pop() }); any = true; }
|
|
102
|
+
else if (c.type === 'aliased_import') {
|
|
103
|
+
const n = dotted(c.childForFieldName('name'));
|
|
104
|
+
out.push({ source, imported: n, local: c.childForFieldName('alias')?.text || n }); any = true;
|
|
105
|
+
} else if (c.type === 'wildcard_import') { out.push({ source, imported: '*', local: null, wildcard: true }); any = true; }
|
|
106
|
+
}
|
|
107
|
+
if (!any) out.push({ source, imported: null, local: null });
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isModuleLevel(node) {
|
|
113
|
+
// (module (expression_statement (assignment)))
|
|
114
|
+
return node.parent?.type === 'module';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const python = {
|
|
118
|
+
id: 'python',
|
|
119
|
+
// `self.x = …` inside a method declares an instance attribute of the class (first assignment wins)
|
|
120
|
+
hoistMemberFields: true,
|
|
121
|
+
grammar: 'python',
|
|
122
|
+
extensions: ['.py', '.pyi'],
|
|
123
|
+
family: 'python',
|
|
124
|
+
query: QUERY,
|
|
125
|
+
implicitThis: false,
|
|
126
|
+
selfNames: ['self', 'cls'],
|
|
127
|
+
externalReceivers: EXTERNAL_RECEIVERS,
|
|
128
|
+
builtinCalls: BUILTIN_CALLS,
|
|
129
|
+
testFile: /(^|\/)(tests?|testing)\/|(^|\/)test_[^/]*\.py$|_test\.py$|(^|\/)conftest\.py$/,
|
|
130
|
+
commentTypes: ['comment'],
|
|
131
|
+
docWrappers: new Set(['decorated_definition']),
|
|
132
|
+
docOf,
|
|
133
|
+
parseImport,
|
|
134
|
+
isModuleLevel,
|
|
135
|
+
isExported: (node, name) => !name.startsWith('_') || /^__\w+__$/.test(name),
|
|
136
|
+
visibility: (node, name) => (name && name.startsWith('_') && !/^__\w+__$/.test(name) ? 'private' : null),
|
|
137
|
+
isPrimitiveType: (t) => PRIMITIVES.has(t),
|
|
138
|
+
isStatic: (node) => node.parent?.type === 'decorated_definition' && node.parent.namedChildren.some(c => c.type === 'decorator' && /^@(staticmethod|classmethod)\b/.test(c.text)),
|
|
139
|
+
transparentTypes: new Set(['Optional', 'Final', 'ClassVar', 'Annotated', 'Type', 'type', 'Awaitable', 'Required', 'NotRequired', 'ReadOnly']),
|
|
140
|
+
elementTypes: new Set(['list', 'List', 'Sequence', 'MutableSequence', 'Iterable', 'Iterator', 'AsyncIterable', 'AsyncIterator',
|
|
141
|
+
'Generator', 'AsyncGenerator', 'set', 'Set', 'frozenset', 'FrozenSet', 'AbstractSet', 'MutableSet', 'Collection', 'Deque', 'deque', 'tuple', 'Tuple']),
|
|
142
|
+
elementMethods: new Set(['pop', 'popleft']),
|
|
143
|
+
mapTypes: new Set(['dict', 'Dict', 'Mapping', 'MutableMapping', 'DefaultDict', 'defaultdict', 'OrderedDict']),
|
|
144
|
+
mapMethods: new Set(['get', 'pop', 'setdefault']),
|
|
145
|
+
mapValueMethods: new Set(['values']),
|
|
146
|
+
decoratorsOf(node) {
|
|
147
|
+
const p = node.parent;
|
|
148
|
+
if (p?.type !== 'decorated_definition') return [];
|
|
149
|
+
return p.namedChildren.filter(c => c.type === 'decorator').map(d => d.text.replace(/^@/, '').split('(')[0].trim()).slice(0, 8);
|
|
150
|
+
},
|
|
151
|
+
bodyField: 'body',
|
|
152
|
+
signatureCleanup: (text) => text.replace(/:$/, ''),
|
|
153
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/** Rust extraction spec. `impl Type { fn m() }` methods are qualified as Type.m. */
|
|
2
|
+
|
|
3
|
+
const TH = (cap) => `[(type_identifier) @${cap} (generic_type type: (type_identifier) @${cap}) (scoped_type_identifier name: (type_identifier) @${cap}) (reference_type type: (type_identifier) @${cap}) (reference_type type: (generic_type type: (type_identifier) @${cap}))]`;
|
|
4
|
+
// a whole type (normalizeType unwraps references, Box/Rc/Arc/Option/Result, and sees Vec<T> as T[])
|
|
5
|
+
const TW = (cap) => `[(type_identifier) (generic_type) (scoped_type_identifier) (reference_type) (array_type) (pointer_type)] @${cap}`;
|
|
6
|
+
|
|
7
|
+
const QUERY = `
|
|
8
|
+
(function_item name: (identifier) @name return_type: ${TW('type')}) @def.function
|
|
9
|
+
(function_item name: (identifier) @name) @def.function
|
|
10
|
+
(function_signature_item name: (identifier) @name return_type: ${TW('type')}) @def.function
|
|
11
|
+
(function_signature_item name: (identifier) @name) @def.function
|
|
12
|
+
(struct_item name: (type_identifier) @name) @def.struct
|
|
13
|
+
(enum_item name: (type_identifier) @name) @def.enum
|
|
14
|
+
(union_item name: (type_identifier) @name) @def.struct
|
|
15
|
+
(trait_item name: (type_identifier) @name) @def.trait
|
|
16
|
+
(type_item name: (type_identifier) @name) @def.type
|
|
17
|
+
(const_item name: (identifier) @name) @def.constant
|
|
18
|
+
(static_item name: (identifier) @name) @def.constant
|
|
19
|
+
(mod_item name: (identifier) @name body: (_)) @def.module
|
|
20
|
+
(macro_definition name: (identifier) @name) @def.macro
|
|
21
|
+
(field_declaration name: (field_identifier) @name type: ${TW('type')}) @def.field
|
|
22
|
+
(field_declaration name: (field_identifier) @name) @def.field
|
|
23
|
+
(enum_variant name: (identifier) @name) @def.constant
|
|
24
|
+
|
|
25
|
+
(call_expression function: (identifier) @name) @ref.call
|
|
26
|
+
(call_expression function: (field_expression value: (_) @recv field: (field_identifier) @name)) @ref.call
|
|
27
|
+
(call_expression function: (scoped_identifier path: (_) @recv name: (identifier) @name)) @ref.call
|
|
28
|
+
(call_expression function: (generic_function function: (identifier) @name)) @ref.call
|
|
29
|
+
(call_expression function: (generic_function function: (scoped_identifier path: (_) @recv name: (identifier) @name))) @ref.call
|
|
30
|
+
(call_expression function: (generic_function function: (field_expression value: (_) @recv field: (field_identifier) @name))) @ref.call
|
|
31
|
+
(macro_invocation macro: (identifier) @name) @ref.call
|
|
32
|
+
(struct_expression name: (type_identifier) @name) @ref.new
|
|
33
|
+
(struct_expression name: (scoped_type_identifier path: (_) @recv name: (type_identifier) @name)) @ref.new
|
|
34
|
+
(type_identifier) @name @ref.type
|
|
35
|
+
(impl_item trait: ${TH('name')}) @ref.inherit
|
|
36
|
+
(trait_item bounds: (trait_bounds ${TH('name')})) @ref.inherit
|
|
37
|
+
(arguments (identifier) @name) @ref.value
|
|
38
|
+
(arguments (scoped_identifier path: (_) @recv name: (identifier) @name)) @ref.value
|
|
39
|
+
|
|
40
|
+
(closure_expression) @scope
|
|
41
|
+
(return_expression (_) @ret)
|
|
42
|
+
(function_item body: (block [(call_expression) (struct_expression) (field_expression) (identifier) (self) (reference_expression) (try_expression) (scoped_identifier)] @ret .))
|
|
43
|
+
(use_declaration) @import
|
|
44
|
+
|
|
45
|
+
(let_declaration pattern: (identifier) @bind.name type: ${TW('bind.type')}) @bind
|
|
46
|
+
(let_declaration pattern: (mut_pattern (identifier) @bind.name) type: ${TW('bind.type')}) @bind
|
|
47
|
+
(let_declaration pattern: (identifier) @bind.name value: (_) @bind.expr) @bind
|
|
48
|
+
(let_declaration pattern: (mut_pattern (identifier) @bind.name) value: (_) @bind.expr) @bind
|
|
49
|
+
(for_expression pattern: (identifier) @bind.name value: (_) @bind.elem) @bind
|
|
50
|
+
(let_declaration pattern: (identifier) @bind.name value: (struct_expression name: (type_identifier) @bind.new)) @bind
|
|
51
|
+
(let_declaration pattern: (identifier) @bind.name value: (call_expression function: (scoped_identifier path: (identifier) @bind.new name: (identifier) @_ctor))) @bind
|
|
52
|
+
(let_declaration pattern: (mut_pattern (identifier) @bind.name) value: (call_expression function: (scoped_identifier path: (identifier) @bind.new name: (identifier) @_ctor))) @bind
|
|
53
|
+
(let_declaration pattern: (identifier) @bind.name value: (call_expression function: (identifier) @bind.call)) @bind
|
|
54
|
+
(parameter pattern: (identifier) @bind.name type: ${TW('bind.type')}) @bind
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
const PRIMITIVES = new Set(['i8', 'i16', 'i32', 'i64', 'i128', 'isize', 'u8', 'u16', 'u32', 'u64', 'u128', 'usize',
|
|
58
|
+
'f32', 'f64', 'bool', 'char', 'str', 'String', 'Option', 'Result', 'Vec', 'Box', 'Rc', 'Arc', 'RefCell',
|
|
59
|
+
'Cell', 'HashMap', 'HashSet', 'BTreeMap', 'BTreeSet', 'Cow', 'Mutex', 'RwLock', 'Pin', 'PhantomData']);
|
|
60
|
+
const BUILTIN_MACROS = new Set(['println', 'print', 'eprintln', 'eprint', 'format', 'vec', 'panic', 'assert',
|
|
61
|
+
'assert_eq', 'assert_ne', 'debug_assert', 'debug_assert_eq', 'write', 'writeln', 'unreachable', 'unimplemented',
|
|
62
|
+
'todo', 'matches', 'include_str', 'include_bytes', 'concat', 'stringify', 'env', 'cfg', 'dbg', 'format_args', 'Ok',
|
|
63
|
+
'Err', 'Some', 'None', 'Box', 'Default', 'drop', 'Into', 'From']);
|
|
64
|
+
|
|
65
|
+
function implOwner(node) {
|
|
66
|
+
// function_item inside (impl_item body: (declaration_list ...))
|
|
67
|
+
const list = node.parent;
|
|
68
|
+
const impl = list?.parent;
|
|
69
|
+
if (list?.type === 'declaration_list' && impl?.type === 'impl_item') {
|
|
70
|
+
const t = impl.childForFieldName('type');
|
|
71
|
+
if (!t) return null;
|
|
72
|
+
if (t.type === 'type_identifier') return t.text;
|
|
73
|
+
const inner = t.childForFieldName('type') ?? t.childForFieldName('name');
|
|
74
|
+
return inner?.type === 'type_identifier' ? inner.text : t.text.replace(/<.*$/s, '').split('::').pop();
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function flattenUse(node, prefix, out) {
|
|
80
|
+
switch (node.type) {
|
|
81
|
+
case 'scoped_identifier': case 'identifier': case 'crate': case 'self': case 'super': {
|
|
82
|
+
const full = (prefix ? prefix + '::' : '') + node.text;
|
|
83
|
+
const name = full.split('::').pop();
|
|
84
|
+
out.push({ source: full.split('::').slice(0, -1).join('::'), imported: name, local: name === 'self' ? full.split('::').slice(-2, -1)[0] : name });
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case 'use_as_clause': {
|
|
88
|
+
const p = node.childForFieldName('path');
|
|
89
|
+
const full = (prefix ? prefix + '::' : '') + (p?.text ?? '');
|
|
90
|
+
out.push({ source: full.split('::').slice(0, -1).join('::'), imported: full.split('::').pop(), local: node.childForFieldName('alias')?.text });
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case 'use_wildcard': {
|
|
94
|
+
const inner = node.namedChildren[0];
|
|
95
|
+
out.push({ source: (prefix ? prefix + '::' : '') + (inner?.text ?? ''), imported: '*', local: null, wildcard: true });
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case 'scoped_use_list': {
|
|
99
|
+
const p = node.childForFieldName('path');
|
|
100
|
+
const np = (prefix ? prefix + '::' : '') + (p?.text ?? '');
|
|
101
|
+
const list = node.childForFieldName('list');
|
|
102
|
+
for (const c of list?.namedChildren ?? []) flattenUse(c, np, out);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case 'use_list':
|
|
106
|
+
for (const c of node.namedChildren) flattenUse(c, prefix, out);
|
|
107
|
+
break;
|
|
108
|
+
default: break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function parseImport(node) {
|
|
113
|
+
const arg = node.childForFieldName('argument');
|
|
114
|
+
const out = [];
|
|
115
|
+
if (arg) flattenUse(arg, '', out);
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function visibility(node) {
|
|
120
|
+
const v = node.namedChildren.find(c => c.type === 'visibility_modifier');
|
|
121
|
+
return v ? 'public' : 'private';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const rust = {
|
|
125
|
+
id: 'rust',
|
|
126
|
+
grammar: 'rust',
|
|
127
|
+
extensions: ['.rs'],
|
|
128
|
+
family: 'rust',
|
|
129
|
+
query: QUERY,
|
|
130
|
+
implicitThis: false,
|
|
131
|
+
selfNames: ['self'],
|
|
132
|
+
externalReceivers: new Set(['std', 'core', 'alloc', 'fmt', 'io', 'mem', 'ptr', 'env', 'fs', 'thread', 'log', 'tracing']),
|
|
133
|
+
builtinCalls: BUILTIN_MACROS,
|
|
134
|
+
testFile: /(^|\/)(tests|benches)\/|_test\.rs$/,
|
|
135
|
+
commentTypes: ['line_comment', 'block_comment'],
|
|
136
|
+
skipBeforeDoc: new Set(['attribute_item', 'inner_attribute_item']),
|
|
137
|
+
parseImport,
|
|
138
|
+
ownerOf: implOwner,
|
|
139
|
+
refineKind(kind, d, parent) {
|
|
140
|
+
if (kind === 'function' && implOwner(d.node)) return 'method';
|
|
141
|
+
return kind;
|
|
142
|
+
},
|
|
143
|
+
isExported: (node) => node.namedChildren.some(c => c.type === 'visibility_modifier') || node.parent?.parent?.type === 'trait_item',
|
|
144
|
+
visibility,
|
|
145
|
+
isPrimitiveType: (t) => PRIMITIVES.has(t),
|
|
146
|
+
transparentTypes: new Set(['Box', 'Rc', 'Arc', 'Cow', 'RefCell', 'Cell', 'Mutex', 'RwLock', 'MutexGuard', 'RwLockReadGuard', 'RwLockWriteGuard', 'Ref', 'RefMut', 'Pin', 'Option', 'Result', 'Weak']),
|
|
147
|
+
elementTypes: new Set(['Vec', 'VecDeque', 'HashSet', 'BTreeSet', 'BinaryHeap', 'LinkedList', 'IntoIter', 'Iter', 'IterMut', 'Drain']),
|
|
148
|
+
elementMethods: new Set(['first', 'last', 'get', 'get_mut', 'first_mut', 'last_mut', 'pop', 'pop_front', 'pop_back', 'front', 'back', 'remove', 'swap_remove', 'next', 'peek', 'find']),
|
|
149
|
+
mapTypes: new Set(['HashMap', 'BTreeMap', 'IndexMap', 'DashMap']),
|
|
150
|
+
mapMethods: new Set(['get', 'get_mut', 'remove', 'insert']),
|
|
151
|
+
mapValueMethods: new Set(['values', 'values_mut', 'into_values']),
|
|
152
|
+
// calls that hand back (a view of) the same value: unwrap, clone, borrow, lock, iter …
|
|
153
|
+
identityMethods: new Set(['unwrap', 'expect', 'unwrap_or_default', 'unwrap_or', 'unwrap_or_else', 'as_ref', 'as_mut', 'as_deref', 'as_deref_mut',
|
|
154
|
+
'clone', 'borrow', 'borrow_mut', 'lock', 'read', 'write', 'to_owned', 'deref', 'deref_mut', 'cloned', 'copied', 'iter', 'iter_mut', 'into_iter', 'drain', 'upgrade']),
|
|
155
|
+
normalizeRefName: (name, r) => (r.node.type === 'macro_invocation' ? (BUILTIN_MACROS.has(name) ? null : name) : name),
|
|
156
|
+
bodyField: 'body',
|
|
157
|
+
};
|