@@ -1086,7 +1086,13 @@ export class TreeSitterExtractor {
10861086 name : string ,
10871087 node : SyntaxNode ,
10881088 extra ?: Partial < Node >
1089- ) : Node {
1089+ ) : Node | null {
1090+ // Skip nodes with empty/missing names — they are not meaningful symbols
1091+ // and would cause FK violations when edges reference them (see issue #42)
1092+ if ( ! name ) {
1093+ return null ;
1094+ }
1095+
10901096 const id = generateNodeId ( this . filePath , kind , name , node . startPosition . row + 1 ) ;
10911097
10921098 const newNode : Node = {
@@ -1209,6 +1215,7 @@ export class TreeSitterExtractor {
12091215 isAsync,
12101216 isStatic,
12111217 } ) ;
1218+ if ( ! funcNode ) return ;
12121219
12131220 // Push to stack and visit body
12141221 this . nodeStack . push ( funcNode . id ) ;
@@ -1238,6 +1245,7 @@ export class TreeSitterExtractor {
12381245 visibility,
12391246 isExported,
12401247 } ) ;
1248+ if ( ! classNode ) return ;
12411249
12421250 // Extract extends/implements
12431251 this . extractInheritance ( node , classNode . id ) ;
@@ -1291,6 +1299,7 @@ export class TreeSitterExtractor {
12911299 isAsync,
12921300 isStatic,
12931301 } ) ;
1302+ if ( ! methodNode ) return ;
12941303
12951304 // Push to stack and visit body
12961305 this . nodeStack . push ( methodNode . id ) ;
@@ -1340,6 +1349,7 @@ export class TreeSitterExtractor {
13401349 visibility,
13411350 isExported,
13421351 } ) ;
1352+ if ( ! structNode ) return ;
13431353
13441354 // Push to stack for field extraction
13451355 this . nodeStack . push ( structNode . id ) ;
@@ -2214,43 +2224,49 @@ export class TreeSitterExtractor {
22142224
22152225 if ( declClass ) {
22162226 const classNode = this . createNode ( 'class' , name , node ) ;
2217- // Extract inheritance from typeref children of declClass
2218- this . extractPascalInheritance ( declClass , classNode . id ) ;
2219- // Visit class body
2220- this . nodeStack . push ( classNode . id ) ;
2221- for ( let i = 0 ; i < declClass . namedChildCount ; i ++ ) {
2222- const child = declClass . namedChild ( i ) ;
2223- if ( child ) this . visitNode ( child ) ;
2227+ if ( classNode ) {
2228+ // Extract inheritance from typeref children of declClass
2229+ this . extractPascalInheritance ( declClass , classNode . id ) ;
2230+ // Visit class body
2231+ this . nodeStack . push ( classNode . id ) ;
2232+ for ( let i = 0 ; i < declClass . namedChildCount ; i ++ ) {
2233+ const child = declClass . namedChild ( i ) ;
2234+ if ( child ) this . visitNode ( child ) ;
2235+ }
2236+ this . nodeStack . pop ( ) ;
22242237 }
2225- this . nodeStack . pop ( ) ;
22262238 } else if ( declIntf ) {
22272239 const ifaceNode = this . createNode ( 'interface' , name , node ) ;
2228- // Visit interface members
2229- this . nodeStack . push ( ifaceNode . id ) ;
2230- for ( let i = 0 ; i < declIntf . namedChildCount ; i ++ ) {
2231- const child = declIntf . namedChild ( i ) ;
2232- if ( child ) this . visitNode ( child ) ;
2240+ if ( ifaceNode ) {
2241+ // Visit interface members
2242+ this . nodeStack . push ( ifaceNode . id ) ;
2243+ for ( let i = 0 ; i < declIntf . namedChildCount ; i ++ ) {
2244+ const child = declIntf . namedChild ( i ) ;
2245+ if ( child ) this . visitNode ( child ) ;
2246+ }
2247+ this . nodeStack . pop ( ) ;
22332248 }
2234- this . nodeStack . pop ( ) ;
22352249 } else if ( typeChild ) {
22362250 // Check if it contains a declEnum
22372251 const declEnum = typeChild . namedChildren . find (
22382252 ( c : SyntaxNode ) => c . type === 'declEnum'
22392253 ) ;
22402254 if ( declEnum ) {
22412255 const enumNode = this . createNode ( 'enum' , name , node ) ;
2242- // Extract enum members
2243- this . nodeStack . push ( enumNode . id ) ;
2244- for ( let i = 0 ; i < declEnum . namedChildCount ; i ++ ) {
2245- const child = declEnum . namedChild ( i ) ;
2246- if ( child ?. type === 'declEnumValue' ) {
2247- const memberName = getChildByField ( child , 'name' ) ;
2248- if ( memberName ) {
2249- this . createNode ( 'enum_member' , getNodeText ( memberName , this . source ) , child ) ;
2256+ if ( enumNode ) {
2257+ // Extract enum members
2258+ this . nodeStack . push ( enumNode . id ) ;
2259+ for ( let i = 0 ; i < declEnum . namedChildCount ; i ++ ) {
2260+ const child = declEnum . namedChild ( i ) ;
2261+ if ( child ?. type === 'declEnumValue' ) {
2262+ const memberName = getChildByField ( child , 'name' ) ;
2263+ if ( memberName ) {
2264+ this . createNode ( 'enum_member' , getNodeText ( memberName , this . source ) , child ) ;
2265+ }
22502266 }
22512267 }
2268+ this . nodeStack . pop ( ) ;
22522269 }
2253- this . nodeStack . pop ( ) ;
22542270 } else {
22552271 // Simple type alias: type TFoo = string / type TFoo = Integer
22562272 this . createNode ( 'type_alias' , name , node ) ;
0 commit comments