Files
go-telegram/internal/spec/overrides.go
T
lukaszraczylo 5aabbe6151 fix(codegen): parse recapitalised Array-of return sentence
Telegram rewrote the forwardMessages and copyMessages return sentence from
"an array of MessageId" to "an Array of MessageId". The pattern that handles
the "... of the sent messages is returned" shape matched lowercase only, so
both methods fell back to bool and the weekly regen job failed at the audit
step.

Add approved_any_locations to overrides.json so a union that renders as `any`
by design can be approved as data instead of a code change. Approve
InputRichMessageMedia.Media, a five-variant InputMedia union added in Bot
API 10.2 that has no declared parent type.

Make the drift test compare HEAD against itself. It compared the working tree
against HEAD, so it failed whenever a regen run added a method.
2026-07-21 22:52:06 +01:00

96 lines
2.7 KiB
Go

package spec
import (
"errors"
"fmt"
"github.com/goccy/go-json"
"os"
)
// Overrides is the schema of internal/spec/overrides.json. It lets engineers
// pin specific method returns or field types, and approve methods that
// genuinely return bool but whose doc phrasing the scraper doesn't recognise.
type Overrides struct {
// MethodReturns maps "<methodName>" → desired return TypeRef.
// Applied AFTER the scraper extracts a return type, overriding it.
MethodReturns map[string]TypeRef `json:"method_returns,omitempty"`
// FieldTypes maps "<TypeName>.<FieldName>" → desired field TypeRef.
// Applied AFTER the scraper builds the IR, overriding the field type.
FieldTypes map[string]TypeRef `json:"field_types,omitempty"`
// ApprovedBoolMethods lists methods whose returns are genuinely bool.
// The audit tool ignores these.
ApprovedBoolMethods []string `json:"approved_bool_methods,omitempty"`
// ApprovedAnyLocations lists IR locations whose union renders as `any` by
// design, keyed "<TypeName>.<FieldName>" for struct fields,
// "<methodName>.<ParamName>" for params and "<methodName>" for returns.
// The audit tool ignores these.
ApprovedAnyLocations []string `json:"approved_any_locations,omitempty"`
}
// LoadOverrides reads and parses overrides.json. Returns an empty Overrides
// (not an error) if the file does not exist.
func LoadOverrides(path string) (*Overrides, error) {
data, err := os.ReadFile(path)
if errors.Is(err, os.ErrNotExist) {
return &Overrides{}, nil
}
if err != nil {
return nil, fmt.Errorf("read %s: %w", path, err)
}
var o Overrides
if err := json.Unmarshal(data, &o); err != nil {
return nil, fmt.Errorf("parse %s: %w", path, err)
}
return &o, nil
}
// Apply patches an API in place using the overrides.
func (o *Overrides) Apply(api *API) {
if o == nil {
return
}
for i, m := range api.Methods {
if rt, ok := o.MethodReturns[m.Name]; ok {
api.Methods[i].Returns = rt
}
}
for i, t := range api.Types {
for j, f := range t.Fields {
key := t.Name + "." + f.Name
if ft, ok := o.FieldTypes[key]; ok {
api.Types[i].Fields[j].Type = ft
}
}
}
}
// IsBoolApproved reports whether methodName is on the approved bool list.
func (o *Overrides) IsBoolApproved(methodName string) bool {
if o == nil {
return false
}
for _, n := range o.ApprovedBoolMethods {
if n == methodName {
return true
}
}
return false
}
// IsAnyApproved reports whether location is on the approved `any` list.
// See ApprovedAnyLocations for the key format.
func (o *Overrides) IsAnyApproved(location string) bool {
if o == nil {
return false
}
for _, n := range o.ApprovedAnyLocations {
if n == location {
return true
}
}
return false
}