@optave/codegraph 3.11.2 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +7 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts +2 -0
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +24 -2
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/graph/builder/call-resolver.d.ts +4 -2
- package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
- package/dist/domain/graph/builder/call-resolver.js +170 -8
- package/dist/domain/graph/builder/call-resolver.js.map +1 -1
- package/dist/domain/graph/builder/cha.d.ts +61 -0
- package/dist/domain/graph/builder/cha.d.ts.map +1 -0
- package/dist/domain/graph/builder/cha.js +143 -0
- package/dist/domain/graph/builder/cha.js.map +1 -0
- package/dist/domain/graph/builder/context.d.ts +3 -0
- package/dist/domain/graph/builder/context.d.ts.map +1 -1
- package/dist/domain/graph/builder/context.js +2 -0
- package/dist/domain/graph/builder/context.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +17 -1
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +159 -5
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +73 -1
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts +2 -0
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +926 -26
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +2 -1
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.js +501 -14
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts +1 -0
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +9 -0
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/journal.js +1 -1
- package/dist/domain/graph/journal.js.map +1 -1
- package/dist/domain/graph/resolver/points-to.d.ts +53 -0
- package/dist/domain/graph/resolver/points-to.d.ts.map +1 -0
- package/dist/domain/graph/resolver/points-to.js +213 -0
- package/dist/domain/graph/resolver/points-to.js.map +1 -0
- package/dist/domain/graph/resolver/ts-resolver.d.ts +9 -0
- package/dist/domain/graph/resolver/ts-resolver.d.ts.map +1 -0
- package/dist/domain/graph/resolver/ts-resolver.js +476 -0
- package/dist/domain/graph/resolver/ts-resolver.js.map +1 -0
- package/dist/domain/parser.d.ts +10 -1
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +39 -7
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/wasm-worker-entry.js +25 -0
- package/dist/domain/wasm-worker-entry.js.map +1 -1
- package/dist/domain/wasm-worker-pool.d.ts.map +1 -1
- package/dist/domain/wasm-worker-pool.js +32 -0
- package/dist/domain/wasm-worker-pool.js.map +1 -1
- package/dist/domain/wasm-worker-protocol.d.ts +14 -1
- package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
- package/dist/extractors/c.js +3 -3
- package/dist/extractors/c.js.map +1 -1
- package/dist/extractors/clojure.js +1 -1
- package/dist/extractors/clojure.js.map +1 -1
- package/dist/extractors/cpp.js +3 -3
- package/dist/extractors/cpp.js.map +1 -1
- package/dist/extractors/csharp.d.ts.map +1 -1
- package/dist/extractors/csharp.js +37 -8
- package/dist/extractors/csharp.js.map +1 -1
- package/dist/extractors/cuda.js +3 -3
- package/dist/extractors/cuda.js.map +1 -1
- package/dist/extractors/elixir.js +6 -6
- package/dist/extractors/elixir.js.map +1 -1
- package/dist/extractors/fsharp.js +1 -1
- package/dist/extractors/fsharp.js.map +1 -1
- package/dist/extractors/go.js +5 -5
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/haskell.js +1 -1
- package/dist/extractors/haskell.js.map +1 -1
- package/dist/extractors/java.js +2 -2
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts +2 -0
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +1674 -64
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.js +5 -5
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/lua.js +1 -1
- package/dist/extractors/lua.js.map +1 -1
- package/dist/extractors/objc.js +3 -3
- package/dist/extractors/objc.js.map +1 -1
- package/dist/extractors/ocaml.js +1 -1
- package/dist/extractors/ocaml.js.map +1 -1
- package/dist/extractors/php.js +2 -2
- package/dist/extractors/php.js.map +1 -1
- package/dist/extractors/python.js +7 -7
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/ruby.js +2 -2
- package/dist/extractors/ruby.js.map +1 -1
- package/dist/extractors/scala.js +1 -1
- package/dist/extractors/scala.js.map +1 -1
- package/dist/extractors/solidity.js +1 -1
- package/dist/extractors/solidity.js.map +1 -1
- package/dist/extractors/swift.js +4 -4
- package/dist/extractors/swift.js.map +1 -1
- package/dist/extractors/zig.js +4 -4
- package/dist/extractors/zig.js.map +1 -1
- package/dist/infrastructure/config.d.ts +10 -0
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +15 -0
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/native.d.ts +11 -0
- package/dist/infrastructure/native.d.ts.map +1 -1
- package/dist/infrastructure/native.js +78 -5
- package/dist/infrastructure/native.js.map +1 -1
- package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
- package/dist/presentation/queries-cli/overview.js +5 -0
- package/dist/presentation/queries-cli/overview.js.map +1 -1
- package/dist/types.d.ts +184 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/db/migrations.ts +7 -0
- package/src/domain/analysis/module-map.ts +29 -1
- package/src/domain/graph/builder/call-resolver.ts +177 -7
- package/src/domain/graph/builder/cha.ts +175 -0
- package/src/domain/graph/builder/context.ts +3 -0
- package/src/domain/graph/builder/helpers.ts +175 -5
- package/src/domain/graph/builder/incremental.ts +79 -1
- package/src/domain/graph/builder/stages/build-edges.ts +1128 -24
- package/src/domain/graph/builder/stages/detect-changes.ts +3 -1
- package/src/domain/graph/builder/stages/native-orchestrator.ts +583 -20
- package/src/domain/graph/builder/stages/resolve-imports.ts +14 -0
- package/src/domain/graph/journal.ts +1 -1
- package/src/domain/graph/resolver/points-to.ts +254 -0
- package/src/domain/graph/resolver/ts-resolver.ts +536 -0
- package/src/domain/parser.ts +43 -5
- package/src/domain/wasm-worker-entry.ts +25 -0
- package/src/domain/wasm-worker-pool.ts +21 -0
- package/src/domain/wasm-worker-protocol.ts +14 -0
- package/src/extractors/c.ts +3 -3
- package/src/extractors/clojure.ts +1 -1
- package/src/extractors/cpp.ts +3 -3
- package/src/extractors/csharp.ts +33 -9
- package/src/extractors/cuda.ts +3 -3
- package/src/extractors/elixir.ts +6 -6
- package/src/extractors/fsharp.ts +1 -1
- package/src/extractors/go.ts +5 -5
- package/src/extractors/haskell.ts +1 -1
- package/src/extractors/java.ts +2 -2
- package/src/extractors/javascript.ts +1802 -66
- package/src/extractors/kotlin.ts +5 -5
- package/src/extractors/lua.ts +1 -1
- package/src/extractors/objc.ts +3 -3
- package/src/extractors/ocaml.ts +1 -1
- package/src/extractors/php.ts +2 -2
- package/src/extractors/python.ts +7 -7
- package/src/extractors/ruby.ts +2 -2
- package/src/extractors/scala.ts +1 -1
- package/src/extractors/solidity.ts +1 -1
- package/src/extractors/swift.ts +4 -4
- package/src/extractors/zig.ts +4 -4
- package/src/infrastructure/config.ts +15 -0
- package/src/infrastructure/native.ts +87 -5
- package/src/presentation/queries-cli/overview.ts +15 -1
- package/src/types.ts +194 -0
package/src/extractors/kotlin.ts
CHANGED
|
@@ -102,7 +102,7 @@ function collectKotlinEnumEntries(node: TreeSitterNode): SubDeclaration[] {
|
|
|
102
102
|
if (!body) return entries;
|
|
103
103
|
for (let i = 0; i < body.childCount; i++) {
|
|
104
104
|
const child = body.child(i);
|
|
105
|
-
if (
|
|
105
|
+
if (child?.type !== 'enum_entry') continue;
|
|
106
106
|
const entryName = findChild(child, 'simple_identifier');
|
|
107
107
|
if (entryName) {
|
|
108
108
|
entries.push({
|
|
@@ -122,7 +122,7 @@ function collectKotlinProperties(node: TreeSitterNode): SubDeclaration[] {
|
|
|
122
122
|
if (!body) return props;
|
|
123
123
|
for (let i = 0; i < body.childCount; i++) {
|
|
124
124
|
const child = body.child(i);
|
|
125
|
-
if (
|
|
125
|
+
if (child?.type !== 'property_declaration') continue;
|
|
126
126
|
const varDecl = findChild(child, 'variable_declaration');
|
|
127
127
|
if (!varDecl) continue;
|
|
128
128
|
const id = findChild(varDecl, 'simple_identifier');
|
|
@@ -144,7 +144,7 @@ function collectKotlinMethods(node: TreeSitterNode, className: string, ctx: Extr
|
|
|
144
144
|
if (!body) return;
|
|
145
145
|
for (let i = 0; i < body.childCount; i++) {
|
|
146
146
|
const child = body.child(i);
|
|
147
|
-
if (
|
|
147
|
+
if (child?.type !== 'function_declaration') continue;
|
|
148
148
|
const methName = findChild(child, 'simple_identifier');
|
|
149
149
|
if (methName) {
|
|
150
150
|
const params = extractKotlinParameters(child);
|
|
@@ -168,7 +168,7 @@ function collectKotlinInheritance(
|
|
|
168
168
|
): void {
|
|
169
169
|
for (let i = 0; i < node.childCount; i++) {
|
|
170
170
|
const child = node.child(i);
|
|
171
|
-
if (
|
|
171
|
+
if (child?.type !== 'delegation_specifier') continue;
|
|
172
172
|
|
|
173
173
|
// constructor_invocation > user_type > type_identifier (extends)
|
|
174
174
|
const ctorInvocation = findChild(child, 'constructor_invocation');
|
|
@@ -294,7 +294,7 @@ function extractKotlinParameters(funcNode: TreeSitterNode): SubDeclaration[] {
|
|
|
294
294
|
if (!paramList) return params;
|
|
295
295
|
for (let i = 0; i < paramList.childCount; i++) {
|
|
296
296
|
const param = paramList.child(i);
|
|
297
|
-
if (
|
|
297
|
+
if (param?.type !== 'parameter') continue;
|
|
298
298
|
const nameNode = findChild(param, 'simple_identifier');
|
|
299
299
|
if (nameNode) {
|
|
300
300
|
params.push({ name: nameNode.text, kind: 'parameter', line: param.startPosition.row + 1 });
|
package/src/extractors/lua.ts
CHANGED
|
@@ -90,7 +90,7 @@ function extractLuaParams(funcNode: TreeSitterNode): SubDeclaration[] {
|
|
|
90
90
|
|
|
91
91
|
for (let i = 0; i < paramList.childCount; i++) {
|
|
92
92
|
const param = paramList.child(i);
|
|
93
|
-
if (
|
|
93
|
+
if (param?.type !== 'identifier') continue;
|
|
94
94
|
params.push({ name: param.text, kind: 'parameter', line: param.startPosition.row + 1 });
|
|
95
95
|
}
|
|
96
96
|
return params;
|
package/src/extractors/objc.ts
CHANGED
|
@@ -468,7 +468,7 @@ function extractPropertyName(propNode: TreeSitterNode): string | null {
|
|
|
468
468
|
if (!structDecl) return null;
|
|
469
469
|
for (let i = 0; i < structDecl.childCount; i++) {
|
|
470
470
|
const child = structDecl.child(i);
|
|
471
|
-
if (
|
|
471
|
+
if (child?.type !== 'struct_declarator') continue;
|
|
472
472
|
const id = findIdentifierDeep(child);
|
|
473
473
|
if (id) return id.text;
|
|
474
474
|
}
|
|
@@ -494,7 +494,7 @@ function extractMethodParams(methodNode: TreeSitterNode): SubDeclaration[] {
|
|
|
494
494
|
const params: SubDeclaration[] = [];
|
|
495
495
|
for (let i = 0; i < methodNode.childCount; i++) {
|
|
496
496
|
const child = methodNode.child(i);
|
|
497
|
-
if (
|
|
497
|
+
if (child?.type !== 'method_parameter') continue;
|
|
498
498
|
let nameNode: TreeSitterNode | null = null;
|
|
499
499
|
for (let j = 0; j < child.childCount; j++) {
|
|
500
500
|
const inner = child.child(j);
|
|
@@ -516,7 +516,7 @@ function extractCParams(paramListNode: TreeSitterNode | null): SubDeclaration[]
|
|
|
516
516
|
if (!paramListNode) return params;
|
|
517
517
|
for (let i = 0; i < paramListNode.childCount; i++) {
|
|
518
518
|
const param = paramListNode.child(i);
|
|
519
|
-
if (
|
|
519
|
+
if (param?.type !== 'parameter_declaration') continue;
|
|
520
520
|
const nameNode = param.childForFieldName('declarator');
|
|
521
521
|
if (nameNode) {
|
|
522
522
|
const name = unwrapObjCDeclaratorName(nameNode);
|
package/src/extractors/ocaml.ts
CHANGED
|
@@ -168,7 +168,7 @@ function handleOCamlTypeDef(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
168
168
|
// type_definition contains one or more type_bindings
|
|
169
169
|
for (let i = 0; i < node.childCount; i++) {
|
|
170
170
|
const child = node.child(i);
|
|
171
|
-
if (
|
|
171
|
+
if (child?.type !== 'type_binding') continue;
|
|
172
172
|
|
|
173
173
|
const nameNode =
|
|
174
174
|
child.childForFieldName('name') ||
|
package/src/extractors/php.ts
CHANGED
|
@@ -36,7 +36,7 @@ function extractPhpParameters(fnNode: TreeSitterNode): SubDeclaration[] {
|
|
|
36
36
|
function extractPhpProperties(member: TreeSitterNode, children: SubDeclaration[]): void {
|
|
37
37
|
for (let j = 0; j < member.childCount; j++) {
|
|
38
38
|
const el = member.child(j);
|
|
39
|
-
if (
|
|
39
|
+
if (el?.type !== 'property_element') continue;
|
|
40
40
|
const varNode = findChild(el, 'variable_name');
|
|
41
41
|
if (varNode) {
|
|
42
42
|
children.push({
|
|
@@ -53,7 +53,7 @@ function extractPhpProperties(member: TreeSitterNode, children: SubDeclaration[]
|
|
|
53
53
|
function extractPhpConstants(member: TreeSitterNode, children: SubDeclaration[]): void {
|
|
54
54
|
for (let j = 0; j < member.childCount; j++) {
|
|
55
55
|
const el = member.child(j);
|
|
56
|
-
if (
|
|
56
|
+
if (el?.type !== 'const_element') continue;
|
|
57
57
|
const nameNode = el.childForFieldName('name') || findChild(el, 'name');
|
|
58
58
|
if (nameNode) {
|
|
59
59
|
children.push({
|
package/src/extractors/python.ts
CHANGED
|
@@ -291,7 +291,7 @@ function extractClassAssignment(
|
|
|
291
291
|
const assignment = findChild(child, 'assignment');
|
|
292
292
|
if (!assignment) return;
|
|
293
293
|
const left = assignment.childForFieldName('left');
|
|
294
|
-
if (
|
|
294
|
+
if (left?.type !== 'identifier' || seen.has(left.text)) return;
|
|
295
295
|
seen.add(left.text);
|
|
296
296
|
props.push({
|
|
297
297
|
name: left.text,
|
|
@@ -308,7 +308,7 @@ function extractInitProperties(
|
|
|
308
308
|
props: SubDeclaration[],
|
|
309
309
|
): void {
|
|
310
310
|
const fnName = node.childForFieldName('name');
|
|
311
|
-
if (
|
|
311
|
+
if (fnName?.text !== '__init__') return;
|
|
312
312
|
const initBody = node.childForFieldName('body') || findChild(node, 'block');
|
|
313
313
|
if (initBody) walkInitBody(initBody, seen, props);
|
|
314
314
|
}
|
|
@@ -342,11 +342,11 @@ function extractPythonClassProperties(classNode: TreeSitterNode): SubDeclaration
|
|
|
342
342
|
function walkInitBody(bodyNode: TreeSitterNode, seen: Set<string>, props: SubDeclaration[]): void {
|
|
343
343
|
for (let i = 0; i < bodyNode.childCount; i++) {
|
|
344
344
|
const stmt = bodyNode.child(i);
|
|
345
|
-
if (
|
|
345
|
+
if (stmt?.type !== 'expression_statement') continue;
|
|
346
346
|
const assignment = findChild(stmt, 'assignment');
|
|
347
347
|
if (!assignment) continue;
|
|
348
348
|
const left = assignment.childForFieldName('left');
|
|
349
|
-
if (
|
|
349
|
+
if (left?.type !== 'attribute') continue;
|
|
350
350
|
const obj = left.childForFieldName('object');
|
|
351
351
|
const attr = left.childForFieldName('attribute');
|
|
352
352
|
if (obj && obj.text === 'self' && attr && attr.type === 'identifier' && !seen.has(attr.text)) {
|
|
@@ -370,7 +370,7 @@ function handlePyTypedParam(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
370
370
|
const isDefault = node.type === 'typed_default_parameter';
|
|
371
371
|
const nameNode = isDefault ? node.childForFieldName('name') : node.child(0);
|
|
372
372
|
const typeNode = node.childForFieldName('type');
|
|
373
|
-
if (
|
|
373
|
+
if (nameNode?.type !== 'identifier' || !typeNode) return;
|
|
374
374
|
if (nameNode.text === 'self' || nameNode.text === 'cls') return;
|
|
375
375
|
const typeName = extractPythonTypeName(typeNode);
|
|
376
376
|
if (typeName && ctx.typeMap) setTypeMapEntry(ctx.typeMap, nameNode.text, typeName, 0.9);
|
|
@@ -380,7 +380,7 @@ function handlePyTypedParam(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
|
380
380
|
function handlePyAssignmentType(node: TreeSitterNode, ctx: ExtractorOutput): void {
|
|
381
381
|
const left = node.childForFieldName('left');
|
|
382
382
|
const right = node.childForFieldName('right');
|
|
383
|
-
if (
|
|
383
|
+
if (left?.type !== 'identifier' || !right || right.type !== 'call') return;
|
|
384
384
|
|
|
385
385
|
const fn = right.childForFieldName('function');
|
|
386
386
|
if (!fn) return;
|
|
@@ -391,7 +391,7 @@ function handlePyAssignmentType(node: TreeSitterNode, ctx: ExtractorOutput): voi
|
|
|
391
391
|
}
|
|
392
392
|
} else if (fn.type === 'attribute') {
|
|
393
393
|
const obj = fn.childForFieldName('object');
|
|
394
|
-
if (
|
|
394
|
+
if (obj?.type !== 'identifier') return;
|
|
395
395
|
const objName = obj.text;
|
|
396
396
|
if (objName[0] && objName[0] !== objName[0].toLowerCase() && !BUILTIN_GLOBALS_PY.has(objName)) {
|
|
397
397
|
if (ctx.typeMap) setTypeMapEntry(ctx.typeMap, left.text, objName, 0.7);
|
package/src/extractors/ruby.ts
CHANGED
|
@@ -264,7 +264,7 @@ function extractRubyBodyConstants(containerNode: TreeSitterNode): SubDeclaration
|
|
|
264
264
|
if (!body) return children;
|
|
265
265
|
for (let i = 0; i < body.childCount; i++) {
|
|
266
266
|
const child = body.child(i);
|
|
267
|
-
if (
|
|
267
|
+
if (child?.type !== 'assignment') continue;
|
|
268
268
|
const left = child.childForFieldName('left');
|
|
269
269
|
if (left && left.type === 'constant') {
|
|
270
270
|
children.push({ name: left.text, kind: 'constant', line: child.startPosition.row + 1 });
|
|
@@ -279,7 +279,7 @@ function extractRubyClassChildren(classNode: TreeSitterNode): SubDeclaration[] {
|
|
|
279
279
|
if (!body) return children;
|
|
280
280
|
for (let i = 0; i < body.childCount; i++) {
|
|
281
281
|
const child = body.child(i);
|
|
282
|
-
if (
|
|
282
|
+
if (child?.type !== 'assignment') continue;
|
|
283
283
|
const left = child.childForFieldName('left');
|
|
284
284
|
if (!left) continue;
|
|
285
285
|
if (left.type === 'instance_variable') {
|
package/src/extractors/scala.ts
CHANGED
|
@@ -263,7 +263,7 @@ function extractScalaParameters(funcNode: TreeSitterNode): SubDeclaration[] {
|
|
|
263
263
|
if (!paramList) return params;
|
|
264
264
|
for (let i = 0; i < paramList.childCount; i++) {
|
|
265
265
|
const param = paramList.child(i);
|
|
266
|
-
if (
|
|
266
|
+
if (param?.type !== 'parameter') continue;
|
|
267
267
|
const nameNode = findChild(param, 'identifier');
|
|
268
268
|
if (nameNode) {
|
|
269
269
|
params.push({ name: nameNode.text, kind: 'parameter', line: param.startPosition.row + 1 });
|
|
@@ -166,7 +166,7 @@ function extractContractMember(child: TreeSitterNode): SubDeclaration | null {
|
|
|
166
166
|
function extractInheritance(node: TreeSitterNode, name: string, ctx: ExtractorOutput): void {
|
|
167
167
|
for (let i = 0; i < node.childCount; i++) {
|
|
168
168
|
const inheritance = node.child(i);
|
|
169
|
-
if (
|
|
169
|
+
if (inheritance?.type !== 'inheritance_specifier') continue;
|
|
170
170
|
for (let j = 0; j < inheritance.childCount; j++) {
|
|
171
171
|
const child = inheritance.child(j);
|
|
172
172
|
if (!child) continue;
|
package/src/extractors/swift.ts
CHANGED
|
@@ -94,7 +94,7 @@ function collectSwiftEnumEntries(node: TreeSitterNode): SubDeclaration[] {
|
|
|
94
94
|
if (!body) return entries;
|
|
95
95
|
for (let i = 0; i < body.childCount; i++) {
|
|
96
96
|
const child = body.child(i);
|
|
97
|
-
if (
|
|
97
|
+
if (child?.type !== 'enum_entry') continue;
|
|
98
98
|
const entryName = findChild(child, 'simple_identifier');
|
|
99
99
|
if (entryName) {
|
|
100
100
|
entries.push({
|
|
@@ -114,7 +114,7 @@ function collectSwiftProperties(node: TreeSitterNode): SubDeclaration[] {
|
|
|
114
114
|
if (!body) return props;
|
|
115
115
|
for (let i = 0; i < body.childCount; i++) {
|
|
116
116
|
const child = body.child(i);
|
|
117
|
-
if (
|
|
117
|
+
if (child?.type !== 'property_declaration') continue;
|
|
118
118
|
const pattern = findChild(child, 'pattern');
|
|
119
119
|
if (!pattern) continue;
|
|
120
120
|
const propName = findChild(pattern, 'simple_identifier');
|
|
@@ -136,7 +136,7 @@ function collectSwiftMethods(node: TreeSitterNode, className: string, ctx: Extra
|
|
|
136
136
|
if (!body) return;
|
|
137
137
|
for (let i = 0; i < body.childCount; i++) {
|
|
138
138
|
const child = body.child(i);
|
|
139
|
-
if (
|
|
139
|
+
if (child?.type !== 'function_declaration') continue;
|
|
140
140
|
const methName = findChild(child, 'simple_identifier');
|
|
141
141
|
if (methName) {
|
|
142
142
|
ctx.definitions.push({
|
|
@@ -159,7 +159,7 @@ function collectSwiftInheritance(
|
|
|
159
159
|
let first = true;
|
|
160
160
|
for (let i = 0; i < node.childCount; i++) {
|
|
161
161
|
const child = node.child(i);
|
|
162
|
-
if (
|
|
162
|
+
if (child?.type !== 'inheritance_specifier') continue;
|
|
163
163
|
const userType = findChild(child, 'user_type');
|
|
164
164
|
const typeId = userType ? findChild(userType, 'type_identifier') : null;
|
|
165
165
|
if (!typeId) continue;
|
package/src/extractors/zig.ts
CHANGED
|
@@ -86,7 +86,7 @@ function extractZigParams(funcNode: TreeSitterNode): SubDeclaration[] {
|
|
|
86
86
|
|
|
87
87
|
for (let i = 0; i < paramList.childCount; i++) {
|
|
88
88
|
const param = paramList.child(i);
|
|
89
|
-
if (
|
|
89
|
+
if (param?.type !== 'parameter') continue;
|
|
90
90
|
const nameNode = findChild(param, 'identifier');
|
|
91
91
|
if (nameNode) {
|
|
92
92
|
params.push({ name: nameNode.text, kind: 'parameter', line: param.startPosition.row + 1 });
|
|
@@ -151,7 +151,7 @@ function zigContainerKind(nodeType: string): 'struct' | 'enum' | undefined {
|
|
|
151
151
|
function tryHandleZigImportDecl(node: TreeSitterNode, name: string, ctx: ExtractorOutput): boolean {
|
|
152
152
|
for (let i = 0; i < node.childCount; i++) {
|
|
153
153
|
const child = node.child(i);
|
|
154
|
-
if (
|
|
154
|
+
if (child?.type !== 'builtin_function') continue;
|
|
155
155
|
const source = extractZigImportSource(child);
|
|
156
156
|
if (source) {
|
|
157
157
|
ctx.imports.push({ source, names: [name], line: node.startPosition.row + 1 });
|
|
@@ -175,7 +175,7 @@ function extractZigContainerFields(container: TreeSitterNode): SubDeclaration[]
|
|
|
175
175
|
const fields: SubDeclaration[] = [];
|
|
176
176
|
for (let i = 0; i < container.childCount; i++) {
|
|
177
177
|
const child = container.child(i);
|
|
178
|
-
if (
|
|
178
|
+
if (child?.type !== 'container_field') continue;
|
|
179
179
|
const nameNode = child.childForFieldName('name') || findChild(child, 'identifier');
|
|
180
180
|
if (nameNode) {
|
|
181
181
|
fields.push({ name: nameNode.text, kind: 'property', line: child.startPosition.row + 1 });
|
|
@@ -191,7 +191,7 @@ function extractZigContainerMethods(
|
|
|
191
191
|
): void {
|
|
192
192
|
for (let i = 0; i < container.childCount; i++) {
|
|
193
193
|
const child = container.child(i);
|
|
194
|
-
if (
|
|
194
|
+
if (child?.type !== 'function_declaration') continue;
|
|
195
195
|
const nameNode = child.childForFieldName('name');
|
|
196
196
|
if (nameNode) {
|
|
197
197
|
ctx.definitions.push({
|
|
@@ -24,6 +24,7 @@ export const DEFAULTS = {
|
|
|
24
24
|
dbPath: '.codegraph/graph.db',
|
|
25
25
|
driftThreshold: 0.2,
|
|
26
26
|
smallFilesThreshold: 5,
|
|
27
|
+
typescriptResolver: false,
|
|
27
28
|
},
|
|
28
29
|
query: {
|
|
29
30
|
defaultDepth: 3,
|
|
@@ -79,6 +80,20 @@ export const DEFAULTS = {
|
|
|
79
80
|
briefImporterDepth: 5,
|
|
80
81
|
briefHighRiskCallers: 10,
|
|
81
82
|
briefMediumRiskCallers: 3,
|
|
83
|
+
// TODO(Phase 8.3): wire these into the points-to solver and type-propagation path
|
|
84
|
+
// once config is threaded through to extractSymbols / buildPointsToMap. Currently
|
|
85
|
+
// controlled by hardcoded constants in src/extractors/javascript.ts
|
|
86
|
+
// (MAX_PROPAGATION_DEPTH, PROPAGATION_HOP_PENALTY) and in
|
|
87
|
+
// src/domain/graph/resolver/points-to.ts (MAX_SOLVER_ITERATIONS).
|
|
88
|
+
typePropagationDepth: 3,
|
|
89
|
+
/**
|
|
90
|
+
* Maximum fixed-point iterations for the Phase 8.3 points-to solver.
|
|
91
|
+
* @reserved — currently not wired to either the WASM solver
|
|
92
|
+
* (`MAX_SOLVER_ITERATIONS` in `points-to.ts`) or the native Rust solver
|
|
93
|
+
* (`MAX_SOLVER_ITERATIONS` in `edge_builder.rs`), both of which use the
|
|
94
|
+
* same hardcoded value of 50. See the TODO comment above.
|
|
95
|
+
*/
|
|
96
|
+
pointsToMaxIterations: 50,
|
|
82
97
|
},
|
|
83
98
|
community: {
|
|
84
99
|
resolution: 1.0,
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
* to the existing WASM pipeline.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
9
10
|
import { createRequire } from 'node:module';
|
|
10
11
|
import os from 'node:os';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
11
13
|
import { EngineError, toErrorMessage } from '../shared/errors.js';
|
|
12
14
|
import type { NativeAddon } from '../types.js';
|
|
13
|
-
import { debug } from './logger.js';
|
|
15
|
+
import { debug, warn } from './logger.js';
|
|
14
16
|
|
|
15
17
|
let _cached: NativeAddon | null | undefined; // undefined = not yet tried, null = failed, NativeAddon = module
|
|
16
18
|
let _loadError: Error | null = null;
|
|
@@ -44,31 +46,107 @@ const PLATFORM_PACKAGES: Record<string, string> = {
|
|
|
44
46
|
'win32-x64': '@optave/codegraph-win32-x64-msvc',
|
|
45
47
|
};
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Map of (platform-arch[-libc]) → locally compiled binary filename.
|
|
51
|
+
* Checked before the npm package so that locally compiled Rust changes
|
|
52
|
+
* are picked up immediately in development without publishing a new release.
|
|
53
|
+
*/
|
|
54
|
+
const PLATFORM_LOCAL_BINARIES: Record<string, string> = {
|
|
55
|
+
'linux-x64-gnu': 'codegraph-core.linux-x64-gnu.node',
|
|
56
|
+
'linux-x64-musl': 'codegraph-core.linux-x64-musl.node',
|
|
57
|
+
'linux-arm64-gnu': 'codegraph-core.linux-arm64-gnu.node',
|
|
58
|
+
'linux-arm64-musl': 'codegraph-core.linux-arm64-musl.node',
|
|
59
|
+
'darwin-arm64': 'codegraph-core.darwin-arm64.node',
|
|
60
|
+
'darwin-x64': 'codegraph-core.darwin-x64.node',
|
|
61
|
+
'win32-x64': 'codegraph-core.win32-x64-msvc.node',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** Compute the platform key used to index PLATFORM_PACKAGES / PLATFORM_LOCAL_BINARIES. */
|
|
65
|
+
function resolvePlatformKey(): string {
|
|
66
|
+
const platform = os.platform();
|
|
67
|
+
const arch = os.arch();
|
|
68
|
+
return platform === 'linux' ? `${platform}-${arch}-${detectLibc()}` : `${platform}-${arch}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
47
71
|
/**
|
|
48
72
|
* Resolve the platform-specific npm package name for the native addon.
|
|
49
73
|
* Returns null if the current platform is not supported.
|
|
50
74
|
*/
|
|
51
75
|
function resolvePlatformPackage(): string | null {
|
|
52
|
-
|
|
53
|
-
const arch = os.arch();
|
|
54
|
-
const key = platform === 'linux' ? `${platform}-${arch}-${detectLibc()}` : `${platform}-${arch}`;
|
|
55
|
-
return PLATFORM_PACKAGES[key] || null;
|
|
76
|
+
return PLATFORM_PACKAGES[resolvePlatformKey()] ?? null;
|
|
56
77
|
}
|
|
57
78
|
|
|
58
79
|
/**
|
|
59
80
|
* Try to load the native napi addon.
|
|
60
81
|
* Returns the module on success, null on failure.
|
|
82
|
+
*
|
|
83
|
+
* Load order:
|
|
84
|
+
* 1. NAPI_RS_NATIVE_LIBRARY_PATH env var (explicit override)
|
|
85
|
+
* 2. locally compiled binary in crates/codegraph-core/ (dev mode — preferred
|
|
86
|
+
* over the npm package so that Rust changes are picked up immediately
|
|
87
|
+
* without publishing a new release)
|
|
88
|
+
* 3. npm platform package (production path)
|
|
61
89
|
*/
|
|
62
90
|
export function loadNative(): NativeAddon | null {
|
|
63
91
|
if (_cached !== undefined) return _cached;
|
|
64
92
|
|
|
93
|
+
const platformKey = resolvePlatformKey();
|
|
94
|
+
|
|
95
|
+
// 1. Explicit path override — highest priority. Failure is fatal: if the
|
|
96
|
+
// operator set this variable, silently loading a different binary would
|
|
97
|
+
// be harder to diagnose than an explicit error.
|
|
98
|
+
const envPath = process.env.NAPI_RS_NATIVE_LIBRARY_PATH;
|
|
99
|
+
if (envPath) {
|
|
100
|
+
try {
|
|
101
|
+
_cached = _require(envPath) as NativeAddon;
|
|
102
|
+
debug(`loadNative: loaded from NAPI_RS_NATIVE_LIBRARY_PATH: ${envPath}`);
|
|
103
|
+
return _cached;
|
|
104
|
+
} catch (err) {
|
|
105
|
+
_loadError = err as Error;
|
|
106
|
+
warn(
|
|
107
|
+
`loadNative: NAPI_RS_NATIVE_LIBRARY_PATH is set but failed to load "${envPath}": ${toErrorMessage(err as Error)}`,
|
|
108
|
+
);
|
|
109
|
+
_cached = null;
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 2. Locally compiled dev binary — preferred over npm package so that Rust
|
|
115
|
+
// changes are visible without publishing. Only used when the file exists.
|
|
116
|
+
// If the file exists but fails to load (e.g. stale ABI), we warn and halt
|
|
117
|
+
// rather than silently falling through to the npm package — that would
|
|
118
|
+
// defeat the purpose of this priority order.
|
|
119
|
+
const localFile = PLATFORM_LOCAL_BINARIES[platformKey];
|
|
120
|
+
if (localFile) {
|
|
121
|
+
const localPath = fileURLToPath(
|
|
122
|
+
new URL(`../../crates/codegraph-core/${localFile}`, import.meta.url),
|
|
123
|
+
);
|
|
124
|
+
if (existsSync(localPath)) {
|
|
125
|
+
try {
|
|
126
|
+
_cached = _require(localPath) as NativeAddon;
|
|
127
|
+
debug(`loadNative: loaded local dev binary: ${localPath}`);
|
|
128
|
+
return _cached;
|
|
129
|
+
} catch (err) {
|
|
130
|
+
_loadError = err as Error;
|
|
131
|
+
warn(
|
|
132
|
+
`loadNative: local dev binary exists but failed to load "${localPath}": ${toErrorMessage(err as Error)}`,
|
|
133
|
+
);
|
|
134
|
+
_cached = null;
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 3. Published npm platform package — production path.
|
|
65
141
|
const pkg = resolvePlatformPackage();
|
|
66
142
|
if (pkg) {
|
|
67
143
|
try {
|
|
68
144
|
_cached = _require(pkg) as NativeAddon;
|
|
145
|
+
debug(`loadNative: loaded npm package: ${pkg}`);
|
|
69
146
|
return _cached;
|
|
70
147
|
} catch (err) {
|
|
71
148
|
_loadError = err as Error;
|
|
149
|
+
debug(`loadNative: npm package ${pkg} not available: ${toErrorMessage(err as Error)}`);
|
|
72
150
|
}
|
|
73
151
|
} else {
|
|
74
152
|
_loadError = new Error(`Unsupported platform: ${os.platform()}-${os.arch()}`);
|
|
@@ -88,6 +166,10 @@ export function isNativeAvailable(): boolean {
|
|
|
88
166
|
/**
|
|
89
167
|
* Read the version from the platform-specific npm package.json.
|
|
90
168
|
* Returns null if the package is not installed or has no version.
|
|
169
|
+
*
|
|
170
|
+
* Note: always reports the npm package version. When the local dev binary or
|
|
171
|
+
* NAPI_RS_NATIVE_LIBRARY_PATH is loaded instead, this version may not match
|
|
172
|
+
* the running binary.
|
|
91
173
|
*/
|
|
92
174
|
export function getNativePackageVersion(): string | null {
|
|
93
175
|
const pkg = resolvePlatformPackage();
|
|
@@ -54,7 +54,13 @@ interface EmbeddingsInfo {
|
|
|
54
54
|
|
|
55
55
|
interface QualityInfo {
|
|
56
56
|
score: number;
|
|
57
|
-
callerCoverage: {
|
|
57
|
+
callerCoverage: {
|
|
58
|
+
ratio: number;
|
|
59
|
+
percentage: number;
|
|
60
|
+
covered: number;
|
|
61
|
+
total: number;
|
|
62
|
+
byTechnique?: Record<string, number>;
|
|
63
|
+
};
|
|
58
64
|
callConfidence: { ratio: number; highConf: number; total: number };
|
|
59
65
|
falsePositiveWarnings: { name: string; callerCount: number; file: string; line: number }[];
|
|
60
66
|
}
|
|
@@ -189,6 +195,14 @@ function printQuality(data: StatsData): void {
|
|
|
189
195
|
console.log(
|
|
190
196
|
` Caller coverage: ${(cc.ratio * 100).toFixed(1)}% (${cc.covered}/${cc.total} functions have >=1 caller)`,
|
|
191
197
|
);
|
|
198
|
+
if (cc.byTechnique && Object.keys(cc.byTechnique).length > 0) {
|
|
199
|
+
const entries = Object.entries(cc.byTechnique).sort((a, b) => b[1] - a[1]) as [
|
|
200
|
+
string,
|
|
201
|
+
number,
|
|
202
|
+
][];
|
|
203
|
+
const parts = entries.map(([k, v]) => `${k} ${v}`).join(' ');
|
|
204
|
+
console.log(` by technique: ${parts}`);
|
|
205
|
+
}
|
|
192
206
|
console.log(
|
|
193
207
|
` Call confidence: ${(cf.ratio * 100).toFixed(1)}% (${cf.highConf}/${cf.total} call edges are high-confidence)`,
|
|
194
208
|
);
|