Skip to content

Commit cbdef21

Browse files
committed
feat(parser): track spans for type and declarator metadata
1 parent e3cdab4 commit cbdef21

9 files changed

Lines changed: 524 additions & 211 deletions

File tree

src/ast/builders.ts

Lines changed: 67 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ export class NodeBuilder {
136136
return { start: startPos, end: endPos }
137137
}
138138

139+
private withTypeSpan<T extends TypeSpecifier>(node: Omit<T, 'start' | 'end'>): T {
140+
return { ...node, start: 0, end: 0 } as T
141+
}
142+
139143
private positionFor(offset: number): SourcePosition {
140144
// Binary search for the line containing this offset
141145
let lo = 0
@@ -325,7 +329,7 @@ export class NodeBuilder {
325329
vlaSizeExprs: Expression[],
326330
fptrInnerPtrDepth: number,
327331
): ParamDeclaration {
328-
return { typeSpec, name, fptrParams, isConst, vlaSizeExprs, fptrInnerPtrDepth }
332+
return { typeSpec, name, nameNode: null, fptrParams, isConst, vlaSizeExprs, fptrInnerPtrDepth }
329333
}
330334

331335
// ---- Initializers ----
@@ -356,73 +360,73 @@ export class NodeBuilder {
356360

357361
// ---- Type Specifiers ----
358362
voidType(): TypeSpecifier {
359-
return { type: 'VoidType' }
363+
return this.withTypeSpan({ type: 'VoidType' })
360364
}
361365
charType(): TypeSpecifier {
362-
return { type: 'CharType' }
366+
return this.withTypeSpan({ type: 'CharType' })
363367
}
364368
shortType(): TypeSpecifier {
365-
return { type: 'ShortType' }
369+
return this.withTypeSpan({ type: 'ShortType' })
366370
}
367371
intType(): TypeSpecifier {
368-
return { type: 'IntType' }
372+
return this.withTypeSpan({ type: 'IntType' })
369373
}
370374
longType(): TypeSpecifier {
371-
return { type: 'LongType' }
375+
return this.withTypeSpan({ type: 'LongType' })
372376
}
373377
longLongType(): TypeSpecifier {
374-
return { type: 'LongLongType' }
378+
return this.withTypeSpan({ type: 'LongLongType' })
375379
}
376380
floatType(): TypeSpecifier {
377-
return { type: 'FloatType' }
381+
return this.withTypeSpan({ type: 'FloatType' })
378382
}
379383
doubleType(): TypeSpecifier {
380-
return { type: 'DoubleType' }
384+
return this.withTypeSpan({ type: 'DoubleType' })
381385
}
382386
longDoubleType(): TypeSpecifier {
383-
return { type: 'LongDoubleType' }
387+
return this.withTypeSpan({ type: 'LongDoubleType' })
384388
}
385389
signedType(): TypeSpecifier {
386-
return { type: 'SignedType' }
390+
return this.withTypeSpan({ type: 'SignedType' })
387391
}
388392
unsignedType(): TypeSpecifier {
389-
return { type: 'UnsignedType' }
393+
return this.withTypeSpan({ type: 'UnsignedType' })
390394
}
391395
unsignedCharType(): TypeSpecifier {
392-
return { type: 'UnsignedCharType' }
396+
return this.withTypeSpan({ type: 'UnsignedCharType' })
393397
}
394398
unsignedShortType(): TypeSpecifier {
395-
return { type: 'UnsignedShortType' }
399+
return this.withTypeSpan({ type: 'UnsignedShortType' })
396400
}
397401
unsignedIntType(): TypeSpecifier {
398-
return { type: 'UnsignedIntType' }
402+
return this.withTypeSpan({ type: 'UnsignedIntType' })
399403
}
400404
unsignedLongType(): TypeSpecifier {
401-
return { type: 'UnsignedLongType' }
405+
return this.withTypeSpan({ type: 'UnsignedLongType' })
402406
}
403407
unsignedLongLongType(): TypeSpecifier {
404-
return { type: 'UnsignedLongLongType' }
408+
return this.withTypeSpan({ type: 'UnsignedLongLongType' })
405409
}
406410
int128Type(): TypeSpecifier {
407-
return { type: 'Int128Type' }
411+
return this.withTypeSpan({ type: 'Int128Type' })
408412
}
409413
unsignedInt128Type(): TypeSpecifier {
410-
return { type: 'UnsignedInt128Type' }
414+
return this.withTypeSpan({ type: 'UnsignedInt128Type' })
411415
}
412416
boolType(): TypeSpecifier {
413-
return { type: 'BoolType' }
417+
return this.withTypeSpan({ type: 'BoolType' })
414418
}
415419
complexFloatType(): TypeSpecifier {
416-
return { type: 'ComplexFloatType' }
420+
return this.withTypeSpan({ type: 'ComplexFloatType' })
417421
}
418422
complexDoubleType(): TypeSpecifier {
419-
return { type: 'ComplexDoubleType' }
423+
return this.withTypeSpan({ type: 'ComplexDoubleType' })
420424
}
421425
complexLongDoubleType(): TypeSpecifier {
422-
return { type: 'ComplexLongDoubleType' }
426+
return this.withTypeSpan({ type: 'ComplexLongDoubleType' })
423427
}
424428
autoTypeType(): TypeSpecifier {
425-
return { type: 'AutoTypeType' }
429+
return this.withTypeSpan({ type: 'AutoTypeType' })
426430
}
427431

428432
structType(
@@ -432,7 +436,14 @@ export class NodeBuilder {
432436
maxFieldAlign: number | null,
433437
structAligned: number | null,
434438
): StructType {
435-
return { type: 'StructType', name, fields, isPacked, maxFieldAlign, structAligned }
439+
return this.withTypeSpan({
440+
type: 'StructType',
441+
name,
442+
fields,
443+
isPacked,
444+
maxFieldAlign,
445+
structAligned,
446+
})
436447
}
437448

438449
unionType(
@@ -442,51 +453,58 @@ export class NodeBuilder {
442453
maxFieldAlign: number | null,
443454
structAligned: number | null,
444455
): UnionType {
445-
return { type: 'UnionType', name, fields, isPacked, maxFieldAlign, structAligned }
456+
return this.withTypeSpan({
457+
type: 'UnionType',
458+
name,
459+
fields,
460+
isPacked,
461+
maxFieldAlign,
462+
structAligned,
463+
})
446464
}
447465

448466
enumType(name: string | null, variants: EnumVariant[] | null, isPacked: boolean): EnumType {
449-
return { type: 'EnumType', name, variants, isPacked }
467+
return this.withTypeSpan({ type: 'EnumType', name, variants, isPacked })
450468
}
451469

452470
typedefNameType(name: string): TypedefNameType {
453-
return { type: 'TypedefNameType', name }
471+
return this.withTypeSpan({ type: 'TypedefNameType', name })
454472
}
455473

456474
pointerType(base: TypeSpecifier, addressSpace: AddressSpace = 'Default'): PointerType {
457-
return { type: 'PointerType', base, addressSpace }
475+
return this.withTypeSpan({ type: 'PointerType', base, addressSpace })
458476
}
459477

460478
arrayType(element: TypeSpecifier, size: Expression | null): ArrayType {
461-
return { type: 'ArrayType', element, size }
479+
return this.withTypeSpan({ type: 'ArrayType', element, size })
462480
}
463481

464482
functionPointerType(
465483
returnType: TypeSpecifier,
466484
params: ParamDeclaration[],
467485
variadic: boolean,
468486
): FunctionPointerType {
469-
return { type: 'FunctionPointerType', returnType, params, variadic }
487+
return this.withTypeSpan({ type: 'FunctionPointerType', returnType, params, variadic })
470488
}
471489

472490
bareFunctionType(
473491
returnType: TypeSpecifier,
474492
params: ParamDeclaration[],
475493
variadic: boolean,
476494
): BareFunctionType {
477-
return { type: 'BareFunctionType', returnType, params, variadic }
495+
return this.withTypeSpan({ type: 'BareFunctionType', returnType, params, variadic })
478496
}
479497

480498
typeofExprType(expr: Expression): TypeofExprType {
481-
return { type: 'TypeofExprType', expr }
499+
return this.withTypeSpan({ type: 'TypeofExprType', expr })
482500
}
483501

484502
typeofTypeType(typeSpec: TypeSpecifier): TypeofTypeType {
485-
return { type: 'TypeofTypeType', typeSpec }
503+
return this.withTypeSpan({ type: 'TypeofTypeType', typeSpec })
486504
}
487505

488506
vectorType(element: TypeSpecifier, totalBytes: number): VectorType {
489-
return { type: 'VectorType', element, totalBytes }
507+
return this.withTypeSpan({ type: 'VectorType', element, totalBytes })
490508
}
491509

492510
// ---- Struct / Enum helpers ----
@@ -498,7 +516,20 @@ export class NodeBuilder {
498516
alignment: number | null,
499517
isPacked: boolean,
500518
): StructFieldDeclaration {
501-
return { typeSpec, name, bitWidth, derived, alignment, isPacked }
519+
const start = typeSpec.start
520+
const end = bitWidth?.end ?? typeSpec.end
521+
return {
522+
type: 'StructFieldDeclaration',
523+
typeSpec,
524+
name,
525+
nameNode: null,
526+
bitWidth,
527+
derived,
528+
alignment,
529+
isPacked,
530+
start,
531+
end,
532+
}
502533
}
503534

504535
enumVariant(name: string, value: Expression | null): EnumVariant {

src/ast/locations.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ function positionFor(offset: number, lineOffsets: number[], sourceLength: number
4646
function isAstNodeLike(value: unknown): value is AstNodeLike {
4747
if (typeof value !== 'object' || value === null) return false
4848
const obj = value as Record<string, unknown>
49-
return typeof obj.type === 'string' && typeof obj.start === 'number' && typeof obj.end === 'number'
49+
return (
50+
typeof obj.type === 'string' && typeof obj.start === 'number' && typeof obj.end === 'number'
51+
)
5052
}
5153

5254
export function normalizeAstLocations(root: unknown, source: string, includeLoc: boolean): void {

0 commit comments

Comments
 (0)