fix(scanner): honor signed numeric constants in swagger:enum - #75
Conversation
|
Thank you. I was precisely writing up a similar fix. The point is that enums are in a bad state (they've always been). So your fix addresses the bug you've reported, but it's a narrow sub-case of a wider problem. I realized that yesterday when investigating your issue. Your commit looks very close to the very first commit of a wider fix about enums. Let's see how it goes today. If the larger fix can be safely merged, tested and fully documented I'll pick mine. Otherwise I'll pick yours as a quick fix to release by monday. Does it sound like a plan? |
Go's scanner never produces a negative numeric literal: `-1` is a unary minus applied to the literal `1`, so a signed const reached the enum collector as *ast.UnaryExpr. findEnumValue type-asserted *ast.BasicLit and skipped anything else, silently dropping every signed member — the enum for a type with `-1`, `0` and `1` came out as `[0, 1]`. Unwrap a sign (`-` or `+`) around an INT or FLOAT literal and fold it into the text handed to strconv, so the whole int64 range round-trips: `-9223372036854775808` parses, whereas negating a parsed `9223372036854775808` would overflow. Integers are now parsed with base 0, reading the literal exactly as Go wrote it. Base 10 rejected the `0x`, `0b` and `0o` prefixes and `_` digit separators outright, and read the legacy `017` octal form as 17 where Go means 15. A literal whose text does not parse is now reported as unsupported and skipped. It previously became a nil enum member, which puts a null in the emitted spec and can panic go-openapi/spec, whose enum handling reflects on the first member. Identifiers, including iota-derived constants, remain uncollected: they need go/types const evaluation, which is out of scope here. contributes go-swagger/go-swagger#3412 Signed-off-by: phatlc <phatle.hsd@gmail.com>
7a59398 to
e3d4994
Compare
Sounds good — a wider fix is the better outcome, enums clearly need it. Happy either way: use mine as the stopgap if the bigger one needs more time, otherwise close this out. If the larger rework lands, one thing worth carrying over: ParseInt was hardcoded to base 10, so 0x/0b/0o/_ literals were dropped and legacy 017 read as 17 instead of 15 — and an unparseable literal became a nil enum member rather than being skipped. |
Go's scanner never produces a negative numeric literal:
-1is a unary minus applied to the literal1, so a signed const reached the enum collector as *ast.UnaryExpr. findEnumValue type-asserted *ast.BasicLit and skipped anything else, silently dropping every signed member — the enum for a type with-1,0and1came out as[0, 1].Unwrap a sign (
-or+) around an INT or FLOAT literal and fold it into the text handed to strconv, so the whole int64 range round-trips:-9223372036854775808parses, whereas negating a parsed9223372036854775808would overflow.Integers are now parsed with base 0, reading the literal exactly as Go wrote it. Base 10 rejected the
0x,0band0oprefixes and_digit separators outright, and read the legacy017octal form as 17 where Go means 15.A literal whose text does not parse is now reported as unsupported and skipped. It previously became a nil enum member, which puts a null in the emitted spec and can panic go-openapi/spec, whose enum handling reflects on the first member.
Identifiers, including iota-derived constants, remain uncollected: they need go/types const evaluation, which is out of scope here.
contributes go-swagger/go-swagger#3412
Change type
Please select: 🆕 New feature or enhancement|🔧 Bug fix'|📃 Documentation update
Short description
Fixes
Full description
Checklist