@monoes/monomindcli 1.6.4 → 1.6.5
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/.claude/helpers/graphify-freshen.cjs +10 -1
- package/bundled-graph/dist/src/analyze.d.ts +32 -0
- package/bundled-graph/dist/src/analyze.d.ts.map +1 -0
- package/bundled-graph/dist/src/analyze.js +297 -0
- package/bundled-graph/dist/src/analyze.js.map +1 -0
- package/bundled-graph/dist/src/build.d.ts +8 -0
- package/bundled-graph/dist/src/build.d.ts.map +1 -0
- package/bundled-graph/dist/src/build.js +73 -0
- package/bundled-graph/dist/src/build.js.map +1 -0
- package/bundled-graph/dist/src/cache.d.ts +12 -0
- package/bundled-graph/dist/src/cache.d.ts.map +1 -0
- package/bundled-graph/dist/src/cache.js +43 -0
- package/bundled-graph/dist/src/cache.js.map +1 -0
- package/bundled-graph/dist/src/cluster.d.ts +5 -0
- package/bundled-graph/dist/src/cluster.d.ts.map +1 -0
- package/bundled-graph/dist/src/cluster.js +120 -0
- package/bundled-graph/dist/src/cluster.js.map +1 -0
- package/bundled-graph/dist/src/detect.d.ts +21 -0
- package/bundled-graph/dist/src/detect.d.ts.map +1 -0
- package/bundled-graph/dist/src/detect.js +195 -0
- package/bundled-graph/dist/src/detect.js.map +1 -0
- package/bundled-graph/dist/src/export.d.ts +21 -0
- package/bundled-graph/dist/src/export.d.ts.map +1 -0
- package/bundled-graph/dist/src/export.js +68 -0
- package/bundled-graph/dist/src/export.js.map +1 -0
- package/bundled-graph/dist/src/extract/index.d.ts +20 -0
- package/bundled-graph/dist/src/extract/index.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/index.js +158 -0
- package/bundled-graph/dist/src/extract/index.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/c.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/c.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/c.js +88 -0
- package/bundled-graph/dist/src/extract/languages/c.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/cpp.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/cpp.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/cpp.js +121 -0
- package/bundled-graph/dist/src/extract/languages/cpp.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/csharp.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/csharp.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/csharp.js +121 -0
- package/bundled-graph/dist/src/extract/languages/csharp.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/go.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/go.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/go.js +181 -0
- package/bundled-graph/dist/src/extract/languages/go.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/java.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/java.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/java.js +117 -0
- package/bundled-graph/dist/src/extract/languages/java.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/kotlin.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/kotlin.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/kotlin.js +112 -0
- package/bundled-graph/dist/src/extract/languages/kotlin.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/php.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/php.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/php.js +130 -0
- package/bundled-graph/dist/src/extract/languages/php.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/python.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/python.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/python.js +230 -0
- package/bundled-graph/dist/src/extract/languages/python.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/ruby.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/ruby.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/ruby.js +120 -0
- package/bundled-graph/dist/src/extract/languages/ruby.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/rust.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/rust.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/rust.js +195 -0
- package/bundled-graph/dist/src/extract/languages/rust.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/scala.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/scala.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/scala.js +110 -0
- package/bundled-graph/dist/src/extract/languages/scala.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/swift.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/swift.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/swift.js +122 -0
- package/bundled-graph/dist/src/extract/languages/swift.js.map +1 -0
- package/bundled-graph/dist/src/extract/languages/typescript.d.ts +3 -0
- package/bundled-graph/dist/src/extract/languages/typescript.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/languages/typescript.js +295 -0
- package/bundled-graph/dist/src/extract/languages/typescript.js.map +1 -0
- package/bundled-graph/dist/src/extract/semantic.d.ts +38 -0
- package/bundled-graph/dist/src/extract/semantic.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/semantic.js +242 -0
- package/bundled-graph/dist/src/extract/semantic.js.map +1 -0
- package/bundled-graph/dist/src/extract/tree-sitter-runner.d.ts +48 -0
- package/bundled-graph/dist/src/extract/tree-sitter-runner.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/tree-sitter-runner.js +137 -0
- package/bundled-graph/dist/src/extract/tree-sitter-runner.js.map +1 -0
- package/bundled-graph/dist/src/extract/types.d.ts +7 -0
- package/bundled-graph/dist/src/extract/types.d.ts.map +1 -0
- package/bundled-graph/dist/src/extract/types.js +2 -0
- package/bundled-graph/dist/src/extract/types.js.map +1 -0
- package/bundled-graph/dist/src/index.d.ts +28 -0
- package/bundled-graph/dist/src/index.d.ts.map +1 -0
- package/bundled-graph/dist/src/index.js +26 -0
- package/bundled-graph/dist/src/index.js.map +1 -0
- package/bundled-graph/dist/src/pipeline.d.ts +27 -0
- package/bundled-graph/dist/src/pipeline.d.ts.map +1 -0
- package/bundled-graph/dist/src/pipeline.js +269 -0
- package/bundled-graph/dist/src/pipeline.js.map +1 -0
- package/bundled-graph/dist/src/report.d.ts +26 -0
- package/bundled-graph/dist/src/report.d.ts.map +1 -0
- package/bundled-graph/dist/src/report.js +214 -0
- package/bundled-graph/dist/src/report.js.map +1 -0
- package/bundled-graph/dist/src/types.d.ts +124 -0
- package/bundled-graph/dist/src/types.d.ts.map +1 -0
- package/bundled-graph/dist/src/types.js +2 -0
- package/bundled-graph/dist/src/types.js.map +1 -0
- package/bundled-graph/dist/src/visualize.d.ts +4 -0
- package/bundled-graph/dist/src/visualize.d.ts.map +1 -0
- package/bundled-graph/dist/src/visualize.js +574 -0
- package/bundled-graph/dist/src/visualize.js.map +1 -0
- package/bundled-graph/dist/tsconfig.tsbuildinfo +1 -0
- package/bundled-graph/package.json +57 -0
- package/package.json +9 -2
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { basename } from 'path';
|
|
2
|
+
import { tryLoadParser, walk } from '../tree-sitter-runner.js';
|
|
3
|
+
function nodeName(node) {
|
|
4
|
+
return node.childForFieldName('name')?.text ?? '';
|
|
5
|
+
}
|
|
6
|
+
function loc(node) {
|
|
7
|
+
return `L${node.startPosition.row + 1}`;
|
|
8
|
+
}
|
|
9
|
+
function extractWithTreeSitter(filePath, content) {
|
|
10
|
+
const nodes = [];
|
|
11
|
+
const edges = [];
|
|
12
|
+
const errors = [];
|
|
13
|
+
const parser = tryLoadParser('java');
|
|
14
|
+
if (!parser)
|
|
15
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
16
|
+
let tree;
|
|
17
|
+
try {
|
|
18
|
+
tree = parser.parse(content);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
errors.push(`tree-sitter parse error in ${filePath}: ${String(err)}`);
|
|
22
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
23
|
+
}
|
|
24
|
+
const classStack = [];
|
|
25
|
+
walk(tree.rootNode, (n) => {
|
|
26
|
+
if (n.type === 'class_declaration' || n.type === 'interface_declaration' || n.type === 'enum_declaration') {
|
|
27
|
+
const name = nodeName(n);
|
|
28
|
+
if (!name)
|
|
29
|
+
return;
|
|
30
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: loc(n) });
|
|
31
|
+
classStack.push(name);
|
|
32
|
+
// Superclass / interfaces
|
|
33
|
+
const superclass = n.childForFieldName('superclass');
|
|
34
|
+
if (superclass) {
|
|
35
|
+
edges.push({ source: name, target: superclass.text.replace(/^extends\s+/, '').trim(), relation: 'extends', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(n) });
|
|
36
|
+
}
|
|
37
|
+
const interfaces = n.childForFieldName('interfaces');
|
|
38
|
+
if (interfaces) {
|
|
39
|
+
for (const child of interfaces.children) {
|
|
40
|
+
if (child.type === 'type_identifier' || child.type === 'identifier') {
|
|
41
|
+
edges.push({ source: name, target: child.text, relation: 'implements', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(interfaces) });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (n.type === 'method_declaration') {
|
|
48
|
+
const name = nodeName(n);
|
|
49
|
+
if (!name)
|
|
50
|
+
return;
|
|
51
|
+
const qualified = classStack.length > 0 ? `${classStack[classStack.length - 1]}.${name}` : name;
|
|
52
|
+
nodes.push({ id: qualified, label: qualified, fileType: 'code', sourceFile: filePath, sourceLocation: loc(n) });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (n.type === 'import_declaration') {
|
|
56
|
+
const path = n.children.find((c) => c.type === 'scoped_identifier' || c.type === 'identifier');
|
|
57
|
+
if (path) {
|
|
58
|
+
edges.push({ source: basename(filePath), target: path.text, relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(n) });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
63
|
+
}
|
|
64
|
+
function extractWithRegex(filePath, content) {
|
|
65
|
+
const nodes = [];
|
|
66
|
+
const edges = [];
|
|
67
|
+
const lines = content.split('\n');
|
|
68
|
+
let currentClass = '';
|
|
69
|
+
lines.forEach((line, idx) => {
|
|
70
|
+
const location = `L${idx + 1}`;
|
|
71
|
+
const trimmed = line.trim();
|
|
72
|
+
// class / interface / enum
|
|
73
|
+
const classMatch = trimmed.match(/^(?:public\s+|private\s+|protected\s+|abstract\s+|final\s+|static\s+)*(?:class|interface|enum)\s+(\w+)/);
|
|
74
|
+
if (classMatch) {
|
|
75
|
+
const name = classMatch[1];
|
|
76
|
+
currentClass = name;
|
|
77
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
78
|
+
const extendsMatch = trimmed.match(/\bextends\s+(\w+)/);
|
|
79
|
+
if (extendsMatch)
|
|
80
|
+
edges.push({ source: name, target: extendsMatch[1], relation: 'extends', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
81
|
+
const implMatch = trimmed.match(/\bimplements\s+([\w,\s]+?)(?:\{|$)/);
|
|
82
|
+
if (implMatch) {
|
|
83
|
+
for (const iface of implMatch[1].split(',')) {
|
|
84
|
+
const n = iface.trim();
|
|
85
|
+
if (n)
|
|
86
|
+
edges.push({ source: name, target: n, relation: 'implements', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// method declarations
|
|
92
|
+
const methodMatch = trimmed.match(/^(?:public|private|protected|static|final|abstract|synchronized|native|strictfp|\s)*(?:[\w<>\[\]]+)\s+(\w+)\s*\(/);
|
|
93
|
+
if (methodMatch && currentClass && !trimmed.startsWith('//') && !trimmed.startsWith('*')) {
|
|
94
|
+
const name = `${currentClass}.${methodMatch[1]}`;
|
|
95
|
+
if (!['if', 'while', 'for', 'switch', 'catch'].includes(methodMatch[1])) {
|
|
96
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// imports
|
|
100
|
+
const importMatch = trimmed.match(/^import\s+(?:static\s+)?([\w.]+(?:\.\*)?);/);
|
|
101
|
+
if (importMatch) {
|
|
102
|
+
edges.push({ source: basename(filePath), target: importMatch[1], relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors: [] };
|
|
106
|
+
}
|
|
107
|
+
export const javaExtractor = {
|
|
108
|
+
language: 'java',
|
|
109
|
+
extensions: ['.java'],
|
|
110
|
+
extract(filePath, content) {
|
|
111
|
+
const ts = extractWithTreeSitter(filePath, content);
|
|
112
|
+
if (ts.nodes.length > 0 || ts.edges.length > 0 || ts.errors.length > 0)
|
|
113
|
+
return ts;
|
|
114
|
+
return extractWithRegex(filePath, content);
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=java.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"java.js","sourceRoot":"","sources":["../../../../src/extract/languages/java.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kotlin.d.ts","sourceRoot":"","sources":["../../../../src/extract/languages/kotlin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAgHrD,eAAO,MAAM,eAAe,EAAE,iBAQ7B,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { basename } from 'path';
|
|
2
|
+
import { tryLoadParser, walk } from '../tree-sitter-runner.js';
|
|
3
|
+
function nodeName(node) {
|
|
4
|
+
return node.childForFieldName('name')?.text ?? '';
|
|
5
|
+
}
|
|
6
|
+
function loc(node) {
|
|
7
|
+
return `L${node.startPosition.row + 1}`;
|
|
8
|
+
}
|
|
9
|
+
function extractWithTreeSitter(filePath, content) {
|
|
10
|
+
const nodes = [];
|
|
11
|
+
const edges = [];
|
|
12
|
+
const errors = [];
|
|
13
|
+
const parser = tryLoadParser('kotlin');
|
|
14
|
+
if (!parser)
|
|
15
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
16
|
+
let tree;
|
|
17
|
+
try {
|
|
18
|
+
tree = parser.parse(content);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
errors.push(`tree-sitter parse error in ${filePath}: ${String(err)}`);
|
|
22
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
23
|
+
}
|
|
24
|
+
const classStack = [];
|
|
25
|
+
walk(tree.rootNode, (n) => {
|
|
26
|
+
if (n.type === 'class_declaration' || n.type === 'interface_declaration' || n.type === 'object_declaration') {
|
|
27
|
+
const name = nodeName(n);
|
|
28
|
+
if (!name)
|
|
29
|
+
return;
|
|
30
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: loc(n) });
|
|
31
|
+
classStack.push(name);
|
|
32
|
+
// delegation_specifiers (: Base, Foo)
|
|
33
|
+
const delegation = n.children.find((c) => c.type === 'delegation_specifiers');
|
|
34
|
+
if (delegation) {
|
|
35
|
+
for (const spec of delegation.children) {
|
|
36
|
+
if (spec.type === 'constructor_invocation' || spec.type === 'explicit_delegation') {
|
|
37
|
+
const typeName = spec.childForFieldName('type')?.text ?? spec.children[0]?.text ?? '';
|
|
38
|
+
if (typeName)
|
|
39
|
+
edges.push({ source: name, target: typeName, relation: 'extends', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(delegation) });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (n.type === 'function_declaration') {
|
|
46
|
+
const name = nodeName(n);
|
|
47
|
+
if (!name)
|
|
48
|
+
return;
|
|
49
|
+
const qualified = classStack.length > 0 ? `${classStack[classStack.length - 1]}.${name}` : name;
|
|
50
|
+
nodes.push({ id: qualified, label: qualified, fileType: 'code', sourceFile: filePath, sourceLocation: loc(n) });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (n.type === 'import_header') {
|
|
54
|
+
const id = n.children.find((c) => c.type === 'identifier' || c.type === 'dot_qualified_expression');
|
|
55
|
+
if (id)
|
|
56
|
+
edges.push({ source: basename(filePath), target: id.text, relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(n) });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
60
|
+
}
|
|
61
|
+
function extractWithRegex(filePath, content) {
|
|
62
|
+
const nodes = [];
|
|
63
|
+
const edges = [];
|
|
64
|
+
const lines = content.split('\n');
|
|
65
|
+
let currentClass = '';
|
|
66
|
+
lines.forEach((line, idx) => {
|
|
67
|
+
const location = `L${idx + 1}`;
|
|
68
|
+
const trimmed = line.trim();
|
|
69
|
+
// import
|
|
70
|
+
const importMatch = trimmed.match(/^import\s+([\w.]+(?:\.\*)?)/);
|
|
71
|
+
if (importMatch) {
|
|
72
|
+
edges.push({ source: basename(filePath), target: importMatch[1], relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// class / interface / object / data class / sealed class
|
|
76
|
+
const classMatch = trimmed.match(/^(?:data\s+|sealed\s+|abstract\s+|open\s+|inner\s+|enum\s+|annotation\s+)*(?:class|interface|object)\s+(\w+)/);
|
|
77
|
+
if (classMatch) {
|
|
78
|
+
const name = classMatch[1];
|
|
79
|
+
currentClass = name;
|
|
80
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
81
|
+
// inheritance: class Foo : Bar(), Baz
|
|
82
|
+
const inhMatch = trimmed.match(/:\s*([\w(),\s]+?)(?:\{|$)/);
|
|
83
|
+
if (inhMatch) {
|
|
84
|
+
for (const part of inhMatch[1].split(',')) {
|
|
85
|
+
const b = part.trim().replace(/\(.*$/, '').trim();
|
|
86
|
+
if (b)
|
|
87
|
+
edges.push({ source: name, target: b, relation: 'extends', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// fun
|
|
93
|
+
const funMatch = trimmed.match(/^(?:private\s+|public\s+|protected\s+|internal\s+|override\s+|suspend\s+|inline\s+|operator\s+)*fun\s+(?:<[^>]+>\s+)?(\w+)/);
|
|
94
|
+
if (funMatch) {
|
|
95
|
+
const name = funMatch[1];
|
|
96
|
+
const qualified = currentClass ? `${currentClass}.${name}` : name;
|
|
97
|
+
nodes.push({ id: qualified, label: qualified, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors: [] };
|
|
101
|
+
}
|
|
102
|
+
export const kotlinExtractor = {
|
|
103
|
+
language: 'kotlin',
|
|
104
|
+
extensions: ['.kt', '.kts'],
|
|
105
|
+
extract(filePath, content) {
|
|
106
|
+
const ts = extractWithTreeSitter(filePath, content);
|
|
107
|
+
if (ts.nodes.length > 0 || ts.edges.length > 0 || ts.errors.length > 0)
|
|
108
|
+
return ts;
|
|
109
|
+
return extractWithRegex(filePath, content);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=kotlin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kotlin.js","sourceRoot":"","sources":["../../../../src/extract/languages/kotlin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"php.d.ts","sourceRoot":"","sources":["../../../../src/extract/languages/php.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAmIrD,eAAO,MAAM,YAAY,EAAE,iBAQ1B,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { basename } from 'path';
|
|
2
|
+
import { tryLoadParser, walk } from '../tree-sitter-runner.js';
|
|
3
|
+
function nodeName(node) {
|
|
4
|
+
return node.childForFieldName('name')?.text ?? '';
|
|
5
|
+
}
|
|
6
|
+
function loc(node) {
|
|
7
|
+
return `L${node.startPosition.row + 1}`;
|
|
8
|
+
}
|
|
9
|
+
function extractWithTreeSitter(filePath, content) {
|
|
10
|
+
const nodes = [];
|
|
11
|
+
const edges = [];
|
|
12
|
+
const errors = [];
|
|
13
|
+
const parser = tryLoadParser('php');
|
|
14
|
+
if (!parser)
|
|
15
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
16
|
+
let tree;
|
|
17
|
+
try {
|
|
18
|
+
tree = parser.parse(content);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
errors.push(`tree-sitter parse error in ${filePath}: ${String(err)}`);
|
|
22
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
23
|
+
}
|
|
24
|
+
const classStack = [];
|
|
25
|
+
walk(tree.rootNode, (n) => {
|
|
26
|
+
if (n.type === 'class_declaration' || n.type === 'interface_declaration' || n.type === 'trait_declaration') {
|
|
27
|
+
const name = nodeName(n);
|
|
28
|
+
if (!name)
|
|
29
|
+
return;
|
|
30
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: loc(n) });
|
|
31
|
+
classStack.push(name);
|
|
32
|
+
// base_clause / class_implements
|
|
33
|
+
const base = n.childForFieldName('base_clause');
|
|
34
|
+
if (base) {
|
|
35
|
+
const baseType = base.children.find((c) => c.type === 'named_type' || c.type === 'name');
|
|
36
|
+
if (baseType)
|
|
37
|
+
edges.push({ source: name, target: baseType.text, relation: 'extends', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(base) });
|
|
38
|
+
}
|
|
39
|
+
const impl = n.childForFieldName('class_implements');
|
|
40
|
+
if (impl) {
|
|
41
|
+
for (const child of impl.children) {
|
|
42
|
+
if (child.type === 'named_type' || child.type === 'name') {
|
|
43
|
+
edges.push({ source: name, target: child.text, relation: 'implements', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(impl) });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (n.type === 'method_declaration' || n.type === 'function_definition') {
|
|
50
|
+
const name = nodeName(n);
|
|
51
|
+
if (!name)
|
|
52
|
+
return;
|
|
53
|
+
const qualified = classStack.length > 0 && n.type === 'method_declaration' ? `${classStack[classStack.length - 1]}::${name}` : name;
|
|
54
|
+
nodes.push({ id: qualified, label: qualified, fileType: 'code', sourceFile: filePath, sourceLocation: loc(n) });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (n.type === 'namespace_use_declaration') {
|
|
58
|
+
for (const child of n.children) {
|
|
59
|
+
if (child.type === 'namespace_use_clause' || child.type === 'qualified_name' || child.type === 'name') {
|
|
60
|
+
const imported = child.childForFieldName('name')?.text ?? child.text;
|
|
61
|
+
if (imported && imported !== 'use') {
|
|
62
|
+
edges.push({ source: basename(filePath), target: imported, relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: loc(n) });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
69
|
+
}
|
|
70
|
+
function extractWithRegex(filePath, content) {
|
|
71
|
+
const nodes = [];
|
|
72
|
+
const edges = [];
|
|
73
|
+
const lines = content.split('\n');
|
|
74
|
+
let currentClass = '';
|
|
75
|
+
lines.forEach((line, idx) => {
|
|
76
|
+
const location = `L${idx + 1}`;
|
|
77
|
+
const trimmed = line.trim();
|
|
78
|
+
// use (namespace import)
|
|
79
|
+
const useMatch = trimmed.match(/^use\s+([\w\\]+(?:\s+as\s+\w+)?);/);
|
|
80
|
+
if (useMatch) {
|
|
81
|
+
const target = useMatch[1].split(/\s+as\s+/)[0].trim();
|
|
82
|
+
edges.push({ source: basename(filePath), target, relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// require / include
|
|
86
|
+
const requireMatch = trimmed.match(/^(?:require|include)(?:_once)?\s+['"]([^'"]+)['"]/);
|
|
87
|
+
if (requireMatch) {
|
|
88
|
+
edges.push({ source: basename(filePath), target: requireMatch[1], relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// class / interface / trait
|
|
92
|
+
const classMatch = trimmed.match(/^(?:abstract\s+|final\s+)*(?:class|interface|trait)\s+(\w+)/);
|
|
93
|
+
if (classMatch) {
|
|
94
|
+
const name = classMatch[1];
|
|
95
|
+
currentClass = name;
|
|
96
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
97
|
+
const extendsMatch = trimmed.match(/\bextends\s+(\w+)/);
|
|
98
|
+
if (extendsMatch)
|
|
99
|
+
edges.push({ source: name, target: extendsMatch[1], relation: 'extends', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
100
|
+
const implMatch = trimmed.match(/\bimplements\s+([\w,\s]+?)(?:\{|$)/);
|
|
101
|
+
if (implMatch) {
|
|
102
|
+
for (const iface of implMatch[1].split(',')) {
|
|
103
|
+
const n = iface.trim();
|
|
104
|
+
if (n)
|
|
105
|
+
edges.push({ source: name, target: n, relation: 'implements', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// function
|
|
111
|
+
const funcMatch = trimmed.match(/^(?:public\s+|private\s+|protected\s+|static\s+|abstract\s+|final\s+)*function\s+(\w+)/);
|
|
112
|
+
if (funcMatch) {
|
|
113
|
+
const name = funcMatch[1];
|
|
114
|
+
const qualified = currentClass ? `${currentClass}::${name}` : name;
|
|
115
|
+
nodes.push({ id: qualified, label: qualified, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors: [] };
|
|
119
|
+
}
|
|
120
|
+
export const phpExtractor = {
|
|
121
|
+
language: 'php',
|
|
122
|
+
extensions: ['.php', '.phtml'],
|
|
123
|
+
extract(filePath, content) {
|
|
124
|
+
const ts = extractWithTreeSitter(filePath, content);
|
|
125
|
+
if (ts.nodes.length > 0 || ts.edges.length > 0 || ts.errors.length > 0)
|
|
126
|
+
return ts;
|
|
127
|
+
return extractWithRegex(filePath, content);
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=php.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"php.js","sourceRoot":"","sources":["../../../../src/extract/languages/php.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python.d.ts","sourceRoot":"","sources":["../../../../src/extract/languages/python.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAgQrD,eAAO,MAAM,eAAe,EAAE,iBAW7B,CAAC"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { basename } from 'path';
|
|
2
|
+
import { tryLoadParser, walk, } from '../tree-sitter-runner.js';
|
|
3
|
+
// ---- helpers ----
|
|
4
|
+
function nodeName(node) {
|
|
5
|
+
const nameNode = node.childForFieldName('name');
|
|
6
|
+
return nameNode?.text ?? '';
|
|
7
|
+
}
|
|
8
|
+
function loc(node) {
|
|
9
|
+
return `L${node.startPosition.row + 1}`;
|
|
10
|
+
}
|
|
11
|
+
// ---- tree-sitter extraction ----
|
|
12
|
+
function extractWithTreeSitter(filePath, content) {
|
|
13
|
+
const nodes = [];
|
|
14
|
+
const edges = [];
|
|
15
|
+
const errors = [];
|
|
16
|
+
const parser = tryLoadParser('python');
|
|
17
|
+
if (!parser) {
|
|
18
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
19
|
+
}
|
|
20
|
+
let tree;
|
|
21
|
+
try {
|
|
22
|
+
tree = parser.parse(content);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
errors.push(`tree-sitter parse error in ${filePath}: ${String(err)}`);
|
|
26
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
27
|
+
}
|
|
28
|
+
// Track method context for call attribution
|
|
29
|
+
const functionStack = [];
|
|
30
|
+
const classStack = [];
|
|
31
|
+
walk(tree.rootNode, (n) => {
|
|
32
|
+
// ---- class definitions ----
|
|
33
|
+
if (n.type === 'class_definition') {
|
|
34
|
+
const name = nodeName(n);
|
|
35
|
+
if (name) {
|
|
36
|
+
nodes.push({
|
|
37
|
+
id: name,
|
|
38
|
+
label: name,
|
|
39
|
+
fileType: 'code',
|
|
40
|
+
sourceFile: filePath,
|
|
41
|
+
sourceLocation: loc(n),
|
|
42
|
+
});
|
|
43
|
+
classStack.push(name);
|
|
44
|
+
// Inheritance: class A(B, C):
|
|
45
|
+
const argList = n.childForFieldName('superclasses');
|
|
46
|
+
if (argList) {
|
|
47
|
+
for (const child of argList.children) {
|
|
48
|
+
if (child.type === 'identifier' || child.type === 'attribute') {
|
|
49
|
+
edges.push({
|
|
50
|
+
source: name,
|
|
51
|
+
target: child.text,
|
|
52
|
+
relation: 'extends',
|
|
53
|
+
confidence: 'EXTRACTED',
|
|
54
|
+
sourceFile: filePath,
|
|
55
|
+
sourceLocation: loc(argList),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// ---- function / async function definitions ----
|
|
64
|
+
if (n.type === 'function_definition' || n.type === 'decorated_definition') {
|
|
65
|
+
// For decorated_definition, descend to find the inner function_definition
|
|
66
|
+
const funcNode = n.type === 'decorated_definition'
|
|
67
|
+
? (n.children.find((c) => c.type === 'function_definition') ?? n)
|
|
68
|
+
: n;
|
|
69
|
+
const name = nodeName(funcNode);
|
|
70
|
+
if (name) {
|
|
71
|
+
const qualifiedName = classStack.length > 0
|
|
72
|
+
? `${classStack[classStack.length - 1]}.${name}`
|
|
73
|
+
: name;
|
|
74
|
+
nodes.push({
|
|
75
|
+
id: qualifiedName,
|
|
76
|
+
label: qualifiedName,
|
|
77
|
+
fileType: 'code',
|
|
78
|
+
sourceFile: filePath,
|
|
79
|
+
sourceLocation: loc(funcNode),
|
|
80
|
+
});
|
|
81
|
+
functionStack.push(qualifiedName);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// ---- import statements ----
|
|
86
|
+
if (n.type === 'import_statement') {
|
|
87
|
+
// import X, import X as Y
|
|
88
|
+
for (const child of n.children) {
|
|
89
|
+
if (child.type === 'dotted_name' || child.type === 'aliased_import') {
|
|
90
|
+
const importedName = child.type === 'aliased_import'
|
|
91
|
+
? child.childForFieldName('name')?.text ?? child.text
|
|
92
|
+
: child.text;
|
|
93
|
+
if (importedName) {
|
|
94
|
+
edges.push({
|
|
95
|
+
source: basename(filePath),
|
|
96
|
+
target: importedName,
|
|
97
|
+
relation: 'imports',
|
|
98
|
+
confidence: 'EXTRACTED',
|
|
99
|
+
sourceFile: filePath,
|
|
100
|
+
sourceLocation: loc(n),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
// ---- from X import Y ----
|
|
108
|
+
if (n.type === 'import_from_statement') {
|
|
109
|
+
const moduleNode = n.childForFieldName('module_name');
|
|
110
|
+
const moduleName = moduleNode?.text ?? '';
|
|
111
|
+
if (moduleName) {
|
|
112
|
+
edges.push({
|
|
113
|
+
source: basename(filePath),
|
|
114
|
+
target: moduleName,
|
|
115
|
+
relation: 'imports',
|
|
116
|
+
confidence: 'EXTRACTED',
|
|
117
|
+
sourceFile: filePath,
|
|
118
|
+
sourceLocation: loc(n),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Also emit edges for individual imported names
|
|
122
|
+
for (const child of n.children) {
|
|
123
|
+
if (child.type === 'dotted_name' || child.type === 'identifier') {
|
|
124
|
+
// Skip the module_name we already handled
|
|
125
|
+
if (child === moduleNode)
|
|
126
|
+
continue;
|
|
127
|
+
edges.push({
|
|
128
|
+
source: filePath,
|
|
129
|
+
target: child.text,
|
|
130
|
+
relation: 'imports',
|
|
131
|
+
confidence: 'EXTRACTED',
|
|
132
|
+
sourceFile: filePath,
|
|
133
|
+
sourceLocation: loc(n),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
if (child.type === 'aliased_import') {
|
|
137
|
+
const importedName = child.childForFieldName('name')?.text ?? child.text;
|
|
138
|
+
if (importedName) {
|
|
139
|
+
edges.push({
|
|
140
|
+
source: filePath,
|
|
141
|
+
target: importedName,
|
|
142
|
+
relation: 'imports',
|
|
143
|
+
confidence: 'EXTRACTED',
|
|
144
|
+
sourceFile: filePath,
|
|
145
|
+
sourceLocation: loc(n),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// ---- call expressions ----
|
|
153
|
+
if (n.type === 'call') {
|
|
154
|
+
const fnNode = n.childForFieldName('function');
|
|
155
|
+
if (!fnNode)
|
|
156
|
+
return;
|
|
157
|
+
const calleeName = fnNode.text;
|
|
158
|
+
const caller = functionStack[functionStack.length - 1] ??
|
|
159
|
+
classStack[classStack.length - 1] ??
|
|
160
|
+
basename(filePath);
|
|
161
|
+
if (calleeName && caller && calleeName !== caller) {
|
|
162
|
+
edges.push({
|
|
163
|
+
source: caller,
|
|
164
|
+
target: calleeName,
|
|
165
|
+
relation: 'calls',
|
|
166
|
+
confidence: 'INFERRED',
|
|
167
|
+
confidenceScore: 0.7,
|
|
168
|
+
sourceFile: filePath,
|
|
169
|
+
sourceLocation: loc(n),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors };
|
|
175
|
+
}
|
|
176
|
+
// ---- regex fallback ----
|
|
177
|
+
function extractWithRegex(filePath, content) {
|
|
178
|
+
const nodes = [];
|
|
179
|
+
const edges = [];
|
|
180
|
+
const lines = content.split('\n');
|
|
181
|
+
lines.forEach((line, idx) => {
|
|
182
|
+
const location = `L${idx + 1}`;
|
|
183
|
+
// class
|
|
184
|
+
const classMatch = line.match(/^class\s+(\w+)/);
|
|
185
|
+
if (classMatch) {
|
|
186
|
+
const name = classMatch[1];
|
|
187
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
188
|
+
// inheritance: class A(B, C):
|
|
189
|
+
const inheritMatch = line.match(/^class\s+\w+\(([^)]+)\)/);
|
|
190
|
+
if (inheritMatch) {
|
|
191
|
+
for (const base of inheritMatch[1].split(',')) {
|
|
192
|
+
const baseName = base.trim();
|
|
193
|
+
if (baseName && baseName !== 'object') {
|
|
194
|
+
edges.push({ source: name, target: baseName, relation: 'extends', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// function
|
|
200
|
+
const funcMatch = line.match(/^(?:async\s+)?def\s+(\w+)/);
|
|
201
|
+
if (funcMatch) {
|
|
202
|
+
const name = funcMatch[1];
|
|
203
|
+
nodes.push({ id: name, label: name, fileType: 'code', sourceFile: filePath, sourceLocation: location });
|
|
204
|
+
}
|
|
205
|
+
// import
|
|
206
|
+
const importMatch = line.match(/^import\s+(\S+)/);
|
|
207
|
+
if (importMatch) {
|
|
208
|
+
edges.push({ source: basename(filePath), target: importMatch[1], relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
209
|
+
}
|
|
210
|
+
// from X import Y
|
|
211
|
+
const fromImportMatch = line.match(/^from\s+(\S+)\s+import/);
|
|
212
|
+
if (fromImportMatch) {
|
|
213
|
+
edges.push({ source: basename(filePath), target: fromImportMatch[1], relation: 'imports', confidence: 'EXTRACTED', sourceFile: filePath, sourceLocation: location });
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
return { nodes, edges, filesProcessed: 1, fromCache: 0, errors: [] };
|
|
217
|
+
}
|
|
218
|
+
// ---- extractor implementation ----
|
|
219
|
+
export const pythonExtractor = {
|
|
220
|
+
language: 'python',
|
|
221
|
+
extensions: ['.py', '.pyw'],
|
|
222
|
+
extract(filePath, content) {
|
|
223
|
+
const tsResult = extractWithTreeSitter(filePath, content);
|
|
224
|
+
if (tsResult.nodes.length > 0 || tsResult.edges.length > 0 || tsResult.errors.length > 0) {
|
|
225
|
+
return tsResult;
|
|
226
|
+
}
|
|
227
|
+
return extractWithRegex(filePath, content);
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
//# sourceMappingURL=python.js.map
|