From 763e280829a638e1f5701bd8f24f2b894e12c496 Mon Sep 17 00:00:00 2001 From: Olaf Monien Date: Wed, 11 Feb 2026 12:50:58 +0100 Subject: [PATCH] fix: Fallback to filename when Pascal module name is empty Some .dpr templates use "program;" without a name, which produces an empty moduleName in the AST. Fall back to the filename (without extension) to prevent nodes with empty names that cause downstream FK constraint errors. Co-Authored-By: Claude Opus 4.6 --- __tests__/extraction.test.ts | 10 ++++++++++ src/extraction/tree-sitter.ts | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/__tests__/extraction.test.ts b/__tests__/extraction.test.ts index 7b248d4..bb758ee 100644 --- a/__tests__/extraction.test.ts +++ b/__tests__/extraction.test.ts @@ -1850,6 +1850,16 @@ describe('Pascal / Delphi Extraction', () => { expect(moduleNode).toBeDefined(); expect(moduleNode?.name).toBe('MyApp'); }); + + it('should fallback to filename when module name is empty', () => { + // Some .dpr templates use "program;" without a name + const code = `program;\nuses SysUtils;\nbegin\nend.`; + const result = extractFromSource('Console.dpr', code); + + const moduleNode = result.nodes.find((n) => n.kind === 'module'); + expect(moduleNode).toBeDefined(); + expect(moduleNode?.name).toBe('Console'); + }); }); describe('Uses clause (imports)', () => { diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index 9cf94b8..d0f9153 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -2056,10 +2056,10 @@ export class TreeSitterExtractor { const moduleNameNode = node.namedChildren.find( (c: SyntaxNode) => c.type === 'moduleName' ); - if (moduleNameNode) { - const name = getNodeText(moduleNameNode, this.source); - this.createNode('module', name, node); - } + const name = moduleNameNode ? getNodeText(moduleNameNode, this.source) : ''; + // Fallback to filename without extension if module name is empty + const moduleName = name || path.basename(this.filePath).replace(/\.[^.]+$/, ''); + this.createNode('module', moduleName, node); // Continue visiting children (interface/implementation sections) for (let i = 0; i < node.namedChildCount; i++) { const child = node.namedChild(i);