Skip to content

Commit 78bea55

Browse files
2dmasterclaude
andcommitted
Add tree-sitter mappers for 10 languages + full Godot file support
- Tree-sitter AST mappers: Python, Go, Rust, Java, PHP, Ruby, C#, C/C++, Bash, GDScript - Regex parsers for Godot scene/resource/project/extension file types - GDScript WASM committed to wasm/ with postinstall.js copying it into node_modules/@vscode/tree-sitter-wasm/wasm after npm install - Added .glsl to default codeInclude for Godot 4 external shader support - Ignored .mcp.json and .notes/ in .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent b795bd0 commit 78bea55

20 files changed

Lines changed: 2501 additions & 144 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ models/
99
site/node_modules
1010
site/.docusaurus
1111
site/build
12+
.mcp.json
13+
.notes/

package-lock.json

Lines changed: 53 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"test:watch": "NODE_OPTIONS='--experimental-vm-modules' jest --watch",
1919
"site:dev": "cd site && npm start",
2020
"site:build": "cd site && npm run build",
21-
"site:serve": "cd site && npm run serve"
21+
"site:serve": "cd site && npm run serve",
22+
"postinstall": "node scripts/postinstall.js"
2223
},
2324
"repository": {
2425
"type": "git",
@@ -44,6 +45,8 @@
4445
},
4546
"files": [
4647
"dist/",
48+
"wasm/",
49+
"scripts/postinstall.js",
4750
"README.md"
4851
],
4952
"publishConfig": {
@@ -69,6 +72,7 @@
6972
"pino": "^10.3.1",
7073
"pino-pretty": "^13.1.3",
7174
"redis": "^5.11.0",
75+
"tree-sitter": "^0.21.1",
7276
"web-tree-sitter": "^0.26.7",
7377
"ws": "^8.19.0",
7478
"yaml": "^2.8.2",
@@ -88,6 +92,7 @@
8892
"graphology-types": "^0.24.8",
8993
"jest": "^30.3.0",
9094
"supertest": "^7.2.2",
95+
"tree-sitter-gdscript": "^6.1.0",
9196
"ts-jest": "^29.4.6",
9297
"tsc-alias": "^1.8.16",
9398
"tsx": "^4.21.0",

scripts/postinstall.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env node
2+
'use strict';
3+
4+
const path = require('path');
5+
const fs = require('fs');
6+
7+
const src = path.join(__dirname, '..', 'wasm', 'tree-sitter-gdscript.wasm');
8+
9+
let wasmDir;
10+
try {
11+
wasmDir = path.join(path.dirname(require.resolve('@vscode/tree-sitter-wasm/package.json')), 'wasm');
12+
} catch {
13+
// @vscode/tree-sitter-wasm not installed yet — skip
14+
process.exit(0);
15+
}
16+
17+
const dest = path.join(wasmDir, 'tree-sitter-gdscript.wasm');
18+
19+
if (!fs.existsSync(dest)) {
20+
fs.copyFileSync(src, dest);
21+
console.log('graphmemory: installed tree-sitter-gdscript.wasm');
22+
}

src/graphs/file-lang.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ export const EXT_TO_LANGUAGE: Record<string, string> = {
128128
'.gd': 'gdscript',
129129
'.gdshader': 'glsl',
130130
'.gdshaderinc': 'glsl',
131+
'.tscn': 'godot-scene',
132+
'.escn': 'godot-scene',
133+
'.tres': 'godot-resource',
134+
'.godot': 'godot-project',
135+
'.gdextension': 'godot-extension',
131136

132137
// Shaders
133138
'.glsl': 'glsl',

src/lib/multi-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ const SERVER_DEFAULTS: Omit<ServerConfig, 'embedding'> & { embedding: EmbeddingC
407407

408408
const PROJECT_DEFAULTS = {
409409
docsInclude: '**/*.md',
410-
codeInclude: '**/*.{js,ts,jsx,tsx,mjs,mts,cjs,cts}',
410+
codeInclude: '**/*.{js,ts,jsx,tsx,mjs,mts,cjs,cts,gd,gdshader,gdshaderinc,glsl,tscn,escn,tres,godot,gdextension}',
411411
chunkDepth: 4,
412412
};
413413

src/lib/parsers/languages/bash.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import type { ExtractedSymbol, ExtractedEdge, ExtractedImport, LanguageMapper } from './types';
2+
import { registerLanguage } from './registry';
3+
import {
4+
type TSNode,
5+
truncate,
6+
startLine,
7+
endLine,
8+
sliceBeforeBody,
9+
buildBody,
10+
getPrecedingDoc,
11+
} from './helpers';
12+
13+
function getDoc(node: TSNode): string {
14+
return getPrecedingDoc(node, ['comment'], '#');
15+
}
16+
17+
function buildSig(node: TSNode): string {
18+
const body = node.childForFieldName('body');
19+
if (!body) return truncate(node.text ?? '');
20+
const header = sliceBeforeBody(node, body);
21+
return truncate(header ?? (node.text ?? '').split('\n')[0]);
22+
}
23+
24+
const bashMapper: LanguageMapper = {
25+
extractSymbols(rootNode: TSNode): ExtractedSymbol[] {
26+
const symbols: ExtractedSymbol[] = [];
27+
28+
function visit(node: TSNode): void {
29+
if (node.type === 'function_definition') {
30+
const nameNode = node.childForFieldName('name');
31+
const name = nameNode?.text ?? '';
32+
if (name) {
33+
const doc = getDoc(node);
34+
symbols.push({
35+
name,
36+
kind: 'function',
37+
signature: buildSig(node),
38+
docComment: doc,
39+
body: buildBody(node, doc),
40+
startLine: startLine(node),
41+
endLine: endLine(node),
42+
isExported: !name.startsWith('_'),
43+
});
44+
return; // don't recurse into function body
45+
}
46+
}
47+
for (const child of node.children ?? []) visit(child);
48+
}
49+
50+
visit(rootNode);
51+
return symbols;
52+
},
53+
54+
extractEdges(_rootNode: TSNode): ExtractedEdge[] {
55+
return [];
56+
},
57+
58+
extractImports(rootNode: TSNode): ExtractedImport[] {
59+
const imports: ExtractedImport[] = [];
60+
61+
function visit(node: TSNode): void {
62+
// source ./foo or . ./foo
63+
if (node.type === 'command') {
64+
const nameNode = node.childForFieldName('name');
65+
if (nameNode?.text === 'source' || nameNode?.text === '.') {
66+
const args = node.childForFieldName('argument');
67+
const arg = args ?? node.namedChildren?.find((c: TSNode) => c.type === 'word');
68+
if (arg) imports.push({ specifier: arg.text });
69+
}
70+
}
71+
for (const child of node.children ?? []) visit(child);
72+
}
73+
74+
visit(rootNode);
75+
return imports;
76+
},
77+
};
78+
79+
let _registered = false;
80+
81+
export function registerBash(): void {
82+
if (_registered) return;
83+
_registered = true;
84+
registerLanguage('shell', 'tree-sitter-bash.wasm', bashMapper);
85+
registerLanguage('bash', 'tree-sitter-bash.wasm', bashMapper);
86+
}

0 commit comments

Comments
 (0)