Commit 8b20770
committed
fix(generator): compile 49 of 54 specs (was 43); broaden CI gold list
Continued chasing real-world spec failures through scripts/spec-compile.sh.
49 of 54 OpenAPI 3.x specs in specs/ now compile cleanly via cargo check
(gitea is Swagger 2.0, skipped). Up from 43 in #18.
## Bugs fixed (in order of how many specs they unblocked)
1. **Wrong fallback arm for typed-error enums.** When an op had only
`default` (no specific 2xx) error responses, op_error_type emitted the
typed enum but the codegen's "no typed enum" arm tried `typed = Some(v)`
where v: serde_json::Value, mismatching the typed slot. Aligned the
conditions in client_generator.rs:1206 so the default arm becomes
`typed = None` whenever any non-2xx response exists.
2. **Indirect cycles via union wrappers.** stripe's
BankAccount → BankAccountCustomer (enum) → Customer →
BankAccountCustomer cycle wasn't direct self-reference, so my prior
self-ref Box fix didn't catch it. generate_union_enum and
generate_discriminated_enum now also Box variant payloads whose target
is in analysis.dependencies.recursive_schemas. Closed stripe (17 errs
→ 0), microsoft-graph (5 → 0), lithic (1535 → 0).
3. **Reserved std type names.** cloudflare has a schema literally named
`Result`; emitting `pub enum Result` shadows std::result::Result,
breaking every `-> Result<T, ApiOpError<...>>`. Also gcore had a
`Default` schema shadowing std::default::Default. to_rust_type_name
now appends `Type` to a small reserved-name set (Result, Option, Box,
Vec, String, Default, Clone, Debug, Send, Sync, Sized, Iterator, From,
Into, TryFrom, TryInto, AsRef, AsMut, Some, None, Ok, Err).
4. **Rust 2024 keyword `gen`.** vercel had fields/types named `gen`.
Added to is_rust_keyword.
5. **Default derive on enum with no variant matching default.** telnyx
has `default: "en"` on a language enum with values like `en-US`,
`en-AU`, … — no exact match. We were emitting `#[derive(Default)]`
without `#[default]` on any variant, triggering E0665. Now we drop
the Default derive when no variant matches.
6. **Sort-enum negative-prefix collisions.** telnyx and gcore use
`["created_at", "-created_at", "ASC", "-ASC", …]` for sort orders.
Both PascalCased to the same Rust variant, causing E0428 on the
inline param enum. generate_single_param_enum now dedupes variant
names with `_2`/`_3`/… suffixes.
7. **Per-method parameter ident collisions.** vercel's
`exclude_ids` + `exclude-ids`, modern-treasury's duplicate `name`,
twilio's `StartTime`/`StartTime>` produced E0382 (use of moved value)
and E0415 (binding declared twice) in generated bodies. Added
`ParameterInfo.rust_ident` populated by the analyzer at operation
scope; client_generator.rs consults it everywhere instead of
sanitizing param.name independently per call site.
8. **Case-sensitive operationId collision detection.** telnyx had two
ops with operationIds `getMdrUsageReports` and `GetMdrUsageReports`.
These didn't collide string-wise but PascalCased to the same Rust
ident, producing two `GetMdrUsageReportsApiError` enum definitions
(E0428). T6's collision check now compares PascalCased forms.
9. **Non-string scalars in `enum`.** gitpod has
`type: string, enum: [2000, 5000, 10000, ...]` — numeric values on a
string-typed schema. string_enum_values used to filter to .as_str()
only, producing an empty Vec → empty enum (E0665, E0004). Now
coerces non-string scalars via Display.
10. **Unresolvable $refs.** pagerduty uses
`#/components/parameters/foo/schema` (last segment `schema` isn't
a type name). google-tasks uses Swagger 2.0 carry-over
`#/definitions/Foo`. extract_schema_name now (a) recognises
`#/definitions/{X}` as an alias for `#/components/schemas/{X}`,
(b) tightens the last-segment fallback to require PascalCase and
skip JSON Schema sub-path keywords, and (c) when a ref still
can't be resolved, falls back to serde_json::Value with a stderr
warning instead of failing whole-document analysis.
11. **Nullable-anyOf wrapper collisions with the inner $ref.**
`Step.status: anyOf [$ref StepStatus, null]` synthesized a
wrapper named `StepStatus` that overwrote the actual top-level
schema. Detect `is_nullable_pattern` in property analysis and
unwrap to the inner type. When a wrapper IS needed, suffix
collisions with `Union2`/`Union3`.
12. **Type-name dedup at emission.** Defensive layer: if two
analyzed schemas PascalCase to the same Rust ident, the first
occurrence wins and later ones are silently dropped (catches
cases where analysis missed the collision).
## CI
The spec-compile job now exercises 49 specs, up from 43:
+ gcore lithic microsoft-graph stripe telnyx vercel
## Quality follow-ups tracked in `bd` (`.beads/issues.jsonl`)
- Q1 Method-name canonicalization
- Q2 Format-typed scalars (date-time, uuid, byte, binary, ipv*, uri)
- Q3 Builder pattern for ops with many parameters (depends on Q1)
- Q4 Tagged discriminator enums
- Q5 Display for ApiOpError that surfaces the typed body
All 205 unit tests still pass; clippy + fmt clean.
Refs #141 parent 5c3a44c commit 8b20770
4 files changed
Lines changed: 115 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
68 | | - | |
| 68 | + | |
69 | 69 | | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3686 | 3686 | | |
3687 | 3687 | | |
3688 | 3688 | | |
3689 | | - | |
| 3689 | + | |
| 3690 | + | |
| 3691 | + | |
| 3692 | + | |
| 3693 | + | |
| 3694 | + | |
| 3695 | + | |
| 3696 | + | |
| 3697 | + | |
| 3698 | + | |
| 3699 | + | |
| 3700 | + | |
| 3701 | + | |
| 3702 | + | |
| 3703 | + | |
| 3704 | + | |
3690 | 3705 | | |
3691 | 3706 | | |
3692 | 3707 | | |
3693 | | - | |
| 3708 | + | |
3694 | 3709 | | |
3695 | 3710 | | |
3696 | 3711 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
638 | 638 | | |
639 | 639 | | |
640 | 640 | | |
641 | | - | |
| 641 | + | |
642 | 642 | | |
643 | 643 | | |
644 | 644 | | |
| |||
648 | 648 | | |
649 | 649 | | |
650 | 650 | | |
651 | | - | |
| 651 | + | |
652 | 652 | | |
653 | 653 | | |
654 | 654 | | |
| |||
868 | 868 | | |
869 | 869 | | |
870 | 870 | | |
871 | | - | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
872 | 877 | | |
873 | 878 | | |
874 | 879 | | |
875 | 880 | | |
876 | 881 | | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
877 | 886 | | |
878 | 887 | | |
879 | 888 | | |
| |||
933 | 942 | | |
934 | 943 | | |
935 | 944 | | |
936 | | - | |
937 | | - | |
938 | | - | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
939 | 949 | | |
940 | 950 | | |
941 | | - | |
942 | | - | |
943 | | - | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
944 | 957 | | |
945 | | - | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
946 | 962 | | |
947 | 963 | | |
948 | 964 | | |
| |||
1119 | 1135 | | |
1120 | 1136 | | |
1121 | 1137 | | |
1122 | | - | |
| 1138 | + | |
1123 | 1139 | | |
1124 | 1140 | | |
| 1141 | + | |
1125 | 1142 | | |
1126 | 1143 | | |
1127 | 1144 | | |
1128 | 1145 | | |
1129 | | - | |
1130 | | - | |
1131 | 1146 | | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
1132 | 1160 | | |
1133 | 1161 | | |
1134 | | - | |
| 1162 | + | |
1135 | 1163 | | |
1136 | 1164 | | |
1137 | 1165 | | |
| |||
1224 | 1252 | | |
1225 | 1253 | | |
1226 | 1254 | | |
| 1255 | + | |
1227 | 1256 | | |
1228 | 1257 | | |
1229 | 1258 | | |
| |||
1332 | 1361 | | |
1333 | 1362 | | |
1334 | 1363 | | |
1335 | | - | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
| 1368 | + | |
| 1369 | + | |
| 1370 | + | |
| 1371 | + | |
| 1372 | + | |
1336 | 1373 | | |
1337 | 1374 | | |
1338 | 1375 | | |
| |||
1803 | 1840 | | |
1804 | 1841 | | |
1805 | 1842 | | |
| 1843 | + | |
| 1844 | + | |
| 1845 | + | |
| 1846 | + | |
| 1847 | + | |
| 1848 | + | |
| 1849 | + | |
| 1850 | + | |
| 1851 | + | |
| 1852 | + | |
| 1853 | + | |
| 1854 | + | |
| 1855 | + | |
| 1856 | + | |
| 1857 | + | |
| 1858 | + | |
| 1859 | + | |
| 1860 | + | |
| 1861 | + | |
| 1862 | + | |
| 1863 | + | |
| 1864 | + | |
| 1865 | + | |
| 1866 | + | |
| 1867 | + | |
| 1868 | + | |
| 1869 | + | |
| 1870 | + | |
| 1871 | + | |
| 1872 | + | |
| 1873 | + | |
| 1874 | + | |
| 1875 | + | |
| 1876 | + | |
1806 | 1877 | | |
1807 | 1878 | | |
1808 | 1879 | | |
| |||
1931 | 2002 | | |
1932 | 2003 | | |
1933 | 2004 | | |
| 2005 | + | |
| 2006 | + | |
1934 | 2007 | | |
1935 | 2008 | | |
1936 | 2009 | | |
| |||
0 commit comments