Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/extraction/grammars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const WASM_GRAMMAR_FILES: Record<GrammarLanguage, string> = {
kotlin: 'tree-sitter-kotlin.wasm',
dart: 'tree-sitter-dart.wasm',
pascal: 'tree-sitter-pascal.wasm',
mql5: 'tree-sitter-mql5.wasm'
};

/**
Expand Down Expand Up @@ -74,6 +75,9 @@ export const EXTENSION_MAP: Record<string, Language> = {
'.lpr': 'pascal',
'.dfm': 'pascal',
'.fmx': 'pascal',
'.mq5': 'mql5',
'.mqh': 'mql5',
'.mql5': 'mql5',
};

/**
Expand All @@ -99,12 +103,12 @@ export async function initGrammars(): Promise<void> {
const entries = Object.entries(WASM_GRAMMAR_FILES) as [GrammarLanguage, string][];
for (const [lang, wasmFile] of entries) {
try {
// Pascal ships its own WASM (not in tree-sitter-wasms)
const wasmPath = lang === 'pascal'
? path.join(__dirname, 'wasm', wasmFile)
: require.resolve(`tree-sitter-wasms/out/${wasmFile}`);
const language = await WasmLanguage.load(wasmPath);
languageCache.set(lang, language);
// Pascal & MQL5 ships its own WASM (not in tree-sitter-wasms)
const wasmPath = (lang === 'pascal' || lang === 'mql5')
? path.join(__dirname, 'wasm', wasmFile)
: require.resolve(`tree-sitter-wasms/out/${wasmFile}`);
const language = await WasmLanguage.load(wasmPath);
languageCache.set(lang, language);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
console.warn(`[CodeGraph] Failed to load ${lang} grammar — parsing will be unavailable: ${message}`);
Expand Down Expand Up @@ -214,6 +218,7 @@ export function getLanguageDisplayName(language: Language): string {
svelte: 'Svelte',
liquid: 'Liquid',
pascal: 'Pascal / Delphi',
mql5: 'mql5',
unknown: 'Unknown',
};
return names[language] || language;
Expand Down
69 changes: 64 additions & 5 deletions src/extraction/tree-sitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,65 @@ const EXTRACTORS: Partial<Record<Language, LanguageExtractor>> = {
return node.type === 'declConst';
},
},
mql5: {
functionTypes: ['function_definition'],
classTypes: ['class_definition'],
methodTypes: ['function_definition'],
interfaceTypes: [],
structTypes: ['struct_definition'],
enumTypes: ['enum_definition'],
typeAliasTypes: ['type'],
importTypes: ['preproc_include'],
callTypes: ['function_call'],
variableTypes: ['variable_declaration'],
nameField: 'name',
bodyField: 'block',
paramsField: 'parameter',
returnField: 'type',

getSignature: (node, source) => {
const params = getChildByField(node, 'parameter');
const returnType = getChildByField(node, 'type');

let sig = '';

if (params) {
sig += getNodeText(params, source);
}

if (returnType) {
sig = `${getNodeText(returnType, source)} ${sig}`;
}

return sig || undefined;
},

getVisibility: (_node) => {
// MQL5 n'a pas de visibilité explicite
return 'public';
},

isExported: (_node, _source) => {
// Tout est visible dans MQL5
return true;
},

isStatic: (node) => {
for (let i = 0; i < node.childCount; i++) {
const child = node.child(i);
if (child?.type === 'static') return true;
}
return false;
},

isConst: (node) => {
for (let i = 0; i < node.childCount; i++) {
const child = node.child(i);
if (child?.type === 'const') return true;
}
return false;
}
}
};

// TSX and JSX use the same extractors as their base languages
Expand Down Expand Up @@ -1392,7 +1451,7 @@ export class TreeSitterExtractor {

// Extract variable declarators based on language
if (this.language === 'typescript' || this.language === 'javascript' ||
this.language === 'tsx' || this.language === 'jsx') {
this.language === 'tsx' || this.language === 'jsx') {
// Handle lexical_declaration and variable_declaration
// These contain one or more variable_declarator children
for (let i = 0; i < node.namedChildCount; i++) {
Expand Down Expand Up @@ -1588,7 +1647,7 @@ export class TreeSitterExtractor {
let moduleName = '';

if (this.language === 'typescript' || this.language === 'javascript' ||
this.language === 'tsx' || this.language === 'jsx') {
this.language === 'tsx' || this.language === 'jsx') {
const source = getChildByField(node, 'source');
if (source) {
moduleName = getNodeText(source, this.source).replace(/['"]/g, '');
Expand Down Expand Up @@ -1689,9 +1748,9 @@ export class TreeSitterExtractor {
if (!firstChild) return getNodeText(scopedNode, this.source);

if (firstChild.type === 'identifier' ||
firstChild.type === 'crate' ||
firstChild.type === 'super' ||
firstChild.type === 'self') {
firstChild.type === 'crate' ||
firstChild.type === 'super' ||
firstChild.type === 'self') {
return getNodeText(firstChild, this.source);
} else if (firstChild.type === 'scoped_identifier') {
return getRootModule(firstChild);
Expand Down
Binary file added src/extraction/wasm/tree-sitter-mql5.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export type Language =
| 'svelte'
| 'liquid'
| 'pascal'
| 'mql5'
| 'unknown';

// =============================================================================
Expand Down