feat(tools): add bif-coverage verifier for AST/encoder/decoder drift

Static-analysis tool that cross-checks uAST.pas against
uUnitInterfaceIO.pas and the root project.xml. For every TASTStmt /
TASTExpr subclass it confirms the class has a dispatch case in
EncodeStmt/EncodeExpr and ReadStmt/ReadExpr, then walks the public
fields and ensures each is either referenced from both encoder and
decoder (`serialise`) or explicitly excluded (`safe`).

Truth is checked-in: bif-coverage.status is a flat file with one
`<TClass>.<Field>  <serialise|safe>` line per field. The default
invocation diffs the live sources against the status file and reports:

  [version]   COMPILER_ID does not match root project <version>
  [encoder]   missing (Class.Field, uAST.pas line)
  [decoder]   missing (Class.Field, uAST.pas line)
  [new]       field exists in AST but is not in the status file
  [stale]     status names a field or class the AST no longer has
  [broken]    serialise field missing from encoder or decoder
  [drift]     safe field has crept into encoder/decoder (with the
              offending uUnitInterfaceIO.pas line)

`bif-coverage --reset` regenerates the status file from current state,
inferring `serialise` when the encoder references the field and `safe`
otherwise. Use after deliberate AST or .bif format changes to
re-baseline.
This commit is contained in:
Andrew Haines 2026-06-04 15:31:10 -04:00 committed by Graeme Geldenhuys
parent 7fe0e90563
commit 56c3fe1d0b
4 changed files with 1289 additions and 0 deletions

View file

@ -15,6 +15,7 @@
<module>compiler</module>
<module>tools/migration-analyser</module>
<module>tools/kanban</module>
<module activeByDefault="false">tools/bif-coverage</module>
</modules>
<profiles>

View file

