gitnexus 1.6.6-rc.101 → 1.6.6-rc.103
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/dist/core/ingestion/export-detection.js +0 -5
- package/dist/core/ingestion/field-extractors/configs/dart.js +1 -4
- package/dist/core/ingestion/field-extractors/configs/php.js +1 -2
- package/dist/core/ingestion/field-extractors/configs/swift.js +1 -1
- package/dist/core/ingestion/field-extractors/typescript.js +0 -29
- package/dist/core/ingestion/languages/c/captures.js +12 -10
- package/dist/core/ingestion/languages/c/query.js +6 -0
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +2 -8
- package/dist/core/ingestion/languages/cpp/captures.js +11 -9
- package/dist/core/ingestion/languages/cpp/query.js +12 -0
- package/dist/core/ingestion/languages/csharp/captures.js +3 -1
- package/dist/core/ingestion/languages/java/captures.js +4 -1
- package/dist/core/ingestion/languages/php/import-decomposer.js +2 -33
- package/dist/core/ingestion/languages/php/receiver-binding.js +8 -4
- package/dist/core/ingestion/languages/python/depends-references.js +1 -1
- package/dist/core/ingestion/languages/ruby/captures.js +2 -2
- package/dist/core/ingestion/languages/rust/range-binding.js +2 -3
- package/dist/core/ingestion/languages/typescript/receiver-binding.js +0 -1
- package/dist/core/ingestion/method-extractors/configs/dart.js +0 -1
- package/dist/core/ingestion/method-extractors/configs/php.js +0 -1
- package/dist/core/ingestion/parsing-processor.js +4 -1
- package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/core/ingestion/tree-sitter-queries.js +18 -0
- package/dist/core/ingestion/type-env.js +0 -2
- package/dist/core/ingestion/type-extractors/c-cpp.js +8 -10
- package/dist/core/ingestion/type-extractors/csharp.js +18 -34
- package/dist/core/ingestion/type-extractors/go.js +2 -10
- package/dist/core/ingestion/type-extractors/jvm.js +6 -5
- package/dist/core/ingestion/type-extractors/php.js +1 -1
- package/dist/core/ingestion/type-extractors/python.js +1 -1
- package/dist/core/ingestion/type-extractors/ruby.js +2 -2
- package/dist/core/ingestion/type-extractors/rust.js +0 -16
- package/dist/core/ingestion/type-extractors/shared.d.ts +2 -2
- package/dist/core/ingestion/type-extractors/shared.js +25 -11
- package/dist/core/ingestion/type-extractors/swift.js +5 -5
- package/dist/core/ingestion/type-extractors/typescript.js +1 -1
- package/dist/core/ingestion/utils/ast-helpers.d.ts +9 -0
- package/dist/core/ingestion/utils/ast-helpers.js +26 -0
- package/dist/core/ingestion/variable-extractors/configs/dart.js +0 -9
- package/dist/core/ingestion/workers/parse-worker.js +4 -1
- package/package.json +1 -1
|
@@ -62,11 +62,6 @@ const CSHARP_DECL_TYPES = new Set([
|
|
|
62
62
|
'struct_declaration',
|
|
63
63
|
'enum_declaration',
|
|
64
64
|
'record_declaration',
|
|
65
|
-
// tree-sitter-c-sharp absorbs 'record struct' and 'record class' into
|
|
66
|
-
// record_declaration — these two node types are listed defensively but
|
|
67
|
-
// never emitted by the grammar in practice (verified against ^0.23.1).
|
|
68
|
-
'record_struct_declaration',
|
|
69
|
-
'record_class_declaration',
|
|
70
65
|
'delegate_declaration',
|
|
71
66
|
'property_declaration',
|
|
72
67
|
'field_declaration',
|
|
@@ -42,10 +42,7 @@ export const dartConfig = {
|
|
|
42
42
|
// declaration > type_identifier (first named child usually)
|
|
43
43
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
44
44
|
const child = node.namedChild(i);
|
|
45
|
-
if (child &&
|
|
46
|
-
(child.type === 'type_identifier' ||
|
|
47
|
-
child.type === 'generic_type' ||
|
|
48
|
-
child.type === 'function_type')) {
|
|
45
|
+
if (child && (child.type === 'type_identifier' || child.type === 'function_type')) {
|
|
49
46
|
return extractSimpleTypeName(child) ?? child.text?.trim();
|
|
50
47
|
}
|
|
51
48
|
}
|
|
@@ -46,8 +46,7 @@ export const phpConfig = {
|
|
|
46
46
|
child.type === 'named_type' ||
|
|
47
47
|
child.type === 'optional_type' ||
|
|
48
48
|
child.type === 'primitive_type' ||
|
|
49
|
-
child.type === 'intersection_type'
|
|
50
|
-
child.type === 'nullable_type') {
|
|
49
|
+
child.type === 'intersection_type') {
|
|
51
50
|
return extractSimpleTypeName(child) ?? child.text?.trim();
|
|
52
51
|
}
|
|
53
52
|
}
|
|
@@ -17,7 +17,7 @@ const SWIFT_VIS = new Set([
|
|
|
17
17
|
*/
|
|
18
18
|
export const swiftConfig = {
|
|
19
19
|
language: SupportedLanguages.Swift,
|
|
20
|
-
typeDeclarationNodes: ['class_declaration', '
|
|
20
|
+
typeDeclarationNodes: ['class_declaration', 'protocol_declaration'],
|
|
21
21
|
fieldNodeTypes: ['property_declaration'],
|
|
22
22
|
bodyNodeTypes: ['class_body', 'protocol_body'],
|
|
23
23
|
defaultVisibility: 'internal',
|
|
@@ -70,17 +70,6 @@ export class TypeScriptFieldExtractor extends BaseFieldExtractor {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
// Check for modifier node (tree-sitter typescript may group these)
|
|
74
|
-
const modifiers = node.childForFieldName('modifiers');
|
|
75
|
-
if (modifiers) {
|
|
76
|
-
for (let i = 0; i < modifiers.childCount; i++) {
|
|
77
|
-
const modifier = modifiers.child(i);
|
|
78
|
-
const modText = modifier?.text.trim();
|
|
79
|
-
if (modText && TypeScriptFieldExtractor.VISIBILITY_MODIFIERS.has(modText)) {
|
|
80
|
-
return modText;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
73
|
// TypeScript class members are public by default
|
|
85
74
|
return 'public';
|
|
86
75
|
}
|
|
@@ -94,15 +83,6 @@ export class TypeScriptFieldExtractor extends BaseFieldExtractor {
|
|
|
94
83
|
return true;
|
|
95
84
|
}
|
|
96
85
|
}
|
|
97
|
-
const modifiers = node.childForFieldName('modifiers');
|
|
98
|
-
if (modifiers) {
|
|
99
|
-
for (let i = 0; i < modifiers.childCount; i++) {
|
|
100
|
-
const modifier = modifiers.child(i);
|
|
101
|
-
if (modifier && modifier.text === 'static') {
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
86
|
return false;
|
|
107
87
|
}
|
|
108
88
|
/**
|
|
@@ -115,15 +95,6 @@ export class TypeScriptFieldExtractor extends BaseFieldExtractor {
|
|
|
115
95
|
return true;
|
|
116
96
|
}
|
|
117
97
|
}
|
|
118
|
-
const modifiers = node.childForFieldName('modifiers');
|
|
119
|
-
if (modifiers) {
|
|
120
|
-
for (let i = 0; i < modifiers.childCount; i++) {
|
|
121
|
-
const modifier = modifiers.child(i);
|
|
122
|
-
if (modifier && modifier.text === 'readonly') {
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
98
|
return false;
|
|
128
99
|
}
|
|
129
100
|
/**
|
|
@@ -14,9 +14,9 @@ export function emitCScopeCaptures(sourceText, filePath, cachedTree) {
|
|
|
14
14
|
}
|
|
15
15
|
const rawMatches = getCScopeQuery().matches(tree.rootNode);
|
|
16
16
|
const out = [];
|
|
17
|
-
// Track ranges where typedef-struct/union was captured as
|
|
18
|
-
// so we can suppress the duplicate @declaration.typedef match
|
|
19
|
-
const
|
|
17
|
+
// Track ranges where typedef-struct/union/enum was captured as its concrete
|
|
18
|
+
// type so we can suppress the duplicate @declaration.typedef match.
|
|
19
|
+
const concreteTypedefRanges = new Set();
|
|
20
20
|
for (const m of rawMatches) {
|
|
21
21
|
const grouped = {};
|
|
22
22
|
for (const c of m.captures) {
|
|
@@ -39,18 +39,20 @@ export function emitCScopeCaptures(sourceText, filePath, cachedTree) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
// Track typedef
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
// Track typedef struct/union/enum ranges to suppress duplicate typedef declarations
|
|
43
|
+
const concreteTypeAnchor = grouped['@declaration.struct'] ??
|
|
44
|
+
grouped['@declaration.union'] ??
|
|
45
|
+
grouped['@declaration.enum'];
|
|
46
|
+
if (concreteTypeAnchor !== undefined) {
|
|
47
|
+
const r = concreteTypeAnchor.range;
|
|
48
|
+
concreteTypedefRanges.add(`${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`);
|
|
47
49
|
}
|
|
48
|
-
// Suppress @declaration.typedef if the same range was already captured as
|
|
50
|
+
// Suppress @declaration.typedef if the same range was already captured as a concrete type.
|
|
49
51
|
const typedefAnchor = grouped['@declaration.typedef'];
|
|
50
52
|
if (typedefAnchor !== undefined) {
|
|
51
53
|
const r = typedefAnchor.range;
|
|
52
54
|
const key = `${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`;
|
|
53
|
-
if (
|
|
55
|
+
if (concreteTypedefRanges.has(key))
|
|
54
56
|
continue;
|
|
55
57
|
}
|
|
56
58
|
// Enrich function declarations with arity metadata and detect static linkage
|
|
@@ -40,6 +40,12 @@ const C_SCOPE_QUERY = `
|
|
|
40
40
|
(enum_specifier
|
|
41
41
|
name: (type_identifier) @declaration.name) @declaration.enum
|
|
42
42
|
|
|
43
|
+
;; Declarations — enum (typedef enum { ... } Name)
|
|
44
|
+
(type_definition
|
|
45
|
+
type: (enum_specifier
|
|
46
|
+
body: (enumerator_list))
|
|
47
|
+
declarator: (type_identifier) @declaration.name) @declaration.enum
|
|
48
|
+
|
|
43
49
|
;; Declarations — function definition
|
|
44
50
|
(function_definition
|
|
45
51
|
declarator: (function_declarator
|
|
@@ -23,7 +23,6 @@ export function computeCppDeclarationArity(node) {
|
|
|
23
23
|
continue;
|
|
24
24
|
if (child.type === 'parameter_declaration' ||
|
|
25
25
|
child.type === 'optional_parameter_declaration' ||
|
|
26
|
-
child.type === 'variadic_parameter' ||
|
|
27
26
|
child.type === 'variadic_parameter_declaration') {
|
|
28
27
|
params.push(child);
|
|
29
28
|
}
|
|
@@ -47,8 +46,7 @@ export function computeCppDeclarationArity(node) {
|
|
|
47
46
|
// token in tree-sitter-cpp, detected via `hasEllipsis` above.
|
|
48
47
|
// C++ parameter packs: `template<typename... Ts> void foo(Ts... args)` —
|
|
49
48
|
// detected as `variadic_parameter_declaration`.
|
|
50
|
-
const isVariadic = hasEllipsis ||
|
|
51
|
-
params.some((p) => p.type === 'variadic_parameter' || p.type === 'variadic_parameter_declaration');
|
|
49
|
+
const isVariadic = hasEllipsis || params.some((p) => p.type === 'variadic_parameter_declaration');
|
|
52
50
|
const optionalCount = params.filter((p) => p.type === 'optional_parameter_declaration').length;
|
|
53
51
|
const requiredCount = params.filter((p) => p.type === 'parameter_declaration' ||
|
|
54
52
|
// variadic_parameter_declaration with a name is a parameter pack — counts as one
|
|
@@ -57,11 +55,7 @@ export function computeCppDeclarationArity(node) {
|
|
|
57
55
|
const types = [];
|
|
58
56
|
const typeClasses = [];
|
|
59
57
|
for (const p of params) {
|
|
60
|
-
if (p.type === '
|
|
61
|
-
types.push('...');
|
|
62
|
-
typeClasses.push(unknownTypeClass('...'));
|
|
63
|
-
}
|
|
64
|
-
else if (p.type === 'variadic_parameter_declaration') {
|
|
58
|
+
if (p.type === 'variadic_parameter_declaration') {
|
|
65
59
|
// Parameter pack: treated as variadic
|
|
66
60
|
types.push('...');
|
|
67
61
|
typeClasses.push(unknownTypeClass('...'));
|
|
@@ -18,9 +18,9 @@ export function emitCppScopeCaptures(sourceText, filePath, cachedTree) {
|
|
|
18
18
|
}
|
|
19
19
|
const rawMatches = getCppScopeQuery().matches(tree.rootNode);
|
|
20
20
|
const out = [];
|
|
21
|
-
// Track ranges where typedef-struct was captured as
|
|
21
|
+
// Track ranges where typedef-struct/enum was captured as its concrete type
|
|
22
22
|
// so we can suppress the duplicate @declaration.typedef match.
|
|
23
|
-
const
|
|
23
|
+
const concreteTypedefRanges = new Set();
|
|
24
24
|
for (const m of rawMatches) {
|
|
25
25
|
const grouped = {};
|
|
26
26
|
for (const c of m.captures) {
|
|
@@ -55,18 +55,20 @@ export function emitCppScopeCaptures(sourceText, filePath, cachedTree) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
// ── Track typedef
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
// ── Track concrete typedef ranges ───────────────────────────────
|
|
59
|
+
const concreteTypeAnchor = grouped['@declaration.struct'] ??
|
|
60
|
+
grouped['@declaration.class'] ??
|
|
61
|
+
grouped['@declaration.enum'];
|
|
62
|
+
if (concreteTypeAnchor !== undefined) {
|
|
63
|
+
const r = concreteTypeAnchor.range;
|
|
64
|
+
concreteTypedefRanges.add(`${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`);
|
|
63
65
|
}
|
|
64
66
|
// Suppress @declaration.typedef if the same range was already captured
|
|
65
67
|
const typedefAnchor = grouped['@declaration.typedef'];
|
|
66
68
|
if (typedefAnchor !== undefined) {
|
|
67
69
|
const r = typedefAnchor.range;
|
|
68
70
|
const key = `${r.startLine}:${r.startCol}:${r.endLine}:${r.endCol}`;
|
|
69
|
-
if (
|
|
71
|
+
if (concreteTypedefRanges.has(key))
|
|
70
72
|
continue;
|
|
71
73
|
}
|
|
72
74
|
// ── Enrich function/method declarations with arity metadata ─────
|
|
@@ -1251,7 +1253,7 @@ function lookupAdlIdentifierType(identNode) {
|
|
|
1251
1253
|
inner = next;
|
|
1252
1254
|
continue;
|
|
1253
1255
|
}
|
|
1254
|
-
if (inner.type === 'reference_declarator'
|
|
1256
|
+
if (inner.type === 'reference_declarator') {
|
|
1255
1257
|
// reference_declarator has a single child (the inner declarator).
|
|
1256
1258
|
let next = null;
|
|
1257
1259
|
for (let j = 0; j < inner.namedChildCount; j++) {
|
|
@@ -47,6 +47,12 @@ const CPP_SCOPE_QUERY = `
|
|
|
47
47
|
(template_argument_list) @declaration.template-arguments)
|
|
48
48
|
body: (field_declaration_list)) @declaration.struct
|
|
49
49
|
|
|
50
|
+
;; Declarations — struct (typedef struct { ... } Name)
|
|
51
|
+
(type_definition
|
|
52
|
+
type: (struct_specifier
|
|
53
|
+
body: (field_declaration_list))
|
|
54
|
+
declarator: (type_identifier) @declaration.name) @declaration.struct
|
|
55
|
+
|
|
50
56
|
;; ─── Declarations — class / struct inside template_declaration ───────
|
|
51
57
|
(template_declaration
|
|
52
58
|
(class_specifier
|
|
@@ -76,6 +82,12 @@ const CPP_SCOPE_QUERY = `
|
|
|
76
82
|
(enum_specifier
|
|
77
83
|
name: (type_identifier) @declaration.name) @declaration.enum
|
|
78
84
|
|
|
85
|
+
;; ─── Declarations — enum (typedef enum { ... } Name) ─────────────────
|
|
86
|
+
(type_definition
|
|
87
|
+
type: (enum_specifier
|
|
88
|
+
body: (enumerator_list))
|
|
89
|
+
declarator: (type_identifier) @declaration.name) @declaration.enum
|
|
90
|
+
|
|
79
91
|
;; ─── Declarations — enum constants ───────────────────────────────────
|
|
80
92
|
(enumerator
|
|
81
93
|
name: (identifier) @declaration.name) @declaration.const
|
|
@@ -242,7 +242,9 @@ function terminalTypeNameNode(node) {
|
|
|
242
242
|
case 'qualified_name':
|
|
243
243
|
return node.lastNamedChild;
|
|
244
244
|
case 'generic_name':
|
|
245
|
-
|
|
245
|
+
// generic_name has no `name` field (verified by real parse, #1920); the
|
|
246
|
+
// base identifier is the first named child.
|
|
247
|
+
return node.firstNamedChild;
|
|
246
248
|
default:
|
|
247
249
|
return null;
|
|
248
250
|
}
|
|
@@ -132,9 +132,12 @@ export function emitJavaScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
132
132
|
findNodeAtRange(tree.rootNode, anchor.range, 'object_creation_expression');
|
|
133
133
|
if (callNode !== null) {
|
|
134
134
|
const argList = callNode.childForFieldName('arguments');
|
|
135
|
+
// Exclude interleaved comments — tree-sitter-java emits `block_comment` /
|
|
136
|
+
// `line_comment` as named children of argument_list, which would inflate
|
|
137
|
+
// arity (and arity feeds call-processor symbol-ID generation). #1920
|
|
135
138
|
const args = argList === null
|
|
136
139
|
? []
|
|
137
|
-
: argList.namedChildren.filter((c) => c !== null && c.type !== '
|
|
140
|
+
: argList.namedChildren.filter((c) => c !== null && c.type !== 'block_comment' && c.type !== 'line_comment');
|
|
138
141
|
grouped['@reference.arity'] = syntheticCapture('@reference.arity', callNode, String(args.length));
|
|
139
142
|
const argTypes = args.map((arg) => inferArgType(arg));
|
|
140
143
|
grouped['@reference.parameter-types'] = syntheticCapture('@reference.parameter-types', callNode, JSON.stringify(argTypes));
|
|
@@ -97,23 +97,7 @@ function parseUseClause(clause, qualifier) {
|
|
|
97
97
|
const source = qualName.text.trim();
|
|
98
98
|
if (source === '')
|
|
99
99
|
return null;
|
|
100
|
-
// Strategy
|
|
101
|
-
const aliasClause = findNamedChild(clause, 'alias_clause');
|
|
102
|
-
if (aliasClause !== null) {
|
|
103
|
-
// alias_clause: "as" name
|
|
104
|
-
const aliasName = findNamedChild(aliasClause, 'name') ?? aliasClause.firstNamedChild;
|
|
105
|
-
const alias = aliasName?.text.trim() ?? '';
|
|
106
|
-
if (alias === '')
|
|
107
|
-
return null;
|
|
108
|
-
return {
|
|
109
|
-
kind: 'alias',
|
|
110
|
-
source,
|
|
111
|
-
name: alias,
|
|
112
|
-
alias,
|
|
113
|
-
atNode: clause,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
// Strategy 2: bare sibling `name` node after the qualified_name.
|
|
100
|
+
// Strategy: bare sibling `name` node after the qualified_name.
|
|
117
101
|
// tree-sitter-php (≥ 0.22) emits `use Foo\Bar as Baz` as:
|
|
118
102
|
// namespace_use_clause
|
|
119
103
|
// qualified_name "Foo\Bar"
|
|
@@ -197,22 +181,7 @@ function parseInnerClause(clause, prefix, qualifier) {
|
|
|
197
181
|
if (innerPath === '')
|
|
198
182
|
return null;
|
|
199
183
|
const source = prefix !== '' ? `${prefix}\\${innerPath}` : innerPath;
|
|
200
|
-
// Strategy
|
|
201
|
-
const aliasClause = findNamedChild(clause, 'alias_clause');
|
|
202
|
-
if (aliasClause !== null) {
|
|
203
|
-
const aliasName = findNamedChild(aliasClause, 'name') ?? aliasClause.firstNamedChild;
|
|
204
|
-
const alias = aliasName?.text.trim() ?? '';
|
|
205
|
-
if (alias === '')
|
|
206
|
-
return null;
|
|
207
|
-
return {
|
|
208
|
-
kind: 'alias',
|
|
209
|
-
source,
|
|
210
|
-
name: alias,
|
|
211
|
-
alias,
|
|
212
|
-
atNode: clause,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
// Strategy 2: bare sibling `name` node after the qualified_name (tree-sitter-php ≥ 0.22).
|
|
184
|
+
// Strategy: bare sibling `name` node after the qualified_name (tree-sitter-php ≥ 0.22).
|
|
216
185
|
if (clause.namedChildCount >= 2) {
|
|
217
186
|
const lastChild = clause.namedChild(clause.namedChildCount - 1);
|
|
218
187
|
if (lastChild !== null && lastChild !== qualName && lastChild.type === 'name') {
|
|
@@ -24,6 +24,11 @@ const TYPE_DECL_NODE_TYPES = new Set([
|
|
|
24
24
|
'interface_declaration',
|
|
25
25
|
'trait_declaration',
|
|
26
26
|
'enum_declaration',
|
|
27
|
+
// tree-sitter-php node for `new class {...}` (real node is `anonymous_class`,
|
|
28
|
+
// not `anonymous_class_declaration`). Included so the enclosing-type walk
|
|
29
|
+
// stops AT the anon class and the guard below skips it (otherwise a method in
|
|
30
|
+
// an anon class nested in a named class would mis-bind $this to the outer class).
|
|
31
|
+
'anonymous_class',
|
|
27
32
|
]);
|
|
28
33
|
const FUNCTION_NODE_TYPES = new Set([
|
|
29
34
|
'method_declaration',
|
|
@@ -94,7 +99,7 @@ export function synthesizePhpReceiverBinding(fnNode) {
|
|
|
94
99
|
if (enclosingType === null)
|
|
95
100
|
return [];
|
|
96
101
|
// Anonymous class — skip (no stable name).
|
|
97
|
-
if (enclosingType.type === '
|
|
102
|
+
if (enclosingType.type === 'anonymous_class')
|
|
98
103
|
return [];
|
|
99
104
|
const enclosingName = typeName(enclosingType);
|
|
100
105
|
if (enclosingName === null)
|
|
@@ -102,9 +107,8 @@ export function synthesizePhpReceiverBinding(fnNode) {
|
|
|
102
107
|
// Anchor the synthesized captures to the method body (compound_statement)
|
|
103
108
|
// so they land inside the function scope, not at the class scope.
|
|
104
109
|
// For interface/abstract methods that have no body, skip.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
fnNode.childForFieldName('return_value');
|
|
110
|
+
// tree-sitter-php arrow_function also exposes its expression via the `body` field.
|
|
111
|
+
const bodyNode = fnNode.childForFieldName('body');
|
|
108
112
|
if (bodyNode === null)
|
|
109
113
|
return [];
|
|
110
114
|
const out = [];
|
|
@@ -27,7 +27,7 @@ export function synthesizeDependsReferences(fnNode) {
|
|
|
27
27
|
if (param.type !== 'typed_default_parameter' && param.type !== 'default_parameter') {
|
|
28
28
|
continue;
|
|
29
29
|
}
|
|
30
|
-
const defaultValue = param.childForFieldName('value')
|
|
30
|
+
const defaultValue = param.childForFieldName('value');
|
|
31
31
|
if (defaultValue === null)
|
|
32
32
|
continue;
|
|
33
33
|
const callNode = defaultValue.type === 'call' ? defaultValue : null;
|
|
@@ -148,7 +148,7 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
148
148
|
if (argList !== null) {
|
|
149
149
|
for (let ai = 0; ai < argList.namedChildCount; ai++) {
|
|
150
150
|
const arg = argList.namedChild(ai);
|
|
151
|
-
if (arg !== null &&
|
|
151
|
+
if (arg !== null && arg.type === 'simple_symbol') {
|
|
152
152
|
const propName = arg.text.replace(/^:/, '');
|
|
153
153
|
out.push({
|
|
154
154
|
'@import.statement': grouped['@reference.call.free'],
|
|
@@ -265,7 +265,7 @@ export function emitRubyScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
265
265
|
if (argList !== null) {
|
|
266
266
|
for (let ai = 0; ai < argList.namedChildCount; ai++) {
|
|
267
267
|
const arg = argList.namedChild(ai);
|
|
268
|
-
if (arg !== null &&
|
|
268
|
+
if (arg !== null && arg.type === 'simple_symbol') {
|
|
269
269
|
const propName = arg.text.replace(/^:/, '');
|
|
270
270
|
out.push({
|
|
271
271
|
'@type-binding.return': syntheticCapture('@type-binding.return', attrNode, text),
|
|
@@ -233,11 +233,10 @@ function processStructDestructuring(root, parsed, scopeMap, moduleScope, allFiel
|
|
|
233
233
|
for (const fieldNode of patternNode.namedChildren) {
|
|
234
234
|
let fieldName;
|
|
235
235
|
if (fieldNode.type === 'field_pattern') {
|
|
236
|
+
// shorthand `{ a }` and full `{ b: c }` are both field_pattern; the
|
|
237
|
+
// `name` field is shorthand_field_identifier or field_identifier.
|
|
236
238
|
fieldName = fieldNode.childForFieldName('name')?.text;
|
|
237
239
|
}
|
|
238
|
-
else if (fieldNode.type === 'shorthand_field_pattern') {
|
|
239
|
-
fieldName = fieldNode.firstNamedChild?.text;
|
|
240
|
-
}
|
|
241
240
|
if (fieldName === undefined)
|
|
242
241
|
continue;
|
|
243
242
|
let fieldType = lookupFieldType(typeName, fieldName, parsed, scopeMap, moduleScope);
|
|
@@ -8,7 +8,6 @@ import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
|
8
8
|
/** Type node types that represent a return type in function/getter/setter signatures. */
|
|
9
9
|
const TYPE_NODE_TYPES = new Set([
|
|
10
10
|
'type_identifier',
|
|
11
|
-
'generic_type',
|
|
12
11
|
'function_type',
|
|
13
12
|
'nullable_type',
|
|
14
13
|
'void_type',
|
|
@@ -7,7 +7,7 @@ import { extractVueScript, isVueSetupTopLevel } from './vue-sfc-extractor.js';
|
|
|
7
7
|
import { yieldToEventLoop } from './utils/event-loop.js';
|
|
8
8
|
import { parseSourceSafe } from '../tree-sitter/safe-parse.js';
|
|
9
9
|
import { isVerboseIngestionEnabled } from './utils/verbose.js';
|
|
10
|
-
import { getDefinitionNodeFromCaptures, findEnclosingClassInfo, findObjectLiteralBindingInfo, getLabelFromCaptures, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
|
|
10
|
+
import { buildConcreteTypedefDefinitionRanges, getDefinitionNodeFromCaptures, findEnclosingClassInfo, findObjectLiteralBindingInfo, getLabelFromCaptures, isSuppressedConcreteTypedefDuplicate, CLASS_CONTAINER_TYPES, } from './utils/ast-helpers.js';
|
|
11
11
|
import { detectFrameworkFromAST } from './framework-detection.js';
|
|
12
12
|
import { buildTypeEnv } from './type-env.js';
|
|
13
13
|
import { buildMethodProps, arityForIdFromInfo, typeTagForId, constTagForId, buildCollisionGroups, parameterShapeIdTag, } from './utils/method-props.js';
|
|
@@ -356,6 +356,7 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, sco
|
|
|
356
356
|
logger.warn({ queryError }, `Query error for ${file.path}:`);
|
|
357
357
|
continue;
|
|
358
358
|
}
|
|
359
|
+
const concreteTypedefRanges = buildConcreteTypedefDefinitionRanges(matches);
|
|
359
360
|
// Build per-file type environment for FieldExtractor context (lightweight — skipped if no fieldExtractor).
|
|
360
361
|
//
|
|
361
362
|
// Note: this TypeEnv is intentionally NOT flushed into the BindingAccumulator.
|
|
@@ -375,6 +376,8 @@ const processParsingSequential = async (graph, files, symbolTable, astCache, sco
|
|
|
375
376
|
match.captures.forEach((c) => {
|
|
376
377
|
captureMap[c.name] = c.node;
|
|
377
378
|
});
|
|
379
|
+
if (isSuppressedConcreteTypedefDuplicate(captureMap, concreteTypedefRanges))
|
|
380
|
+
return;
|
|
378
381
|
const definitionNodeForRange = getDefinitionNodeFromCaptures(captureMap);
|
|
379
382
|
const definitionNode = getDefinitionNodeFromCaptures(captureMap);
|
|
380
383
|
const defaultNodeLabel = getLabelFromCaptures(captureMap, provider);
|
|
@@ -2,9 +2,9 @@ export declare const TYPESCRIPT_QUERIES = "\n(class_declaration\n name: (type_i
|
|
|
2
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; Custom fetch wrappers: apiFetch('/path'), fetchJSON('/api/data'), httpGet('/users'), etc.\n(call_expression\n function: (identifier) @_wrapper_fn (#match? @_wrapper_fn \"^(api(Fetch|Get|Post|Put|Delete|Patch|Request)|fetch(API|JSON|Data|Endpoint|Resource|Url)|http(Fetch|Get|Post|Put|Delete|Patch|Request))$\")\n arguments: (arguments\n (string (string_fragment) @route.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
|
-
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";
|
|
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(type_definition\n type: (struct_specifier\n body: (field_declaration_list))\n declarator: (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\n type: (enum_specifier\n body: (enumerator_list))\n declarator: (type_identifier) @name) @definition.enum\n(enumerator name: (identifier) @name) @definition.const\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";
|
|
6
6
|
export declare const GO_QUERIES = "\n; Functions & Methods\n(function_declaration name: (identifier) @name) @definition.function\n(method_declaration name: (field_identifier) @name) @definition.method\n\n; Types\n(type_declaration (type_spec name: (type_identifier) @name type: (struct_type))) @definition.struct\n(type_declaration (type_spec name: (type_identifier) @name type: (interface_type))) @definition.interface\n\n; Imports\n(import_declaration (import_spec path: (interpreted_string_literal) @import.source)) @import\n(import_declaration (import_spec_list (import_spec path: (interpreted_string_literal) @import.source))) @import\n\n; Struct fields \u2014 named field declarations inside struct types\n(field_declaration_list\n (field_declaration\n name: (field_identifier) @name) @definition.property)\n\n; Struct embedding (anonymous fields = inheritance)\n(type_declaration\n (type_spec\n name: (type_identifier) @heritage.class\n type: (struct_type\n (field_declaration_list\n (field_declaration\n type: (type_identifier) @heritage.extends))))) @definition.struct\n\n; Calls\n(call_expression function: (identifier) @call.name) @call\n(call_expression function: (selector_expression field: (field_identifier) @call.name)) @call\n\n; Const/var declarations\n(const_declaration (const_spec name: (identifier) @name)) @definition.const\n(var_declaration (var_spec name: (identifier) @name)) @definition.variable\n\n; Short variable declaration: x := 5\n(short_var_declaration left: (expression_list (identifier) @name)) @definition.variable\n\n; Struct literal construction: User{Name: \"Alice\"}\n(composite_literal type: (type_identifier) @call.name) @call\n\n; Write access: obj.field = value\n(assignment_statement\n left: (expression_list\n (selector_expression\n operand: (_) @assignment.receiver\n field: (field_identifier) @assignment.property))\n right: (_)) @assignment\n\n; Write access: obj.field++ / obj.field--\n(inc_statement\n (selector_expression\n operand: (_) @assignment.receiver\n field: (field_identifier) @assignment.property)) @assignment\n(dec_statement\n (selector_expression\n operand: (_) @assignment.receiver\n field: (field_identifier) @assignment.property)) @assignment\n";
|
|
7
|
-
export declare const CPP_QUERIES = "\n; Classes, Structs, Namespaces\n(class_specifier name: (type_identifier) @name) @definition.class\n(class_specifier\n name: (template_type\n (type_identifier) @name\n (template_argument_list) @template-arguments)) @definition.class\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(struct_specifier\n name: (template_type\n (type_identifier) @name\n (template_argument_list) @template-arguments)) @definition.struct\n(namespace_definition name: (namespace_identifier) @name) @definition.namespace\n(enum_specifier name: (type_identifier) @name) @definition.enum\n\n; Typedefs and unions (common in C-style headers and mixed C/C++ code)\n(type_definition declarator: (type_identifier) @name) @definition.typedef\n(union_specifier name: (type_identifier) @name) @definition.union\n\n; Macros\n(preproc_function_def name: (identifier) @name) @definition.macro\n(preproc_def name: (identifier) @name) @definition.macro\n\n; Functions & Methods (direct declarator)\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(function_definition declarator: (function_declarator declarator: (operator_name) @name)) @definition.function\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))) @definition.method\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (operator_name) @name))) @definition.method\n\n; Functions/methods returning pointers (pointer_declarator wraps function_declarator)\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method\n\n; Functions/methods returning double pointers (nested pointer_declarator)\n(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name)))) @definition.function\n(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))))) @definition.method\n\n; Functions/methods returning references (reference_declarator wraps function_declarator)\n(function_definition declarator: (reference_declarator (function_declarator declarator: (identifier) @name))) @definition.function\n(function_definition declarator: (reference_declarator (function_declarator declarator: (operator_name) @name))) @definition.function\n(function_definition declarator: (reference_declarator (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method\n(function_definition declarator: (reference_declarator (function_declarator declarator: (qualified_identifier name: (operator_name) @name)))) @definition.method\n\n; Destructors (destructor_name is distinct from identifier in tree-sitter-cpp)\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (destructor_name) @name))) @definition.method\n\n; Function declarations / prototypes (common in headers)\n(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(declaration declarator: (function_declarator declarator: (operator_name) @name)) @definition.function\n(declaration declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(declaration declarator: (reference_declarator (function_declarator declarator: (operator_name) @name))) @definition.function\n\n; Class/struct data member fields (Address address; int count;)\n; Uses field_identifier to exclude method declarations (which use function_declarator)\n(field_declaration\n declarator: (field_identifier) @name) @definition.property\n\n; Pointer member fields (Address* address;)\n(field_declaration\n declarator: (pointer_declarator\n declarator: (field_identifier) @name)) @definition.property\n\n; Reference member fields (Address& address;)\n(field_declaration\n declarator: (reference_declarator\n (field_identifier) @name)) @definition.property\n\n; Inline class method declarations (inside class body, no body: void save();)\n; tree-sitter-cpp uses field_identifier (not identifier) for names inside class bodies\n(field_declaration declarator: (function_declarator declarator: [(field_identifier) (identifier) (operator_name)] @name)) @definition.method\n\n; Inline class method declarations returning a pointer (User* lookup();)\n(field_declaration declarator: (pointer_declarator declarator: (function_declarator declarator: [(field_identifier) (identifier)] @name))) @definition.method\n\n; Inline class method declarations returning a reference (User& lookup();)\n(field_declaration declarator: (reference_declarator (function_declarator declarator: [(field_identifier) (identifier) (operator_name)] @name))) @definition.method\n\n; Inline class method definitions (inside class body, with body: void Foo() { ... })\n(field_declaration_list\n (function_definition\n declarator: (function_declarator\n declarator: [(field_identifier) (identifier) (operator_name) (destructor_name)] @name)) @definition.method)\n\n; Inline class methods returning a pointer type (User* lookup(int id) { ... })\n(field_declaration_list\n (function_definition\n declarator: (pointer_declarator\n declarator: (function_declarator\n declarator: [(field_identifier) (identifier) (operator_name)] @name))) @definition.method)\n\n; Inline class methods returning a reference type (User& lookup(int id) { ... })\n(field_declaration_list\n (function_definition\n declarator: (reference_declarator\n (function_declarator\n declarator: [(field_identifier) (identifier) (operator_name)] @name))) @definition.method)\n\n; Templates\n(template_declaration (class_specifier name: (type_identifier) @name)) @definition.template\n(template_declaration\n (class_specifier\n name: (template_type\n (type_identifier) @name\n (template_argument_list) @template-arguments))) @definition.template\n(template_declaration (function_definition declarator: (function_declarator declarator: (identifier) @name))) @definition.template\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(call_expression function: (qualified_identifier name: (identifier) @call.name)) @call\n(call_expression function: (template_function name: (identifier) @call.name)) @call\n(binary_expression operator: \"+\" @call.name) @call\n(binary_expression operator: \"<<\" @call.name) @call\n\n; Constructor calls: new User()\n(new_expression type: (type_identifier) @call.name) @call\n\n; Variable declarations: int x = 5; or auto x = 5;\n(declaration\n declarator: (init_declarator\n declarator: (identifier) @name)) @definition.variable\n\n; Heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (type_identifier) @heritage.extends)) @heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (access_specifier) (type_identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (field_expression\n argument: (_) @assignment.receiver\n field: (field_identifier) @assignment.property)\n right: (_)) @assignment\n\n";
|
|
7
|
+
export declare const CPP_QUERIES = "\n; Classes, Structs, Namespaces\n(class_specifier name: (type_identifier) @name) @definition.class\n(class_specifier\n name: (template_type\n (type_identifier) @name\n (template_argument_list) @template-arguments)) @definition.class\n(struct_specifier name: (type_identifier) @name) @definition.struct\n(struct_specifier\n name: (template_type\n (type_identifier) @name\n (template_argument_list) @template-arguments)) @definition.struct\n(namespace_definition name: (namespace_identifier) @name) @definition.namespace\n(enum_specifier name: (type_identifier) @name) @definition.enum\n\n; Typedefs and unions (common in C-style headers and mixed C/C++ code)\n(type_definition\n type: (struct_specifier\n body: (field_declaration_list))\n declarator: (type_identifier) @name) @definition.struct\n(type_definition\n type: (enum_specifier\n body: (enumerator_list))\n declarator: (type_identifier) @name) @definition.enum\n(enumerator name: (identifier) @name) @definition.const\n(type_definition declarator: (type_identifier) @name) @definition.typedef\n(union_specifier name: (type_identifier) @name) @definition.union\n\n; Macros\n(preproc_function_def name: (identifier) @name) @definition.macro\n(preproc_def name: (identifier) @name) @definition.macro\n\n; Functions & Methods (direct declarator)\n(function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(function_definition declarator: (function_declarator declarator: (operator_name) @name)) @definition.function\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))) @definition.method\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (operator_name) @name))) @definition.method\n\n; Functions/methods returning pointers (pointer_declarator wraps function_declarator)\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(function_definition declarator: (pointer_declarator declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method\n\n; Functions/methods returning double pointers (nested pointer_declarator)\n(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name)))) @definition.function\n(function_definition declarator: (pointer_declarator declarator: (pointer_declarator declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))))) @definition.method\n\n; Functions/methods returning references (reference_declarator wraps function_declarator)\n(function_definition declarator: (reference_declarator (function_declarator declarator: (identifier) @name))) @definition.function\n(function_definition declarator: (reference_declarator (function_declarator declarator: (operator_name) @name))) @definition.function\n(function_definition declarator: (reference_declarator (function_declarator declarator: (qualified_identifier name: (identifier) @name)))) @definition.method\n(function_definition declarator: (reference_declarator (function_declarator declarator: (qualified_identifier name: (operator_name) @name)))) @definition.method\n\n; Destructors (destructor_name is distinct from identifier in tree-sitter-cpp)\n(function_definition declarator: (function_declarator declarator: (qualified_identifier name: (destructor_name) @name))) @definition.method\n\n; Function declarations / prototypes (common in headers)\n(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function\n(declaration declarator: (function_declarator declarator: (operator_name) @name)) @definition.function\n(declaration declarator: (pointer_declarator declarator: (function_declarator declarator: (identifier) @name))) @definition.function\n(declaration declarator: (reference_declarator (function_declarator declarator: (operator_name) @name))) @definition.function\n\n; Class/struct data member fields (Address address; int count;)\n; Uses field_identifier to exclude method declarations (which use function_declarator)\n(field_declaration\n declarator: (field_identifier) @name) @definition.property\n\n; Pointer member fields (Address* address;)\n(field_declaration\n declarator: (pointer_declarator\n declarator: (field_identifier) @name)) @definition.property\n\n; Reference member fields (Address& address;)\n(field_declaration\n declarator: (reference_declarator\n (field_identifier) @name)) @definition.property\n\n; Inline class method declarations (inside class body, no body: void save();)\n; tree-sitter-cpp uses field_identifier (not identifier) for names inside class bodies\n(field_declaration declarator: (function_declarator declarator: [(field_identifier) (identifier) (operator_name)] @name)) @definition.method\n\n; Inline class method declarations returning a pointer (User* lookup();)\n(field_declaration declarator: (pointer_declarator declarator: (function_declarator declarator: [(field_identifier) (identifier)] @name))) @definition.method\n\n; Inline class method declarations returning a reference (User& lookup();)\n(field_declaration declarator: (reference_declarator (function_declarator declarator: [(field_identifier) (identifier) (operator_name)] @name))) @definition.method\n\n; Inline class method definitions (inside class body, with body: void Foo() { ... })\n(field_declaration_list\n (function_definition\n declarator: (function_declarator\n declarator: [(field_identifier) (identifier) (operator_name) (destructor_name)] @name)) @definition.method)\n\n; Inline class methods returning a pointer type (User* lookup(int id) { ... })\n(field_declaration_list\n (function_definition\n declarator: (pointer_declarator\n declarator: (function_declarator\n declarator: [(field_identifier) (identifier) (operator_name)] @name))) @definition.method)\n\n; Inline class methods returning a reference type (User& lookup(int id) { ... })\n(field_declaration_list\n (function_definition\n declarator: (reference_declarator\n (function_declarator\n declarator: [(field_identifier) (identifier) (operator_name)] @name))) @definition.method)\n\n; Templates\n(template_declaration (class_specifier name: (type_identifier) @name)) @definition.template\n(template_declaration\n (class_specifier\n name: (template_type\n (type_identifier) @name\n (template_argument_list) @template-arguments))) @definition.template\n(template_declaration (function_definition declarator: (function_declarator declarator: (identifier) @name))) @definition.template\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(call_expression function: (qualified_identifier name: (identifier) @call.name)) @call\n(call_expression function: (template_function name: (identifier) @call.name)) @call\n(binary_expression operator: \"+\" @call.name) @call\n(binary_expression operator: \"<<\" @call.name) @call\n\n; Constructor calls: new User()\n(new_expression type: (type_identifier) @call.name) @call\n\n; Variable declarations: int x = 5; or auto x = 5;\n(declaration\n declarator: (init_declarator\n declarator: (identifier) @name)) @definition.variable\n\n; Heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (type_identifier) @heritage.extends)) @heritage\n(class_specifier name: (type_identifier) @heritage.class\n (base_class_clause (access_specifier) (type_identifier) @heritage.extends)) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (field_expression\n argument: (_) @assignment.receiver\n field: (field_identifier) @assignment.property)\n right: (_)) @assignment\n\n";
|
|
8
8
|
export declare const CSHARP_QUERIES = "\n; Types\n(class_declaration name: (identifier) @name) @definition.class\n(interface_declaration name: (identifier) @name) @definition.interface\n(struct_declaration name: (identifier) @name) @definition.struct\n(enum_declaration name: (identifier) @name) @definition.enum\n(record_declaration name: (identifier) @name) @definition.record\n(delegate_declaration name: (identifier) @name) @definition.delegate\n\n; Namespaces (block form and C# 10+ file-scoped form)\n(namespace_declaration name: (identifier) @name) @definition.namespace\n(namespace_declaration name: (qualified_name) @name) @definition.namespace\n(file_scoped_namespace_declaration name: (identifier) @name) @definition.namespace\n(file_scoped_namespace_declaration name: (qualified_name) @name) @definition.namespace\n\n; Methods & Properties\n(method_declaration name: (identifier) @name) @definition.method\n(local_function_statement name: (identifier) @name) @definition.function\n(constructor_declaration name: (identifier) @name) @definition.constructor\n(property_declaration name: (identifier) @name) @definition.property\n\n; Primary constructors (C# 12): class User(string name, int age) { }\n(class_declaration name: (identifier) @name (parameter_list) @definition.constructor)\n(record_declaration name: (identifier) @name (parameter_list) @definition.constructor)\n\n; Using\n(using_directive (qualified_name) @import.source) @import\n(using_directive (identifier) @import.source) @import\n\n; Calls\n(invocation_expression function: (identifier) @call.name) @call\n(invocation_expression function: (member_access_expression name: (identifier) @call.name)) @call\n\n; Null-conditional method calls: user?.Save()\n; Parses as: invocation_expression \u2192 conditional_access_expression \u2192 member_binding_expression \u2192 identifier\n(invocation_expression\n function: (conditional_access_expression\n (member_binding_expression\n (identifier) @call.name))) @call\n\n; Constructor calls: new Foo() and new Foo { Props }\n(object_creation_expression type: (identifier) @call.name) @call\n\n; Target-typed new (C# 9): User u = new(\"x\", 5)\n(variable_declaration type: (identifier) @call.name (variable_declarator (implicit_object_creation_expression) @call))\n\n; Local variable declarations\n(local_declaration_statement\n (variable_declaration\n (variable_declarator\n (identifier) @name))) @definition.variable\n\n; Heritage\n(class_declaration name: (identifier) @heritage.class\n (base_list (identifier) @heritage.extends)) @heritage\n(class_declaration name: (identifier) @heritage.class\n (base_list (generic_name (identifier) @heritage.extends))) @heritage\n\n; Interface inheritance: interface IFoo : IBar / interface IFoo : IBar, IBaz\n; Without these patterns, interface-to-interface relationships are never\n; captured, so transitive \"class X implements IBar\" chains are broken.\n(interface_declaration name: (identifier) @heritage.class\n (base_list (identifier) @heritage.extends)) @heritage\n(interface_declaration name: (identifier) @heritage.class\n (base_list (generic_name (identifier) @heritage.extends))) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (member_access_expression\n expression: (_) @assignment.receiver\n name: (identifier) @assignment.property)\n right: (_)) @assignment\n";
|
|
9
9
|
export declare const RUST_QUERIES = "\n; Functions & Items\n(function_item name: (identifier) @name) @definition.function\n(function_signature_item name: (identifier) @name) @definition.function\n(struct_item name: (type_identifier) @name) @definition.struct\n(enum_item name: (type_identifier) @name) @definition.enum\n(trait_item name: (type_identifier) @name) @definition.trait\n(impl_item type: (type_identifier) @name !trait) @definition.impl\n(impl_item type: (generic_type type: (type_identifier) @name) !trait) @definition.impl\n(mod_item name: (identifier) @name) @definition.module\n\n; Type aliases, const, static, macros\n(type_item name: (type_identifier) @name) @definition.type\n(const_item name: (identifier) @name) @definition.const\n(static_item name: (identifier) @name) @definition.static\n(macro_definition name: (identifier) @name) @definition.macro\n\n; Use statements\n(use_declaration argument: (_) @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(call_expression function: (scoped_identifier name: (identifier) @call.name)) @call\n(call_expression function: (generic_function function: (identifier) @call.name)) @call\n\n; Struct literal construction: User { name: value }\n(struct_expression name: (type_identifier) @call.name) @call\n\n; Struct fields \u2014 named field declarations inside struct bodies\n(field_declaration_list\n (field_declaration\n name: (field_identifier) @name) @definition.property)\n\n; Heritage (trait implementation) \u2014 all combinations of concrete/generic trait \u00D7 concrete/generic type\n(impl_item trait: (type_identifier) @heritage.trait type: (type_identifier) @heritage.class) @heritage\n(impl_item trait: (generic_type type: (type_identifier) @heritage.trait) type: (type_identifier) @heritage.class) @heritage\n(impl_item trait: (type_identifier) @heritage.trait type: (generic_type type: (type_identifier) @heritage.class)) @heritage\n(impl_item trait: (generic_type type: (type_identifier) @heritage.trait) type: (generic_type type: (type_identifier) @heritage.class)) @heritage\n\n; Write access: obj.field = value\n(assignment_expression\n left: (field_expression\n value: (_) @assignment.receiver\n field: (field_identifier) @assignment.property)\n right: (_)) @assignment\n\n; Write access: obj.field += value (compound assignment)\n(compound_assignment_expr\n left: (field_expression\n value: (_) @assignment.receiver\n field: (field_identifier) @assignment.property)\n right: (_)) @assignment\n";
|
|
10
10
|
export declare const PHP_QUERIES = "\n; \u2500\u2500 Namespace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(namespace_definition\n name: (namespace_name) @name) @definition.namespace\n\n; \u2500\u2500 Classes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @name) @definition.class\n\n; \u2500\u2500 Interfaces \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(interface_declaration\n name: (name) @name) @definition.interface\n\n; \u2500\u2500 Traits \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(trait_declaration\n name: (name) @name) @definition.trait\n\n; \u2500\u2500 Enums (PHP 8.1) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(enum_declaration\n name: (name) @name) @definition.enum\n\n; \u2500\u2500 Top-level functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(function_definition\n name: (name) @name) @definition.function\n\n; \u2500\u2500 Methods (including constructors) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(method_declaration\n name: (name) @name) @definition.method\n\n; \u2500\u2500 Class properties (including Eloquent $fillable, $casts, etc.) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(property_declaration\n (property_element\n (variable_name\n (name) @name))) @definition.property\n\n; Constructor property promotion (PHP 8.0+: public Address $address in __construct)\n(method_declaration\n parameters: (formal_parameters\n (property_promotion_parameter\n name: (variable_name\n (name) @name)))) @definition.property\n\n; \u2500\u2500 Imports: use statements \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; Simple: use App\\Models\\User;\n(namespace_use_declaration\n (namespace_use_clause\n (qualified_name) @import.source)) @import\n\n; \u2500\u2500 Function/method calls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; Regular function call: foo()\n(function_call_expression\n function: (name) @call.name) @call\n\n; Method call: $obj->method()\n(member_call_expression\n name: (name) @call.name) @call\n\n; Nullsafe method call: $obj?->method()\n(nullsafe_member_call_expression\n name: (name) @call.name) @call\n\n; Static call: Foo::bar() (php_only uses scoped_call_expression)\n(scoped_call_expression\n name: (name) @call.name) @call\n\n; Constructor call: new User()\n(object_creation_expression (name) @call.name) @call\n\n; Const declarations at class scope\n(const_declaration\n (const_element\n (name) @name)) @definition.const\n\n; \u2500\u2500 Heritage: extends \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @heritage.class\n (base_clause\n [(name) (qualified_name)] @heritage.extends)) @heritage\n\n; \u2500\u2500 Heritage: implements \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @heritage.class\n (class_interface_clause\n [(name) (qualified_name)] @heritage.implements)) @heritage.impl\n\n; \u2500\u2500 Heritage: use trait (must capture enclosing class name) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n(class_declaration\n name: (name) @heritage.class\n body: (declaration_list\n (use_declaration\n [(name) (qualified_name)] @heritage.trait))) @heritage\n\n; \u2500\u2500 Heritage: trait uses another trait (transitive trait composition) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n; PHP allows a trait body to contain \"use OtherTrait;\". The trait-uses-trait\n; IMPLEMENTS edge is required by buildPhpMro to compute the full transitive\n; trait closure (depth 3+ chains).\n(trait_declaration\n name: (name) @heritage.class\n body: (declaration_list\n (use_declaration\n [(name) (qualified_name)] @heritage.trait))) @heritage\n\n; PHP HTTP consumers: file_get_contents('/path'), curl_init('/path')\n(function_call_expression\n function: (name) @_php_http (#match? @_php_http \"^(file_get_contents|curl_init)$\")\n arguments: (arguments\n (argument (string (string_content) @http_client.url)))) @http_client\n\n; Write access: $obj->field = value\n(assignment_expression\n left: (member_access_expression\n object: (_) @assignment.receiver\n name: (name) @assignment.property)\n right: (_)) @assignment\n\n; Write access: ClassName::$field = value (static property)\n(assignment_expression\n left: (scoped_property_access_expression\n scope: (_) @assignment.receiver\n name: (variable_name (name) @assignment.property))\n right: (_)) @assignment\n";
|
|
@@ -601,8 +601,17 @@ export const C_QUERIES = `
|
|
|
601
601
|
|
|
602
602
|
; Structs, Unions, Enums, Typedefs
|
|
603
603
|
(struct_specifier name: (type_identifier) @name) @definition.struct
|
|
604
|
+
(type_definition
|
|
605
|
+
type: (struct_specifier
|
|
606
|
+
body: (field_declaration_list))
|
|
607
|
+
declarator: (type_identifier) @name) @definition.struct
|
|
604
608
|
(union_specifier name: (type_identifier) @name) @definition.union
|
|
605
609
|
(enum_specifier name: (type_identifier) @name) @definition.enum
|
|
610
|
+
(type_definition
|
|
611
|
+
type: (enum_specifier
|
|
612
|
+
body: (enumerator_list))
|
|
613
|
+
declarator: (type_identifier) @name) @definition.enum
|
|
614
|
+
(enumerator name: (identifier) @name) @definition.const
|
|
606
615
|
(type_definition declarator: (type_identifier) @name) @definition.typedef
|
|
607
616
|
|
|
608
617
|
; Macros
|
|
@@ -698,6 +707,15 @@ export const CPP_QUERIES = `
|
|
|
698
707
|
(enum_specifier name: (type_identifier) @name) @definition.enum
|
|
699
708
|
|
|
700
709
|
; Typedefs and unions (common in C-style headers and mixed C/C++ code)
|
|
710
|
+
(type_definition
|
|
711
|
+
type: (struct_specifier
|
|
712
|
+
body: (field_declaration_list))
|
|
713
|
+
declarator: (type_identifier) @name) @definition.struct
|
|
714
|
+
(type_definition
|
|
715
|
+
type: (enum_specifier
|
|
716
|
+
body: (enumerator_list))
|
|
717
|
+
declarator: (type_identifier) @name) @definition.enum
|
|
718
|
+
(enumerator name: (identifier) @name) @definition.const
|
|
701
719
|
(type_definition declarator: (type_identifier) @name) @definition.typedef
|
|
702
720
|
(union_specifier name: (type_identifier) @name) @definition.union
|
|
703
721
|
|
|
@@ -35,7 +35,6 @@ const findTypeIdentifierChild = (node) => {
|
|
|
35
35
|
* Includes both multi-arm pattern-match branches AND if-statement bodies for null-check narrowing. */
|
|
36
36
|
const NARROWING_BRANCH_TYPES = new Set([
|
|
37
37
|
'when_entry', // Kotlin when
|
|
38
|
-
'switch_block_label', // Java switch (enhanced)
|
|
39
38
|
'if_statement', // TS/JS, Java, C/C++
|
|
40
39
|
'if_expression', // Kotlin (if is an expression)
|
|
41
40
|
'statement_block', // TS/JS: { ... } body of if
|
|
@@ -796,7 +795,6 @@ export const buildTypeEnv = (tree, language, options) => {
|
|
|
796
795
|
(child.type === 'user_type' ||
|
|
797
796
|
child.type === 'type_identifier' ||
|
|
798
797
|
child.type === 'generic_type' ||
|
|
799
|
-
child.type === 'parameterized_type' ||
|
|
800
798
|
child.type === 'nullable_type')) {
|
|
801
799
|
fallbackType = child;
|
|
802
800
|
}
|
|
@@ -111,13 +111,13 @@ const extractInitializer = (node, env, classNames) => {
|
|
|
111
111
|
// or: call_expression > function: template_function (unqualified)
|
|
112
112
|
const templateFunc = func.type === 'template_function'
|
|
113
113
|
? func
|
|
114
|
-
: func.type === 'qualified_identifier'
|
|
114
|
+
: func.type === 'qualified_identifier'
|
|
115
115
|
? (func.namedChildren.find((c) => c.type === 'template_function') ?? null)
|
|
116
116
|
: null;
|
|
117
117
|
if (templateFunc) {
|
|
118
118
|
const nameNode = templateFunc.firstNamedChild;
|
|
119
119
|
if (nameNode) {
|
|
120
|
-
const funcName = nameNode.type === 'qualified_identifier'
|
|
120
|
+
const funcName = nameNode.type === 'qualified_identifier'
|
|
121
121
|
? (nameNode.lastNamedChild?.text ?? '')
|
|
122
122
|
: nameNode.text;
|
|
123
123
|
if (SMART_PTR_FACTORIES.has(funcName)) {
|
|
@@ -185,7 +185,7 @@ const scanConstructorBinding = (node) => {
|
|
|
185
185
|
const func = value.childForFieldName('function');
|
|
186
186
|
if (!func)
|
|
187
187
|
return undefined;
|
|
188
|
-
if (func.type === 'qualified_identifier'
|
|
188
|
+
if (func.type === 'qualified_identifier') {
|
|
189
189
|
const last = func.lastNamedChild;
|
|
190
190
|
if (!last)
|
|
191
191
|
return undefined;
|
|
@@ -309,16 +309,14 @@ const extractCppElementTypeFromTypeNode = (typeNode, pos = 'last', depth = 0) =>
|
|
|
309
309
|
if (args.length >= 1)
|
|
310
310
|
return pos === 'first' ? args[0] : args[args.length - 1];
|
|
311
311
|
}
|
|
312
|
-
//
|
|
313
|
-
if (typeNode.type === '
|
|
314
|
-
typeNode.type === 'pointer_type' ||
|
|
315
|
-
typeNode.type === 'type_descriptor') {
|
|
312
|
+
// type_descriptor wrapper: unwrap and recurse (vector<User>& → vector<User>)
|
|
313
|
+
if (typeNode.type === 'type_descriptor') {
|
|
316
314
|
const inner = typeNode.lastNamedChild;
|
|
317
315
|
if (inner)
|
|
318
316
|
return extractCppElementTypeFromTypeNode(inner, pos, depth + 1);
|
|
319
317
|
}
|
|
320
|
-
// qualified
|
|
321
|
-
if (typeNode.type === 'qualified_identifier'
|
|
318
|
+
// qualified types: std::vector<User> → unwrap to template_type child
|
|
319
|
+
if (typeNode.type === 'qualified_identifier') {
|
|
322
320
|
const inner = typeNode.lastNamedChild;
|
|
323
321
|
if (inner)
|
|
324
322
|
return extractCppElementTypeFromTypeNode(inner, pos, depth + 1);
|
|
@@ -497,7 +495,7 @@ const detectCppConstructorType = (node, classNames) => {
|
|
|
497
495
|
if (!nameNode)
|
|
498
496
|
return undefined;
|
|
499
497
|
let funcName;
|
|
500
|
-
if (nameNode.type === 'qualified_identifier'
|
|
498
|
+
if (nameNode.type === 'qualified_identifier') {
|
|
501
499
|
funcName = nameNode.lastNamedChild?.text ?? '';
|
|
502
500
|
}
|
|
503
501
|
else {
|
|
@@ -27,7 +27,7 @@ const extractDeclaration = (node, env) => {
|
|
|
27
27
|
const child = node.namedChild(i);
|
|
28
28
|
if (!child)
|
|
29
29
|
continue;
|
|
30
|
-
if (!typeNode && child.type !== 'variable_declarator'
|
|
30
|
+
if (!typeNode && child.type !== 'variable_declarator') {
|
|
31
31
|
// First non-declarator child is the type (identifier, implicit_type, generic_name, etc.)
|
|
32
32
|
typeNode = child;
|
|
33
33
|
}
|
|
@@ -41,11 +41,9 @@ const extractDeclaration = (node, env) => {
|
|
|
41
41
|
let typeName;
|
|
42
42
|
if (typeNode.type === 'implicit_type' && typeNode.text === 'var') {
|
|
43
43
|
// Try to infer from initializer: var x = new Foo()
|
|
44
|
-
// tree-sitter-c-sharp
|
|
45
|
-
// or inside equals_value_clause depending on grammar version
|
|
44
|
+
// tree-sitter-c-sharp puts object_creation_expression as a direct child
|
|
46
45
|
if (declarators.length === 1) {
|
|
47
|
-
const initializer = findChild(declarators[0], 'object_creation_expression')
|
|
48
|
-
findChild(declarators[0], 'equals_value_clause')?.firstNamedChild;
|
|
46
|
+
const initializer = findChild(declarators[0], 'object_creation_expression');
|
|
49
47
|
if (initializer?.type === 'object_creation_expression') {
|
|
50
48
|
const ctorType = initializer.childForFieldName('type');
|
|
51
49
|
if (ctorType)
|
|
@@ -76,7 +74,7 @@ const extractParameter = (node, env) => {
|
|
|
76
74
|
nameNode = node.childForFieldName('name');
|
|
77
75
|
}
|
|
78
76
|
else {
|
|
79
|
-
nameNode = node.childForFieldName('name')
|
|
77
|
+
nameNode = node.childForFieldName('name');
|
|
80
78
|
typeNode = node.childForFieldName('type');
|
|
81
79
|
}
|
|
82
80
|
if (!nameNode || !typeNode)
|
|
@@ -113,17 +111,13 @@ const scanConstructorBinding = (node) => {
|
|
|
113
111
|
const nameNode = declarator.childForFieldName('name') ?? declarator.firstNamedChild;
|
|
114
112
|
if (!nameNode || nameNode.type !== 'identifier')
|
|
115
113
|
return undefined;
|
|
116
|
-
// Find the initializer value
|
|
114
|
+
// Find the initializer value as a direct child
|
|
117
115
|
// (tree-sitter-c-sharp puts invocation_expression directly inside variable_declarator)
|
|
118
116
|
let value = null;
|
|
119
117
|
for (let i = 0; i < declarator.namedChildCount; i++) {
|
|
120
118
|
const child = declarator.namedChild(i);
|
|
121
119
|
if (!child)
|
|
122
120
|
continue;
|
|
123
|
-
if (child.type === 'equals_value_clause') {
|
|
124
|
-
value = child.firstNamedChild;
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
121
|
if (child.type === 'invocation_expression' ||
|
|
128
122
|
child.type === 'object_creation_expression' ||
|
|
129
123
|
child.type === 'await_expression') {
|
|
@@ -462,18 +456,9 @@ const extractPendingAssignment = (node, scopeEnv) => {
|
|
|
462
456
|
const lhs = nameNode.text;
|
|
463
457
|
if (scopeEnv.has(lhs))
|
|
464
458
|
continue;
|
|
465
|
-
// C#
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
if (child.child(j)?.type === 'equals_value_clause') {
|
|
469
|
-
evc = child.child(j);
|
|
470
|
-
break;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
const valueNode = evc?.firstNamedChild ?? child.namedChild(child.namedChildCount - 1);
|
|
474
|
-
if (valueNode &&
|
|
475
|
-
valueNode !== nameNode &&
|
|
476
|
-
(valueNode.type === 'identifier' || valueNode.type === 'simple_identifier')) {
|
|
459
|
+
// C# variable_declarator holds the initializer value as a direct named child
|
|
460
|
+
const valueNode = child.namedChild(child.namedChildCount - 1);
|
|
461
|
+
if (valueNode && valueNode !== nameNode && valueNode.type === 'identifier') {
|
|
477
462
|
return { kind: 'copy', lhs, rhs: valueNode.text };
|
|
478
463
|
}
|
|
479
464
|
// member_access_expression RHS → fieldAccess (a.Field)
|
|
@@ -487,7 +472,7 @@ const extractPendingAssignment = (node, scopeEnv) => {
|
|
|
487
472
|
// invocation_expression RHS
|
|
488
473
|
if (valueNode?.type === 'invocation_expression') {
|
|
489
474
|
const funcNode = valueNode.firstNamedChild;
|
|
490
|
-
if (funcNode?.type === '
|
|
475
|
+
if (funcNode?.type === 'identifier') {
|
|
491
476
|
return { kind: 'callResult', lhs, callee: funcNode.text };
|
|
492
477
|
}
|
|
493
478
|
// method call with receiver → methodCallResult: a.GetC()
|
|
@@ -504,7 +489,7 @@ const extractPendingAssignment = (node, scopeEnv) => {
|
|
|
504
489
|
const inner = valueNode.firstNamedChild;
|
|
505
490
|
if (inner?.type === 'invocation_expression') {
|
|
506
491
|
const funcNode = inner.firstNamedChild;
|
|
507
|
-
if (funcNode?.type === '
|
|
492
|
+
if (funcNode?.type === 'identifier') {
|
|
508
493
|
return { kind: 'callResult', lhs, callee: funcNode.text };
|
|
509
494
|
}
|
|
510
495
|
if (funcNode?.type === 'member_access_expression') {
|
|
@@ -555,15 +540,14 @@ export const typeConfig = {
|
|
|
555
540
|
const direct = node.childForFieldName('type');
|
|
556
541
|
if (direct)
|
|
557
542
|
return direct;
|
|
558
|
-
const wrapped =
|
|
559
|
-
(
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
})();
|
|
543
|
+
const wrapped = (() => {
|
|
544
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
545
|
+
const c = node.namedChild(i);
|
|
546
|
+
if (c?.type === 'variable_declaration')
|
|
547
|
+
return c;
|
|
548
|
+
}
|
|
549
|
+
return null;
|
|
550
|
+
})();
|
|
567
551
|
return wrapped?.childForFieldName('type') ?? null;
|
|
568
552
|
},
|
|
569
553
|
forLoopNodeTypes: FOR_LOOP_NODE_TYPES,
|
|
@@ -131,16 +131,8 @@ const extractDeclaration = (node, env) => {
|
|
|
131
131
|
};
|
|
132
132
|
/** Go: parameter → name type */
|
|
133
133
|
const extractParameter = (node, env) => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (node.type === 'parameter') {
|
|
137
|
-
nameNode = node.childForFieldName('name');
|
|
138
|
-
typeNode = node.childForFieldName('type');
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
nameNode = node.childForFieldName('name') ?? node.childForFieldName('pattern');
|
|
142
|
-
typeNode = node.childForFieldName('type');
|
|
143
|
-
}
|
|
134
|
+
const nameNode = node.childForFieldName('name');
|
|
135
|
+
const typeNode = node.childForFieldName('type');
|
|
144
136
|
if (!nameNode || !typeNode)
|
|
145
137
|
return;
|
|
146
138
|
const varName = extractVarName(nameNode);
|
|
@@ -60,7 +60,7 @@ const extractJavaParameter = (node, env) => {
|
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
62
|
// Generic fallback
|
|
63
|
-
nameNode = node.childForFieldName('name')
|
|
63
|
+
nameNode = node.childForFieldName('name');
|
|
64
64
|
typeNode = node.childForFieldName('type');
|
|
65
65
|
}
|
|
66
66
|
if (!nameNode || !typeNode)
|
|
@@ -359,9 +359,10 @@ const extractKotlinDeclaration = (node, env) => {
|
|
|
359
359
|
env.set(varName, typeName);
|
|
360
360
|
return;
|
|
361
361
|
}
|
|
362
|
-
// Fallback:
|
|
363
|
-
|
|
364
|
-
const
|
|
362
|
+
// Fallback: Kotlin property_declaration has no name/type fields (verified by
|
|
363
|
+
// real parse, #1920); the name/type are positional children.
|
|
364
|
+
const nameNode = findChild(node, 'simple_identifier');
|
|
365
|
+
const typeNode = findChild(node, 'user_type');
|
|
365
366
|
if (!nameNode || !typeNode)
|
|
366
367
|
return;
|
|
367
368
|
const varName = extractVarName(nameNode);
|
|
@@ -393,7 +394,7 @@ const extractKotlinParameter = (node, env) => {
|
|
|
393
394
|
nameNode = node.childForFieldName('name');
|
|
394
395
|
}
|
|
395
396
|
else {
|
|
396
|
-
nameNode = node.childForFieldName('name')
|
|
397
|
+
nameNode = node.childForFieldName('name');
|
|
397
398
|
typeNode = node.childForFieldName('type');
|
|
398
399
|
}
|
|
399
400
|
// Fallback: Kotlin `parameter` nodes use positional children, not named fields
|
|
@@ -269,7 +269,7 @@ const extractParameter = (node, env) => {
|
|
|
269
269
|
nameNode = node.childForFieldName('name');
|
|
270
270
|
}
|
|
271
271
|
else {
|
|
272
|
-
nameNode = node.childForFieldName('name')
|
|
272
|
+
nameNode = node.childForFieldName('name');
|
|
273
273
|
typeNode = node.childForFieldName('type');
|
|
274
274
|
}
|
|
275
275
|
if (!nameNode || !typeNode)
|
|
@@ -59,7 +59,7 @@ const extractParameter = (node, env) => {
|
|
|
59
59
|
typeNode = node.childForFieldName('type');
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
|
-
nameNode = node.childForFieldName('name')
|
|
62
|
+
nameNode = node.childForFieldName('name');
|
|
63
63
|
typeNode = node.childForFieldName('type');
|
|
64
64
|
// Python typed_parameter: name is a positional child (identifier), not a named field
|
|
65
65
|
if (!nameNode && node.type === 'typed_parameter') {
|
|
@@ -345,8 +345,8 @@ const extractPendingAssignment = (node, scopeEnv) => {
|
|
|
345
345
|
return undefined;
|
|
346
346
|
if (rhsNode.type === 'identifier')
|
|
347
347
|
return { kind: 'copy', lhs: varName, rhs: rhsNode.text };
|
|
348
|
-
// call
|
|
349
|
-
if (rhsNode.type === 'call'
|
|
348
|
+
// call RHS — Ruby uses method calls for both field access and method calls
|
|
349
|
+
if (rhsNode.type === 'call') {
|
|
350
350
|
const methodNode = rhsNode.childForFieldName('method');
|
|
351
351
|
const receiverNode = rhsNode.childForFieldName('receiver');
|
|
352
352
|
if (!receiverNode && methodNode?.type === 'identifier') {
|
|
@@ -266,16 +266,6 @@ const extractPendingAssignment = (node, scopeEnv) => {
|
|
|
266
266
|
return { kind: 'callResult', lhs, callee: funcNode.text };
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
|
-
// method_call_expression RHS → methodCallResult (receiver.method())
|
|
270
|
-
if (unwrapped.type === 'method_call_expression') {
|
|
271
|
-
const obj = unwrapped.firstNamedChild;
|
|
272
|
-
if (obj?.type === 'identifier') {
|
|
273
|
-
const methodNode = unwrapped.childForFieldName('name') ?? unwrapped.namedChild(1);
|
|
274
|
-
if (methodNode?.type === 'field_identifier') {
|
|
275
|
-
return { kind: 'methodCallResult', lhs, receiver: obj.text, method: methodNode.text };
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
269
|
return undefined;
|
|
280
270
|
};
|
|
281
271
|
/**
|
|
@@ -395,12 +385,6 @@ const extractRustElementTypeFromTypeNode = (typeNode, pos = 'last', depth = 0) =
|
|
|
395
385
|
if (elemNode)
|
|
396
386
|
return extractSimpleTypeName(elemNode);
|
|
397
387
|
}
|
|
398
|
-
// slice_type: [User] — element is the first child
|
|
399
|
-
if (typeNode.type === 'slice_type') {
|
|
400
|
-
const elemNode = typeNode.firstNamedChild;
|
|
401
|
-
if (elemNode)
|
|
402
|
-
return extractSimpleTypeName(elemNode);
|
|
403
|
-
}
|
|
404
388
|
return undefined;
|
|
405
389
|
};
|
|
406
390
|
/** Walk up from a for-loop to the enclosing function_item and search parameters
|
|
@@ -65,8 +65,8 @@ export declare const TYPED_PARAMETER_TYPES: Set<string>;
|
|
|
65
65
|
* Note: Go slices/maps use slice_type/map_type, not generic_type — those are
|
|
66
66
|
* NOT handled here. Use language-specific extractors for Go container types.
|
|
67
67
|
*
|
|
68
|
-
* @param typeNode A generic_type
|
|
69
|
-
* returns [] for non-generic types).
|
|
68
|
+
* @param typeNode A generic_type / generic_name / user_type AST node (or any
|
|
69
|
+
* node — returns [] for non-generic types).
|
|
70
70
|
* @returns Array of resolved type argument names. Unresolvable arguments are omitted.
|
|
71
71
|
*/
|
|
72
72
|
export declare const extractGenericTypeArgs: (typeNode: SyntaxNode, depth?: number) => string[];
|
|
@@ -204,9 +204,7 @@ export const extractSimpleTypeName = (typeNode, depth = 0) => {
|
|
|
204
204
|
}
|
|
205
205
|
// Generic types: extract the base type (e.g., List<User> → List)
|
|
206
206
|
// For nullable wrappers (Optional<User>, Option<User>), unwrap to inner type.
|
|
207
|
-
if (typeNode.type === 'generic_type' ||
|
|
208
|
-
typeNode.type === 'parameterized_type' ||
|
|
209
|
-
typeNode.type === 'generic_name') {
|
|
207
|
+
if (typeNode.type === 'generic_type' || typeNode.type === 'generic_name') {
|
|
210
208
|
const base = typeNode.childForFieldName('name') ??
|
|
211
209
|
typeNode.childForFieldName('type') ??
|
|
212
210
|
typeNode.firstNamedChild;
|
|
@@ -348,17 +346,20 @@ export const TYPED_PARAMETER_TYPES = new Set([
|
|
|
348
346
|
* Note: Go slices/maps use slice_type/map_type, not generic_type — those are
|
|
349
347
|
* NOT handled here. Use language-specific extractors for Go container types.
|
|
350
348
|
*
|
|
351
|
-
* @param typeNode A generic_type
|
|
352
|
-
* returns [] for non-generic types).
|
|
349
|
+
* @param typeNode A generic_type / generic_name / user_type AST node (or any
|
|
350
|
+
* node — returns [] for non-generic types).
|
|
353
351
|
* @returns Array of resolved type argument names. Unresolvable arguments are omitted.
|
|
354
352
|
*/
|
|
355
353
|
export const extractGenericTypeArgs = (typeNode, depth = 0) => {
|
|
356
354
|
if (depth > 50)
|
|
357
355
|
return [];
|
|
358
|
-
// Unwrap wrapper nodes
|
|
356
|
+
// Unwrap pure wrapper nodes (which carry no type_arguments of their own) that
|
|
357
|
+
// may sit above the generic type. `user_type` is intentionally NOT unwrapped
|
|
358
|
+
// here: a Kotlin `user_type` can itself carry a `type_arguments` child
|
|
359
|
+
// (`List<User>` → user_type > [type_identifier, type_arguments]), so it is
|
|
360
|
+
// handled as a generic-bearing node below.
|
|
359
361
|
if (typeNode.type === 'type_annotation' ||
|
|
360
362
|
typeNode.type === 'type' ||
|
|
361
|
-
typeNode.type === 'user_type' ||
|
|
362
363
|
typeNode.type === 'nullable_type' ||
|
|
363
364
|
typeNode.type === 'optional_type') {
|
|
364
365
|
const inner = typeNode.firstNamedChild;
|
|
@@ -366,10 +367,14 @@ export const extractGenericTypeArgs = (typeNode, depth = 0) => {
|
|
|
366
367
|
return extractGenericTypeArgs(inner, depth + 1);
|
|
367
368
|
return [];
|
|
368
369
|
}
|
|
369
|
-
//
|
|
370
|
+
// Generic-bearing nodes hold their arguments in a `type_arguments` /
|
|
371
|
+
// `type_argument_list` child: generic_type (Java/TypeScript/Rust/Go),
|
|
372
|
+
// generic_name (C#), and Kotlin's user_type. Verified against the installed
|
|
373
|
+
// grammars by real parse (#1920). A user_type without its own type_arguments
|
|
374
|
+
// is unwrapped at the argsNode guard below.
|
|
370
375
|
if (typeNode.type !== 'generic_type' &&
|
|
371
|
-
typeNode.type !== '
|
|
372
|
-
typeNode.type !== '
|
|
376
|
+
typeNode.type !== 'generic_name' &&
|
|
377
|
+
typeNode.type !== 'user_type') {
|
|
373
378
|
return [];
|
|
374
379
|
}
|
|
375
380
|
// Find the type_arguments / type_argument_list child
|
|
@@ -381,8 +386,17 @@ export const extractGenericTypeArgs = (typeNode, depth = 0) => {
|
|
|
381
386
|
break;
|
|
382
387
|
}
|
|
383
388
|
}
|
|
384
|
-
if (!argsNode)
|
|
389
|
+
if (!argsNode) {
|
|
390
|
+
// A `user_type` without its own type_arguments wraps an inner type node
|
|
391
|
+
// (e.g. user_type > generic_type, or a plain user_type > type_identifier with
|
|
392
|
+
// no generics) — recurse into that child. generic_type / generic_name with no
|
|
393
|
+
// args simply have no type arguments to report.
|
|
394
|
+
if (typeNode.type === 'user_type') {
|
|
395
|
+
const inner = typeNode.firstNamedChild;
|
|
396
|
+
return inner ? extractGenericTypeArgs(inner, depth + 1) : [];
|
|
397
|
+
}
|
|
385
398
|
return [];
|
|
399
|
+
}
|
|
386
400
|
const result = [];
|
|
387
401
|
for (let i = 0; i < argsNode.namedChildCount; i++) {
|
|
388
402
|
let argNode = argsNode.namedChild(i);
|
|
@@ -27,7 +27,7 @@ function swiftNavigationSuffixName(node) {
|
|
|
27
27
|
/** Swift: let x: Foo = ... */
|
|
28
28
|
const extractDeclaration = (node, env) => {
|
|
29
29
|
// Swift property_declaration has pattern and type_annotation
|
|
30
|
-
const pattern =
|
|
30
|
+
const pattern = findChild(node, 'pattern');
|
|
31
31
|
const typeAnnotation = node.childForFieldName('type') ?? findChild(node, 'type_annotation');
|
|
32
32
|
if (!pattern || !typeAnnotation)
|
|
33
33
|
return;
|
|
@@ -41,11 +41,11 @@ const extractParameter = (node, env) => {
|
|
|
41
41
|
let nameNode = null;
|
|
42
42
|
let typeNode = null;
|
|
43
43
|
if (node.type === 'parameter') {
|
|
44
|
-
nameNode = node.childForFieldName('name')
|
|
44
|
+
nameNode = node.childForFieldName('name');
|
|
45
45
|
typeNode = node.childForFieldName('type');
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
|
-
nameNode = node.childForFieldName('name')
|
|
48
|
+
nameNode = node.childForFieldName('name');
|
|
49
49
|
typeNode = node.childForFieldName('type');
|
|
50
50
|
}
|
|
51
51
|
if (!nameNode || !typeNode)
|
|
@@ -65,7 +65,7 @@ const extractInitializer = (node, env, classNames) => {
|
|
|
65
65
|
if (node.childForFieldName('type') || findChild(node, 'type_annotation'))
|
|
66
66
|
return;
|
|
67
67
|
// Find pattern (variable name)
|
|
68
|
-
const pattern =
|
|
68
|
+
const pattern = findChild(node, 'pattern');
|
|
69
69
|
if (!pattern)
|
|
70
70
|
return;
|
|
71
71
|
const varName = extractVarName(pattern) ?? pattern.text;
|
|
@@ -117,7 +117,7 @@ const scanConstructorBinding = (node) => {
|
|
|
117
117
|
return undefined;
|
|
118
118
|
if (hasTypeAnnotation(node))
|
|
119
119
|
return undefined;
|
|
120
|
-
const pattern =
|
|
120
|
+
const pattern = findChild(node, 'pattern');
|
|
121
121
|
if (!pattern)
|
|
122
122
|
return undefined;
|
|
123
123
|
const varName = pattern.text;
|
|
@@ -269,7 +269,7 @@ const findTsIterableElementType = (iterableName, startNode, pos = 'last') => {
|
|
|
269
269
|
while (current) {
|
|
270
270
|
if (TS_FUNCTION_NODE_TYPES.has(current.type)) {
|
|
271
271
|
// Search function parameters
|
|
272
|
-
const paramsNode = current.childForFieldName('parameters')
|
|
272
|
+
const paramsNode = current.childForFieldName('parameters');
|
|
273
273
|
if (paramsNode) {
|
|
274
274
|
for (let i = 0; i < paramsNode.namedChildCount; i++) {
|
|
275
275
|
const param = paramsNode.namedChild(i);
|
|
@@ -10,6 +10,14 @@ export type SyntaxNode = Parser.SyntaxNode;
|
|
|
10
10
|
export declare const DEFINITION_CAPTURE_KEYS: readonly ["definition.function", "definition.class", "definition.interface", "definition.method", "definition.struct", "definition.enum", "definition.namespace", "definition.module", "definition.trait", "definition.impl", "definition.type", "definition.const", "definition.static", "definition.variable", "definition.typedef", "definition.macro", "definition.union", "definition.property", "definition.record", "definition.delegate", "definition.annotation", "definition.constructor", "definition.template"];
|
|
11
11
|
/** Extract the definition node from a tree-sitter query capture map. */
|
|
12
12
|
export declare const getDefinitionNodeFromCaptures: (captureMap: Record<string, SyntaxNode>) => SyntaxNode | null;
|
|
13
|
+
type QueryMatchLike = {
|
|
14
|
+
captures: Array<{
|
|
15
|
+
name: string;
|
|
16
|
+
node: SyntaxNode;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
export declare const buildConcreteTypedefDefinitionRanges: (matches: readonly QueryMatchLike[]) => Set<string>;
|
|
20
|
+
export declare const isSuppressedConcreteTypedefDuplicate: (captureMap: Record<string, SyntaxNode>, concreteTypedefRanges: ReadonlySet<string>) => boolean;
|
|
13
21
|
/**
|
|
14
22
|
* Node types that represent function/method definitions across languages.
|
|
15
23
|
* Used by parent-walk in call-processor, parse-worker, and type-env to detect
|
|
@@ -144,3 +152,4 @@ export declare function findNodeAtRange(root: SyntaxNode, range: Range, expected
|
|
|
144
152
|
* Used by every language's scope-capture path (go/python/ruby/php/rust/csharp).
|
|
145
153
|
*/
|
|
146
154
|
export declare function nodeIfType<T extends SyntaxNode>(node: T | undefined, ...types: readonly string[]): T | null;
|
|
155
|
+
export {};
|
|
@@ -37,6 +37,32 @@ export const getDefinitionNodeFromCaptures = (captureMap) => {
|
|
|
37
37
|
}
|
|
38
38
|
return null;
|
|
39
39
|
};
|
|
40
|
+
const nodeRangeKey = (node) => `${node.startPosition.row}:${node.startPosition.column}:${node.endPosition.row}:${node.endPosition.column}`;
|
|
41
|
+
const isConcreteTypedefCapture = (captureMap) => {
|
|
42
|
+
const definitionNode = getDefinitionNodeFromCaptures(captureMap);
|
|
43
|
+
return (definitionNode?.type === 'type_definition' &&
|
|
44
|
+
(captureMap['definition.struct'] !== undefined || captureMap['definition.enum'] !== undefined));
|
|
45
|
+
};
|
|
46
|
+
export const buildConcreteTypedefDefinitionRanges = (matches) => {
|
|
47
|
+
const ranges = new Set();
|
|
48
|
+
for (const match of matches) {
|
|
49
|
+
const captureMap = {};
|
|
50
|
+
for (const capture of match.captures) {
|
|
51
|
+
captureMap[capture.name] = capture.node;
|
|
52
|
+
}
|
|
53
|
+
const definitionNode = getDefinitionNodeFromCaptures(captureMap);
|
|
54
|
+
if (definitionNode && isConcreteTypedefCapture(captureMap)) {
|
|
55
|
+
ranges.add(nodeRangeKey(definitionNode));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return ranges;
|
|
59
|
+
};
|
|
60
|
+
export const isSuppressedConcreteTypedefDuplicate = (captureMap, concreteTypedefRanges) => {
|
|
61
|
+
const definitionNode = getDefinitionNodeFromCaptures(captureMap);
|
|
62
|
+
return (definitionNode?.type === 'type_definition' &&
|
|
63
|
+
captureMap['definition.typedef'] !== undefined &&
|
|
64
|
+
concreteTypedefRanges.has(nodeRangeKey(definitionNode)));
|
|
65
|
+
};
|
|
40
66
|
/**
|
|
41
67
|
* Node types that represent function/method definitions across languages.
|
|
42
68
|
* Used by parent-walk in call-processor, parse-worker, and type-env to detect
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// gitnexus/src/core/ingestion/variable-extractors/configs/dart.ts
|
|
2
2
|
import { SupportedLanguages } from '../../../../_shared/index.js';
|
|
3
|
-
import { extractSimpleTypeName } from '../../type-extractors/shared.js';
|
|
4
3
|
/**
|
|
5
4
|
* Dart variable extraction config.
|
|
6
5
|
*
|
|
@@ -43,14 +42,6 @@ function extractDartVarName(node) {
|
|
|
43
42
|
return undefined;
|
|
44
43
|
}
|
|
45
44
|
function extractDartVarType(node) {
|
|
46
|
-
for (let i = 0; i < node.namedChildCount; i++) {
|
|
47
|
-
const child = node.namedChild(i);
|
|
48
|
-
if (child?.type === 'initialized_variable_definition') {
|
|
49
|
-
const typeNode = child.childForFieldName('type');
|
|
50
|
-
if (typeNode)
|
|
51
|
-
return extractSimpleTypeName(typeNode) ?? typeNode.text?.trim();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
45
|
// Look for type_identifier directly on the node
|
|
55
46
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
56
47
|
const child = node.namedChild(i);
|
|
@@ -37,7 +37,7 @@ try {
|
|
|
37
37
|
}
|
|
38
38
|
catch { }
|
|
39
39
|
import { getLanguageFromFilename } from '../../../_shared/index.js';
|
|
40
|
-
import { FUNCTION_NODE_TYPES, getDefinitionNodeFromCaptures, findEnclosingClassInfo, findObjectLiteralBindingInfo, getLabelFromCaptures, genericFuncName, inferFunctionLabel, CLASS_CONTAINER_TYPES, } from '../utils/ast-helpers.js';
|
|
40
|
+
import { buildConcreteTypedefDefinitionRanges, FUNCTION_NODE_TYPES, getDefinitionNodeFromCaptures, findEnclosingClassInfo, findObjectLiteralBindingInfo, getLabelFromCaptures, genericFuncName, inferFunctionLabel, isSuppressedConcreteTypedefDuplicate, CLASS_CONTAINER_TYPES, } from '../utils/ast-helpers.js';
|
|
41
41
|
import { extractCallArgTypes } from '../utils/call-analysis.js';
|
|
42
42
|
import { buildTypeEnv } from '../type-env.js';
|
|
43
43
|
import { detectFrameworkFromAST } from '../framework-detection.js';
|
|
@@ -747,6 +747,7 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
|
|
|
747
747
|
logger.warn(`Query execution failed for ${file.path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
748
748
|
continue;
|
|
749
749
|
}
|
|
750
|
+
const concreteTypedefRanges = buildConcreteTypedefDefinitionRanges(matches);
|
|
750
751
|
const provider = getProvider(language);
|
|
751
752
|
// RFC #909 Ring 2: produce a `ParsedFile` for the new scope-based
|
|
752
753
|
// resolution pipeline. No-op (returns undefined) for every language
|
|
@@ -838,6 +839,8 @@ const processFileGroup = (files, language, queryString, result, onFileProcessed)
|
|
|
838
839
|
for (const c of match.captures) {
|
|
839
840
|
captureMap[c.name] = c.node;
|
|
840
841
|
}
|
|
842
|
+
if (isSuppressedConcreteTypedefDuplicate(captureMap, concreteTypedefRanges))
|
|
843
|
+
continue;
|
|
841
844
|
// Extract import paths before skipping
|
|
842
845
|
if (captureMap['import'] && captureMap['import.source']) {
|
|
843
846
|
const rawImportPath = preprocessImportPath(captureMap['import.source'].text, captureMap['import'], provider);
|
package/package.json
CHANGED