code-graph-llm 1.4.1 → 1.5.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/index.js +34 -17
- package/llm-code-graph.md +3 -9
- package/package.json +2 -2
- package/test/index.test.js +14 -0
package/index.js
CHANGED
|
@@ -11,22 +11,25 @@ const __dirname = path.dirname(__filename);
|
|
|
11
11
|
|
|
12
12
|
const IGNORE_FILE = '.gitignore';
|
|
13
13
|
const DEFAULT_MAP_FILE = 'llm-code-graph.md';
|
|
14
|
-
|
|
15
14
|
const SYMBOL_REGEXES = [
|
|
16
15
|
// Types, Classes, Interfaces (Universal) with Inheritance support
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
/\b(?:class|interface|type|struct|enum|protocol|extension|trait|module|namespace|object)\s+([a-zA-Z_]\w*)(?:[^\n\S]*(?:extends|implements|:|(?:\())[^\n\S]*([a-zA-Z_]\w*(?:[^\n\S]*,\s*[a-zA-Z_]\w*)*)\)?)?/g,
|
|
17
|
+
|
|
20
18
|
// Explicit Function Keywords
|
|
21
19
|
/\b(?:function|def|fn|func|fun|method|procedure|sub|routine)\s+([a-zA-Z_]\w*)/g,
|
|
22
|
-
|
|
23
|
-
// Method/Var Declarations (
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
|
|
21
|
+
// Method/Var Declarations (Java, Spring Boot, C-style)
|
|
22
|
+
// Captures: public String askAi(String question), void realFunction()
|
|
23
|
+
/\b(?:void|async|public|private|protected|static|final|native|synchronized|abstract|transient|volatile)\s+(?:[\w<>[\]]+\s+)?([a-zA-Z_]\w*)(?=\s*\([^)]*\)\s*(?:\{|=>|;|=))/g,
|
|
24
|
+
|
|
25
|
+
// Spring/Java/Dart Annotations (Captures the annotation name as a prefix)
|
|
26
|
+
/(@[a-zA-Z_]\w*(?:\([^)]*\))?)\s*(?:(?:public|private|protected|static|final|abstract|class|interface|enum|void|[\w<>[\]]+)\s+)+([a-zA-Z_]\w*)/g,
|
|
27
|
+
|
|
26
28
|
// Exported symbols
|
|
27
29
|
/\bexport\s+(?:default\s+)?(?:const|let|var|function|class|type|interface|enum|async|val)\s+([a-zA-Z_]\w*)/g
|
|
28
30
|
];
|
|
29
31
|
|
|
32
|
+
|
|
30
33
|
const EDGE_REGEXES = [
|
|
31
34
|
// Imports/Includes (JS, TS, Python, Go, Rust, C++, Java, Dart)
|
|
32
35
|
/\b(?:import|from|include|require|using)\s*(?:[\(\s])\s*['"]?([@\w\.\/\-]+)['"]?/g,
|
|
@@ -59,19 +62,30 @@ export function extractSymbolsAndInheritance(content) {
|
|
|
59
62
|
const symbols = [];
|
|
60
63
|
const inheritance = [];
|
|
61
64
|
|
|
62
|
-
// Create a version of content without comments to find symbols accurately
|
|
63
|
-
const
|
|
65
|
+
// Create a version of content without comments AND strings to find symbols accurately
|
|
66
|
+
const cleanContent = content
|
|
67
|
+
.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '')
|
|
68
|
+
.replace(/['"`](?:\\.|[^'"`])*['"`]/g, '');
|
|
64
69
|
|
|
65
70
|
for (const regex of SYMBOL_REGEXES) {
|
|
66
71
|
let match;
|
|
67
72
|
regex.lastIndex = 0;
|
|
68
|
-
while ((match = regex.exec(
|
|
73
|
+
while ((match = regex.exec(cleanContent)) !== null) {
|
|
69
74
|
if (match[1]) {
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
// Handle the Annotation regex separately (it has 2 groups)
|
|
76
|
+
let symbolName = match[1];
|
|
77
|
+
let annotation = '';
|
|
78
|
+
|
|
79
|
+
if (symbolName.startsWith('@')) {
|
|
80
|
+
annotation = symbolName;
|
|
81
|
+
symbolName = match[2] || '';
|
|
82
|
+
if (!symbolName) continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (['if', 'for', 'while', 'switch', 'return', 'await', 'yield', 'const', 'new', 'let', 'var', 'class', 'void', 'public', 'private', 'protected'].includes(symbolName)) continue;
|
|
72
86
|
|
|
73
|
-
// Capture inheritance if present (match[2])
|
|
74
|
-
if (match[2]) {
|
|
87
|
+
// Capture inheritance if present (match[2] only for non-annotation regex)
|
|
88
|
+
if (!annotation && match[2]) {
|
|
75
89
|
const parents = match[2].split(',').map(p => p.trim());
|
|
76
90
|
parents.forEach(parent => {
|
|
77
91
|
inheritance.push({ child: symbolName, parent });
|
|
@@ -94,6 +108,7 @@ export function extractSymbolsAndInheritance(content) {
|
|
|
94
108
|
if (clean) comment = clean + (comment ? ' ' + comment : '');
|
|
95
109
|
if (comment.length > 100) break;
|
|
96
110
|
} else if (line === '' && comment === '') continue;
|
|
111
|
+
else if (line.startsWith('@')) continue; // Skip annotations in comment search
|
|
97
112
|
else break;
|
|
98
113
|
}
|
|
99
114
|
|
|
@@ -106,7 +121,8 @@ export function extractSymbolsAndInheritance(content) {
|
|
|
106
121
|
}
|
|
107
122
|
}
|
|
108
123
|
|
|
109
|
-
|
|
124
|
+
const displaySymbol = annotation ? `${annotation} ${symbolName}` : symbolName;
|
|
125
|
+
symbols.push(context ? `${displaySymbol} [${context}]` : displaySymbol);
|
|
110
126
|
}
|
|
111
127
|
}
|
|
112
128
|
}
|
|
@@ -125,7 +141,8 @@ export function extractEdges(content) {
|
|
|
125
141
|
while ((match = regex.exec(noComments)) !== null) {
|
|
126
142
|
if (match[1]) {
|
|
127
143
|
const dep = match[1];
|
|
128
|
-
|
|
144
|
+
// Filter out obvious noise, common library names, or keywords
|
|
145
|
+
if (dep.length > 1 && !['style', 'react', 'vue', 'flutter', 'new', 'const', 'let', 'var', 'dependencies', 'from', 'import'].includes(dep.toLowerCase())) {
|
|
129
146
|
dependencies.add(dep);
|
|
130
147
|
}
|
|
131
148
|
}
|
package/llm-code-graph.md
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
# CODE_GRAPH_MAP
|
|
2
2
|
> LLM_ONLY: DO NOT EDIT. COMPACT PROJECT MAP.
|
|
3
3
|
|
|
4
|
-
- index.js | desc: Contains
|
|
5
|
-
- syms: [SUPPORTED_EXTENSIONS [= [], extractSymbolsAndInheritance [(content)], generate [(cwd = process.cwd()], getIgnores [(cwd, additionalLines = [])],
|
|
6
|
-
- test/index.test.js
|
|
7
|
-
- syms: [AdminUser [extends BaseUser], IRepository [implements IBase], MyWidget [: StatelessWidget], ignored [by subdir/.gitignore], included [.js'), 'function included()], noDocFunc [(arg1: string, arg2: number)], realFunction [()], testFunc [This is a test function]]
|
|
4
|
+
- index.js | desc: Contains 5 symbols.
|
|
5
|
+
- syms: [SUPPORTED_EXTENSIONS [= [], extractSymbolsAndInheritance [(content)], generate [(cwd = process.cwd()], getIgnores [(cwd, additionalLines = [])], walk [(dir, ig)]]
|
|
6
|
+
- test/index.test.js
|
|
8
7
|
|
|
9
8
|
## GRAPH EDGES
|
|
10
|
-
[AdminUser] -> [inherits] -> [BaseUser]
|
|
11
|
-
[IRepository] -> [inherits] -> [IBase]
|
|
12
|
-
[MyWidget] -> [inherits] -> [StatelessWidget]
|
|
13
9
|
[index.js] -> [imports] -> [chokidar]
|
|
14
|
-
[index.js] -> [imports] -> [dependencies]
|
|
15
10
|
[index.js] -> [imports] -> [fs]
|
|
16
11
|
[index.js] -> [imports] -> [ignore]
|
|
17
|
-
[index.js] -> [imports] -> [new]
|
|
18
12
|
[index.js] -> [imports] -> [path]
|
|
19
13
|
[index.js] -> [imports] -> [url]
|
|
20
14
|
[test/index.test.js] -> [imports] -> [../index.js]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-graph-llm",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Compact, language-agnostic codebase mapper for LLM token efficiency.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
|
-
"url": "https://github.com/
|
|
21
|
+
"url": "https://github.com/jabhijeet/code-graph.git"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"chokidar": "^3.6.0",
|
package/test/index.test.js
CHANGED
|
@@ -67,6 +67,20 @@ test('extractEdges - Imports and includes', () => {
|
|
|
67
67
|
assert.ok(edges.includes('header.h'));
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
+
test('extractSymbols - Java/Spring Annotations', () => {
|
|
71
|
+
const code = `
|
|
72
|
+
@RestController
|
|
73
|
+
public class MyController {
|
|
74
|
+
@GetMapping("/test")
|
|
75
|
+
public String hello() { return "hi"; }
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
const { symbols } = extractSymbolsAndInheritance(code);
|
|
79
|
+
assert.ok(symbols.some(s => s.includes('@RestController MyController')));
|
|
80
|
+
// Note: Strings are stripped during extraction to avoid false positives
|
|
81
|
+
assert.ok(symbols.some(s => s.includes('@GetMapping() hello')));
|
|
82
|
+
});
|
|
83
|
+
|
|
70
84
|
test('getIgnores - Default Patterns', () => {
|
|
71
85
|
const ig = getIgnores(process.cwd());
|
|
72
86
|
assert.strictEqual(ig.ignores('.git/'), true);
|