@ -0,0 +1,239 @@
# bif-coverage status - one line per public AST field.
# Format: <TClass>.<Field> <serialise|safe>
# serialise must appear in EncodeStmt/EncodeExpr AND ReadStmt/ReadExpr
# safe intentionally not serialised (set by semantic etc.)
# Regenerate from scratch with: bif-coverage --reset
# TIntLiteral (uAST.pas:36)
TIntLiteral.Value serialise
TIntLiteral.IsUInt64 safe
# TFloatLiteral (uAST.pas:44)
TFloatLiteral.Value serialise
# TStringLiteral (uAST.pas:49)
TStringLiteral.Value serialise
TStringLiteral.IsCharCoerce safe
TStringLiteral.CharOrdValue safe
# TStringSubscriptExpr (uAST.pas:56)
TStringSubscriptExpr.StrExpr serialise
TStringSubscriptExpr.IndexExpr serialise
# TArrayLiteralExpr (uAST.pas:63)
TArrayLiteralExpr.Elements serialise
# TNilLiteral (uAST.pas:70)
# TIdentExpr (uAST.pas:72)
TIdentExpr.Name serialise
TIdentExpr.IsVarParam safe
TIdentExpr.IsConstant safe
TIdentExpr.ConstValue safe
TIdentExpr.ConstString safe
TIdentExpr.IsNoArgFuncCall safe
TIdentExpr.IsGlobal safe
TIdentExpr.IsImplicitSelf safe
TIdentExpr.IsImplicitSelfMethod safe
TIdentExpr.IsMetaclassRef safe
TIdentExpr.ConstArraySymbol safe
# TFieldAccessExpr (uAST.pas:94)
TFieldAccessExpr.RecordName serialise
TFieldAccessExpr.FieldName serialise
TFieldAccessExpr.Base serialise
TFieldAccessExpr.FieldInfo safe
TFieldAccessExpr.IsConstant safe
TFieldAccessExpr.ConstValue safe
TFieldAccessExpr.ConstString safe
TFieldAccessExpr.ConstArraySymbol safe
TFieldAccessExpr.IsConstructorCall safe
TFieldAccessExpr.IsClassAccess safe
TFieldAccessExpr.PropRead safe
TFieldAccessExpr.PropOwnerType safe
TFieldAccessExpr.IsImplicitSelf safe
TFieldAccessExpr.IsMethodCall safe
TFieldAccessExpr.IsInterfaceCall safe
TFieldAccessExpr.IsGlobal safe
TFieldAccessExpr.IsClassNameAccess safe
TFieldAccessExpr.IsClassTypeAccess safe
TFieldAccessExpr.IsBuiltinToString safe
TFieldAccessExpr.IsVarParam safe
TFieldAccessExpr.PropIndexExpr serialise
TFieldAccessExpr.IsCharAccess safe
# TIsExpr (uAST.pas:125)
TIsExpr.Obj serialise
TIsExpr.TypeName serialise
# TAsExpr (uAST.pas:133)
TAsExpr.Obj serialise
TAsExpr.TypeName serialise
# TSupportsExpr (uAST.pas:142)
TSupportsExpr.Obj serialise
TSupportsExpr.IntfTypeName serialise
TSupportsExpr.OutVarName serialise
TSupportsExpr.OutVarIsGlobal safe
# TBinaryExpr (uAST.pas:158)
TBinaryExpr.Op serialise
TBinaryExpr.Left serialise
TBinaryExpr.Right serialise
# TNotExpr (uAST.pas:166)
TNotExpr.Expr serialise
# TAssignment (uAST.pas:178)
TAssignment.Name serialise
TAssignment.Expr serialise
TAssignment.IsVarParam safe
TAssignment.IsGlobal safe
TAssignment.IsWeakLhs safe
TAssignment.ImplicitSelfField safe
# TIfStmt (uAST.pas:193)
TIfStmt.Condition serialise
TIfStmt.ThenStmt serialise
TIfStmt.ElseStmt serialise
# TCompoundStmt (uAST.pas:201)
TCompoundStmt.Stmts serialise
# TWhileStmt (uAST.pas:208)
TWhileStmt.Condition serialise
TWhileStmt.Body serialise
# TRepeatStmt (uAST.pas:215)
TRepeatStmt.Body serialise
TRepeatStmt.Condition serialise
# TForStmt (uAST.pas:222)
TForStmt.VarName serialise
TForStmt.IsGlobal safe
TForStmt.StartExpr serialise
TForStmt.EndExpr serialise
TForStmt.IsDownTo serialise
TForStmt.Body serialise
# TForInStmt (uAST.pas:233)
TForInStmt.VarName serialise
TForInStmt.VarIsGlobal safe
TForInStmt.CollExpr serialise
TForInStmt.Body serialise
TForInStmt.IsArrayIter safe
TForInStmt.EnumVarName safe
TForInStmt.ResolvedEnumTypeName safe
TForInStmt.IdxVarName safe
TForInStmt.ArrayLow safe
TForInStmt.ArrayHigh safe
TForInStmt.IsDynArrayIter safe
TForInStmt.IsStringIter safe
TForInStmt.IsSetIter safe
TForInStmt.SetBitCount safe
TForInStmt.SetMaskVarName safe
# TTryFinallyStmt (uAST.pas:263)
TTryFinallyStmt.TryBody serialise
TTryFinallyStmt.FinallyBody serialise
# TTryExceptStmt (uAST.pas:280)
TTryExceptStmt.TryBody serialise
TTryExceptStmt.Handlers serialise
TTryExceptStmt.ElseBody serialise
TTryExceptStmt.ExceptBody serialise
# TRaiseStmt (uAST.pas:293)
TRaiseStmt.Expr serialise
# TExitStmt (uAST.pas:304)
TExitStmt.Value safe
TExitStmt.ResultAssign safe
# TBreakStmt (uAST.pas:312)
# TContinueStmt (uAST.pas:315)
# TCaseStmt (uAST.pas:326)
TCaseStmt.Selector serialise
TCaseStmt.Branches serialise
TCaseStmt.ElseStmt serialise
TCaseStmt.IsStringCase safe
# TFieldAssignment (uAST.pas:337)
TFieldAssignment.RecordName serialise
TFieldAssignment.FieldName serialise
TFieldAssignment.Expr serialise
TFieldAssignment.ObjExpr serialise
TFieldAssignment.FieldInfo safe
TFieldAssignment.IsClassAccess safe
TFieldAssignment.IsImplicitSelf safe
TFieldAssignment.IsGlobal safe
TFieldAssignment.IsVarParam safe
TFieldAssignment.PropIndexExpr serialise
TFieldAssignment.PropOwnerType safe
# TStaticSubscriptAssign (uAST.pas:356)
TStaticSubscriptAssign.ArrayName serialise
TStaticSubscriptAssign.IndexExpr serialise
TStaticSubscriptAssign.ValueExpr serialise
TStaticSubscriptAssign.IsGlobal safe
# TPointerWriteStmt (uAST.pas:367)
TPointerWriteStmt.PtrExpr serialise
TPointerWriteStmt.ValExpr serialise
# TProcCall (uAST.pas:375)
TProcCall.Name serialise
TProcCall.Args serialise
TProcCall.IsImplicitSelfMethod safe
TProcCall.IsIndirectCall safe
TProcCall.IndirectCallIsGlobal safe
# TFuncCallExpr (uAST.pas:388)
TFuncCallExpr.Name serialise
TFuncCallExpr.Args serialise
TFuncCallExpr.IsImplicitSelfMethod safe
TFuncCallExpr.IsIndirectCall safe
TFuncCallExpr.IndirectCallIsGlobal safe
TFuncCallExpr.IsBuiltinHasClassAttr safe
TFuncCallExpr.HasClassAttrClass safe
TFuncCallExpr.HasClassAttrAttr safe
# TIndirectFuncCallExpr (uAST.pas:414)
TIndirectFuncCallExpr.CalleeExpr safe
TIndirectFuncCallExpr.Args safe
# TDerefExpr (uAST.pas:424)
TDerefExpr.Expr serialise
# TAddrOfExpr (uAST.pas:431)
TAddrOfExpr.Expr serialise
TAddrOfExpr.ResolvedFreeRoutine safe
# TMethodCallStmt (uAST.pas:443)
TMethodCallStmt.ObjectName serialise
TMethodCallStmt.Name serialise
TMethodCallStmt.Args serialise
TMethodCallStmt.ObjExpr serialise
TMethodCallStmt.IsImplicitSelf safe
TMethodCallStmt.IsGlobal safe
TMethodCallStmt.IsVarParam safe
TMethodCallStmt.IsBuiltinToString safe
TMethodCallStmt.IsProcFieldCall safe
# TInheritedCallStmt (uAST.pas:470)
TInheritedCallStmt.Name serialise
TInheritedCallStmt.Args serialise
# TMethodCallExpr (uAST.pas:659)
TMethodCallExpr.ObjectName serialise
TMethodCallExpr.Name serialise
TMethodCallExpr.Args serialise
TMethodCallExpr.ObjExpr serialise
TMethodCallExpr.IsConstructorCall safe
TMethodCallExpr.IsGlobal safe
TMethodCallExpr.IsVarParam safe
TMethodCallExpr.IsBuiltinToString safe
TMethodCallExpr.IsBuiltinInheritsFrom safe

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project>
<name>blaise-bif-coverage</name>
<version>0.10.0-SNAPSHOT</version>
<build>
<packaging>application</packaging>
<mainSource>BifCoverage.pas</mainSource>
<executableName>bif-coverage</executableName>
<manualUnitPaths>true</manualUnitPaths>
<unitPaths>
<path>src/main/pascal</path>
<path>../../compiler/src/main/pascal</path>
</unitPaths>
</build>
</project>

File diff suppressed because it is too large Load diff