mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-08-05 00:15:44 +00:00
Update module github.com/go-swagger/go-swagger to v0.36.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
parent
9b2de6085b
commit
ea1679488f
43 changed files with 1958 additions and 481 deletions
|
|
@ -8,7 +8,7 @@ go 1.25.0
|
|||
|
||||
require (
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7
|
||||
github.com/go-swagger/go-swagger v0.35.3
|
||||
github.com/go-swagger/go-swagger v0.36.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -21,26 +21,26 @@ require (
|
|||
github.com/felixge/httpsnoop v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.10.1 // indirect
|
||||
github.com/go-openapi/analysis v0.25.5 // indirect
|
||||
github.com/go-openapi/codescan v0.35.1 // indirect
|
||||
github.com/go-openapi/codescan v0.36.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.8 // indirect
|
||||
github.com/go-openapi/inflect v0.21.6 // indirect
|
||||
github.com/go-openapi/inflect v1.0.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v1.0.0 // indirect
|
||||
github.com/go-openapi/jsonreference v1.0.0 // indirect
|
||||
github.com/go-openapi/loads v0.25.0 // indirect
|
||||
github.com/go-openapi/runtime v0.32.6 // indirect
|
||||
github.com/go-openapi/runtime/server-middleware v0.32.6 // indirect
|
||||
github.com/go-openapi/runtime v0.33.0 // indirect
|
||||
github.com/go-openapi/runtime/server-middleware v0.33.0 // indirect
|
||||
github.com/go-openapi/spec v0.22.9 // indirect
|
||||
github.com/go-openapi/strfmt v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/conv v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/loading v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/netutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/pools v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/conv v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/loading v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/netutils v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/pools v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.28.0 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.28.0 // indirect
|
||||
github.com/go-openapi/validate v0.26.1 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
|
|
@ -50,10 +50,10 @@ require (
|
|||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||
github.com/mattn/go-isatty v0.0.23 // indirect
|
||||
github.com/mattn/go-isatty v0.0.24 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.1 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.4.3 // indirect
|
||||
github.com/rogpeppe/go-internal v1.15.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
|
|
@ -65,7 +65,7 @@ require (
|
|||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/toqueteos/webbrowser v1.2.1 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
golang.org/x/crypto v0.54.0 // indirect
|
||||
golang.org/x/mod v0.38.0 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
|
|
|
|||
|
|
@ -23,57 +23,57 @@ github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx5
|
|||
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
|
||||
github.com/go-openapi/analysis v0.25.5 h1:xPYEvTb90o1y0epuiOPAoG4QqahjP3cdp5xNlHeKJRI=
|
||||
github.com/go-openapi/analysis v0.25.5/go.mod h1:d3UGtQC5uq5Kqqqis2VH09Km/v3vwsWrYkbp4gdm+Rc=
|
||||
github.com/go-openapi/codescan v0.35.1 h1:ajmiS6ha1cA6S/V4uSF1KLEEi5/DqhM7Bef1polLl14=
|
||||
github.com/go-openapi/codescan v0.35.1/go.mod h1:2mzXphT7B2mM6IsMcP8pi01t2apd3LlIOuemfz4KLqI=
|
||||
github.com/go-openapi/codescan v0.36.0 h1:sp2RVgGp5IUlYRU3kwlQK6cUiQ9a1GNbgKbaAjdeSoI=
|
||||
github.com/go-openapi/codescan v0.36.0/go.mod h1:n0z3IJDm3ysnon+bLfBbHoy0WrRzlBE0LfeuAxGEnuM=
|
||||
github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I=
|
||||
github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w=
|
||||
github.com/go-openapi/inflect v0.21.6 h1:0Se5BlyDT4hnV9JQQKA63W9TIUU6SC4hPJiY3qJOEzQ=
|
||||
github.com/go-openapi/inflect v0.21.6/go.mod h1:ksYcnLD7j24H79hdqOMmWaLXjFXd0LTkRoBA0UazLW8=
|
||||
github.com/go-openapi/inflect v1.0.0 h1:IzG7K5YBu97odaCXhjODGGt25WaNtEYLJc9NfUcW4AI=
|
||||
github.com/go-openapi/inflect v1.0.0/go.mod h1:ksYcnLD7j24H79hdqOMmWaLXjFXd0LTkRoBA0UazLW8=
|
||||
github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s=
|
||||
github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y=
|
||||
github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY=
|
||||
github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0=
|
||||
github.com/go-openapi/loads v0.25.0 h1:74Bc2snfaVlsHzwdQj/3gsA9XJz3daXTJVs+4ZaK7jI=
|
||||
github.com/go-openapi/loads v0.25.0/go.mod h1:JFBw4SIB9+PTIFHDfcXuSSy5h6aWzjtUCrPYyx3qWU8=
|
||||
github.com/go-openapi/runtime v0.32.6 h1:hrcTTF8P7ZZr2Majzq11I65QtL/s85o7Q+zJf+AvFN4=
|
||||
github.com/go-openapi/runtime v0.32.6/go.mod h1:+rsupH3+TFKqmFysqkmgBOTxpVJV8eV+j9myvvea2Xw=
|
||||
github.com/go-openapi/runtime/server-middleware v0.32.6 h1:IGTYzybyFrUeSqQEwwO1y/9KnOk4QsabFNtAQtIHxDE=
|
||||
github.com/go-openapi/runtime/server-middleware v0.32.6/go.mod h1:OQHTBqMGquJShXhPYQ62yAqDMtC1rYpsEwldNWjYKhA=
|
||||
github.com/go-openapi/runtime v0.33.0 h1:Dd3Oj2ig+WH8ckK95l0Wn2V8a4bH/UqWPRZVT0vc8yU=
|
||||
github.com/go-openapi/runtime v0.33.0/go.mod h1:+rsupH3+TFKqmFysqkmgBOTxpVJV8eV+j9myvvea2Xw=
|
||||
github.com/go-openapi/runtime/server-middleware v0.33.0 h1:ZFUNyaa2eUs9DhLd6MTe/QRsuxeYn4Lq0C8iAoY13XE=
|
||||
github.com/go-openapi/runtime/server-middleware v0.33.0/go.mod h1:OQHTBqMGquJShXhPYQ62yAqDMtC1rYpsEwldNWjYKhA=
|
||||
github.com/go-openapi/spec v0.22.9 h1:/vKIFDcGKp0ktZWGbym/tJEWbk6/XOEmAVU0kqKMH+w=
|
||||
github.com/go-openapi/spec v0.22.9/go.mod h1:b/mNUYIOQOyIiUzUzXEE8xzyZqf93KvM9hQGP91yfl0=
|
||||
github.com/go-openapi/strfmt v0.27.0 h1:kbcTeaD9TXuXD0hhMXzuYa1sdTo6+dWGvwjW93E80IM=
|
||||
github.com/go-openapi/strfmt v0.27.0/go.mod h1:s/qhDqfY72irigXUGJmtgid2Rm+3tnz3k8hZaRmvWYc=
|
||||
github.com/go-openapi/swag v0.27.3 h1:i6oVKkGZeFgETHMiBHGtj9gIQ1aLtWDdJnT/SRZeets=
|
||||
github.com/go-openapi/swag/conv v0.27.3 h1:iqJFmGEjmX3AY0lSszABFqRVqOSt99XS0LzNIMJYuhU=
|
||||
github.com/go-openapi/swag/conv v0.27.3/go.mod h1:nPRmN6jgNme99hpf+nM0auDZGALWIqlwhisKPK/bQhQ=
|
||||
github.com/go-openapi/swag/fileutils v0.27.3 h1:3UVoZ2RLaIs1lt+2jcKzL8RM3Yk0rmsDE9FLA/HGxFE=
|
||||
github.com/go-openapi/swag/fileutils v0.27.3/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.3 h1:1DEz+O82frtSMBcos/7XIn1GnpNTbsD4Bru4Dc/uhRc=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.3/go.mod h1:qiDCoQvzkMxrV3G8FLEdIU5L+EFYc0zcDOHWT3Yofvo=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.3 h1:h/eT9kmGCDdFLJF29lOhzLtF0FmP1AX2MhLJWVebsb8=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.3/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
|
||||
github.com/go-openapi/swag/loading v0.27.3 h1:L9nQkEgzU7QgFQL+pLEMfGUKxeM4pWwGwbET9Z3weW0=
|
||||
github.com/go-openapi/swag/loading v0.27.3/go.mod h1:rJ0NeaKsF4CVPnMGjPQl7JlSHzvD0bc2DKXLss1hiuE=
|
||||
github.com/go-openapi/swag/mangling v0.27.3 h1:gRzzD1PAUoLTtGMgI3KpBmCSOlTuLTFWnviLxLcTnyg=
|
||||
github.com/go-openapi/swag/mangling v0.27.3/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w=
|
||||
github.com/go-openapi/swag/netutils v0.27.3 h1:IoBvfCoprsE6E87kAIm9basnISqDDqB79mJ8MN+f5PU=
|
||||
github.com/go-openapi/swag/netutils v0.27.3/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ=
|
||||
github.com/go-openapi/swag/pools v0.27.3 h1:gXjImP3F6/56wRRcFgEPld084Y6u2gs21ikPBt8NKBk=
|
||||
github.com/go-openapi/swag/pools v0.27.3/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE=
|
||||
github.com/go-openapi/swag/stringutils v0.27.3 h1:Ru28hnbAvN5wycALQYy8IobHvASq+FUFMlp1QzLM0JI=
|
||||
github.com/go-openapi/swag/stringutils v0.27.3/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
|
||||
github.com/go-openapi/swag/typeutils v0.27.3 h1:l6SSrx5eR5/WVwrGNzN6bQ9WqL04mrxNBl9YgQ3rcJ4=
|
||||
github.com/go-openapi/swag/typeutils v0.27.3/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.3 h1:cRFCAoYtslYn9L9T0xWryHy1t7c1MACC+DMj3CLvwvs=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.3/go.mod h1:6JYBGj8sw/NawMllyZY+cTA8Mzk2etS3ZBASdcyPsiU=
|
||||
github.com/go-openapi/swag v0.28.0 h1:xkgbOSKj6DZziNpyqRRAOt3GJGtgjgsd2RoyT30VWuw=
|
||||
github.com/go-openapi/swag/conv v0.28.0 h1:GtqqbyFe7vR5Y7ehxG9W6/OvrSFdf1OLeTGp40TqxH8=
|
||||
github.com/go-openapi/swag/conv v0.28.0/go.mod h1:mbUE+mzctnhxi864m0Q07SpN8OowD9JhxmxuYvZZD/k=
|
||||
github.com/go-openapi/swag/fileutils v0.28.0 h1:Z04XWQD7R8Eq+7GnOrjovBxPPmZzsS4gt2H2GPGIViU=
|
||||
github.com/go-openapi/swag/fileutils v0.28.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
|
||||
github.com/go-openapi/swag/jsonutils v0.28.0 h1:YIch6FwO7RXzeAnbO8Tu7dWBZeUEH+4nA0HXltVTnv4=
|
||||
github.com/go-openapi/swag/jsonutils v0.28.0/go.mod h1:CYM3WlTUcagR2ZoHdz54di/cbBqt82tuxuXgAjxw+mg=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0 h1:qV+VVUAx5Oro8WjVWpZeql7YReTKhT4smR4zhcOQZr0=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.28.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
|
||||
github.com/go-openapi/swag/loading v0.28.0 h1:td8QZdZC9MIYGGSnSPKShKiK22I2tU5UQvuUhIBPRLU=
|
||||
github.com/go-openapi/swag/loading v0.28.0/go.mod h1:rXB0QiQX5mMveXEA7ouM4KiiM9jVJe4K6BVbwhD1M4k=
|
||||
github.com/go-openapi/swag/mangling v0.28.0 h1:pH8eyeNO9SLYsTMWJrurnNfKmDa28XrlA+HePVD53VM=
|
||||
github.com/go-openapi/swag/mangling v0.28.0/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w=
|
||||
github.com/go-openapi/swag/netutils v0.28.0 h1:YXN6TALEi2pzts8/8GNm6T61HTAZsieukGZidap989k=
|
||||
github.com/go-openapi/swag/netutils v0.28.0/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ=
|
||||
github.com/go-openapi/swag/pools v0.28.0 h1:HPMZWSAfce3rdVTFcjFiCIBtDg9h4x2QlRrHipwhxeU=
|
||||
github.com/go-openapi/swag/pools v0.28.0/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE=
|
||||
github.com/go-openapi/swag/stringutils v0.28.0 h1:ixsc9iYgDPubHL/8nSkbnryEHpD2VRlBMLKpQyPXcDU=
|
||||
github.com/go-openapi/swag/stringutils v0.28.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
|
||||
github.com/go-openapi/swag/typeutils v0.28.0 h1:nRBKSBXjDgf01VDPB3fWeD9nQuhCOVeIYAkUx2tbkyY=
|
||||
github.com/go-openapi/swag/typeutils v0.28.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.28.0 h1:TV3JXH6DS46KUroDtMLAYHGkdWf5VDq3wVWFirmzROY=
|
||||
github.com/go-openapi/swag/yamlutils v0.28.0/go.mod h1:x0q/yndZHEgk9Rx3DyDqzFUmHy55KTvIZldvF2dTJXs=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo=
|
||||
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
|
||||
github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||
github.com/go-openapi/validate v0.26.1 h1:pZSbvtRO8G2R2FpWTYRn3w8LrsNwbtaVhP2dWiBa0Us=
|
||||
github.com/go-openapi/validate v0.26.1/go.mod h1:B8UMgXiQiwwQWIbmuROlwJZDPGlikPuh7iHV1vPX9Oo=
|
||||
github.com/go-swagger/go-swagger v0.35.3 h1:TjesBnknEKhd5y1KOngCAYuySA+SN42UmSy4kYtTLNU=
|
||||
github.com/go-swagger/go-swagger v0.35.3/go.mod h1:qvb30RtfTWVMAQKI0f4dNyHsulfVapjDfobkGP6ZbWc=
|
||||
github.com/go-swagger/go-swagger v0.36.0 h1:YDdoOZ6QNzRWZwoRNLT9hOKN8xdvlSzjXM9JMRE9Gvc=
|
||||
github.com/go-swagger/go-swagger v0.36.0/go.mod h1:zGi9Fhr7htWfJwNtjhEE93A1ITPDoeCulv4ASB46Gg8=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
|
|
@ -92,14 +92,14 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.23 h1:cYwCQTQf3HB6xUC+BtyCLZNr7IzbOmoZbmssVNzSyiQ=
|
||||
github.com/mattn/go-isatty v0.0.23/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
||||
github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
|
||||
github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
|
||||
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/oklog/ulid/v2 v2.1.2 h1:IEclFb9JNvzYA6MW2SCxbLzcHTVsfqm3PrqGQJH5zec=
|
||||
github.com/oklog/ulid/v2 v2.1.2/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY=
|
||||
github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
|
|
@ -129,8 +129,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
|
|||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/toqueteos/webbrowser v1.2.1 h1:O7IsnnU7XQyJ1nHMRfAktUUJOAZD3aQyUVnxzhWphCg=
|
||||
github.com/toqueteos/webbrowser v1.2.1/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
|
|
|
|||
7
test/tools/vendor/github.com/go-openapi/codescan/.codecov.yml
generated
vendored
7
test/tools/vendor/github.com/go-openapi/codescan/.codecov.yml
generated
vendored
|
|
@ -1,8 +1,9 @@
|
|||
codecov:
|
||||
notify:
|
||||
after_n_builds: 2
|
||||
|
||||
coverage:
|
||||
status:
|
||||
patch:
|
||||
default:
|
||||
target: 80%
|
||||
ignore:
|
||||
- internal/scantest
|
||||
- fixtures
|
||||
|
|
|
|||
1
test/tools/vendor/github.com/go-openapi/codescan/.gitattributes
generated
vendored
1
test/tools/vendor/github.com/go-openapi/codescan/.gitattributes
generated
vendored
|
|
@ -2,5 +2,6 @@
|
|||
# so byte-level comparison doesn't trip on Windows checkouts that
|
||||
# default to core.autocrlf=true.
|
||||
*.json text eol=lf
|
||||
*.txt text eol=lf
|
||||
internal/parsers/grammar/grammar_test/testdata/golden/* text eol=lf
|
||||
fixtures/integration/golden/* text eol=lf
|
||||
|
|
|
|||
3
test/tools/vendor/github.com/go-openapi/codescan/.gitignore
generated
vendored
3
test/tools/vendor/github.com/go-openapi/codescan/.gitignore
generated
vendored
|
|
@ -20,6 +20,9 @@ profile.cov
|
|||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace: commit go.work, ignore the generated checksum file
|
||||
go.work.sum
|
||||
|
||||
# env file
|
||||
.env
|
||||
|
||||
|
|
|
|||
20
test/tools/vendor/github.com/go-openapi/codescan/.golangci.yml
generated
vendored
20
test/tools/vendor/github.com/go-openapi/codescan/.golangci.yml
generated
vendored
|
|
@ -7,6 +7,7 @@ linters:
|
|||
- gomoddirectives # mono-repo, multi-modules (docs/examples): local replace directives are needed for proper releasing
|
||||
- goconst # disabled, perhaps temporarily as this linter has become way too pick and noisy
|
||||
- godox
|
||||
- gomoddirectives
|
||||
- gomodguard
|
||||
- gomodguard_v2
|
||||
- exhaustruct
|
||||
|
|
@ -54,6 +55,25 @@ linters:
|
|||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
rules:
|
||||
# cmd/genspec-tui is a bubbletea front-end. These four disagree with the
|
||||
# shape of TUI code rather than with the code itself, and each fires often
|
||||
# enough (102 between them) that //nolint would be the scattering this
|
||||
# repo's linting rule tells us to avoid. Scoped by path so the library
|
||||
# keeps all four.
|
||||
- path: cmd/genspec-tui/
|
||||
linters:
|
||||
# Layout arithmetic, where the number IS the explanation: w-2 is the
|
||||
# two border columns, h-3 is border plus title row.
|
||||
- mnd
|
||||
# Key, mouse and message switches read open-ended INPUT, not a closed
|
||||
# domain. Falling through to the code after the switch is the
|
||||
# behaviour, so a required `default:` would be an empty statement
|
||||
# asserting nothing. The scanner's go/types switches still get this.
|
||||
- exhaustive
|
||||
# clamp/clampInt keep a general (v, lo, hi) signature though every
|
||||
# call site happens to pass lo=0.
|
||||
- unparam
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
|
|
|
|||
22
test/tools/vendor/github.com/go-openapi/codescan/README.md
generated
vendored
22
test/tools/vendor/github.com/go-openapi/codescan/README.md
generated
vendored
|
|
@ -18,7 +18,9 @@ Supports Go modules (since go1.11).
|
|||
|
||||
## Announcements
|
||||
|
||||
* **2025-04-19** : large package layout reshuffle
|
||||
* **2026-07-31** : landed a new spec generation TUI tool
|
||||
|
||||
* **2026-04-19** : large package layout reshuffle
|
||||
* the entire project is being refactored to restore a reasonable level of maintenability
|
||||
* the only exposed API is Run() and Options.
|
||||
|
||||
|
|
@ -32,7 +34,7 @@ API is stable.
|
|||
go get github.com/go-openapi/codescan
|
||||
```
|
||||
|
||||
## Basic usage
|
||||
## Basic usage as a library
|
||||
|
||||
```go
|
||||
import (
|
||||
|
|
@ -44,6 +46,22 @@ swaggerSpec, err := codescan.Run(&codescan.Options{
|
|||
})
|
||||
```
|
||||
|
||||
## Work with the TUI
|
||||
|
||||
This project comes with a terminal UI to quickly render a Swagger spec from source
|
||||
and navigate your code annotations. It shows diagnostics and you may test the impact
|
||||
of the various available options.
|
||||
|
||||
```cmd
|
||||
go install github.com/go-openapi/codescan/cmd/genspec-tui@latest
|
||||
```
|
||||
|
||||
```cmd
|
||||
genspec-tui -workdir [my source location]
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Change log
|
||||
|
||||
See <https://github.com/go-openapi/codescan/releases>
|
||||
|
|
|
|||
20
test/tools/vendor/github.com/go-openapi/codescan/go.work
generated
vendored
Normal file
20
test/tools/vendor/github.com/go-openapi/codescan/go.work
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
go 1.25.0
|
||||
|
||||
// Workspace for the codescan monorepo: the main library module (.) and the
|
||||
// genspec-tui front-end module (./cmd/genspec-tui), kept in separate go.mod
|
||||
// files so the TUI's bubbletea dependency tree never pollutes the lean library.
|
||||
//
|
||||
// The workspace is what lets CI test every module in one pass (`go test work
|
||||
// ./...`, via the shared go-test-monorepo workflow) — the TUI has no CI of its
|
||||
// own. `go install .../cmd/genspec-tui@latest` ignores this file, so the TUI
|
||||
// module's own go.mod carries the real `require` on the library.
|
||||
//
|
||||
// Keep the `go` directive above in step with the modules (all 1.25.0): raising
|
||||
// it past them imposes a toolchain floor the code does not need, and would take
|
||||
// the oldstable CI job out.
|
||||
use (
|
||||
.
|
||||
./cmd/genspec-tui
|
||||
./docs/examples
|
||||
./fixtures
|
||||
)
|
||||
336
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/README.md
generated
vendored
336
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/README.md
generated
vendored
|
|
@ -20,6 +20,7 @@ trade-offs, and known quirks live here.
|
|||
- [§allof](#allof) — `buildAllOf`, `buildNamedAllOf`, `scanEmbeddedFields`
|
||||
- [§embedded](#embedded) — embed routing, struct/interface specials asymmetry
|
||||
- [§embed-depth](#embed-depth) — ambiguous-embed diagnostic mechanism
|
||||
- [§omit](#omit) — `swagger:omit` — the author's pre-filter on promoted fields
|
||||
- [§method-mangler](#method-mangler) — interface-method JSON-name derivation
|
||||
- [§user-overrides](#user-overrides) — explicit user-driven type/format overrides at decl-site and field-site
|
||||
- [§traceability](#traceability) — `x-go-name` / `x-go-package` / `x-go-type` origin extensions and `EmitXGoType`
|
||||
|
|
@ -587,6 +588,90 @@ contribute an `{}` entry to the outer schema.
|
|||
|
||||
---
|
||||
|
||||
## <a id="omit"></a>§omit — `swagger:omit`, the author's pre-filter on promoted fields
|
||||
|
||||
Promoting an embed can produce a schema the author never meant, and codescan must not guess which
|
||||
one they meant. The two cases that motivated the annotation (go-swagger#1992 plus the override
|
||||
defects found while auditing `DefaultAllOfForEmbeds`):
|
||||
|
||||
| shape | Go marshals | inlined | composed (`allOf`) |
|
||||
|---|---|---|---|
|
||||
| outer `ID` re-declared to add `readOnly` | one `ID` | one, decorated | `ID` in BOTH members |
|
||||
| outer `ID string` over `ID int64` | one, string | string | integer AND string — unsatisfiable |
|
||||
| a shared type embedded in a request body | every field | every field | every field |
|
||||
|
||||
Inlining **resolves** an override (it applies Go's depth rule and emits the winner); `allOf`
|
||||
**accumulates** — members conjoin, and conjunction can only narrow, never replace. So an override
|
||||
that replaces is not expressible as composition, and no amount of tidying the members fixes it.
|
||||
`swagger:omit` is the escape hatch: the author states which promoted fields do not belong, and the
|
||||
scanner keeps mirroring the code otherwise.
|
||||
|
||||
### It is a pre-filter, not a post-hoc delete
|
||||
|
||||
`swagger:omit` means *"do not promote this field when walking the embed"*. One rule then covers both
|
||||
renderings — the field is simply never written:
|
||||
|
||||
- inlined: an outer re-declaration wins as it already did (so omitting
|
||||
its promoted twin is correctly a no-op there);
|
||||
- composed: the base member is built without the field, which removes
|
||||
the duplicate and the unsatisfiable pair above.
|
||||
|
||||
No mode-awareness, and no Go-name↔JSON-name reconciliation, because filtering happens *before* names
|
||||
are computed — which is why targets are Go field names and why the annotation is indifferent to json
|
||||
tags and to `NameFromTags`.
|
||||
|
||||
The filter itself is one condition in `processStructField` (`struct.go`); everything else lives in
|
||||
`omit.go`.
|
||||
|
||||
### Resolution runs against the type, not the walk
|
||||
|
||||
Each target is resolved once, at the annotation site, with `types.LookupFieldOrMethod` — Go's own
|
||||
promoted-field lookup, so depth and ambiguity rules come for free. The scope then carries the
|
||||
resulting `*types.Var` objects and the filter is pointer identity.
|
||||
|
||||
Consequences worth keeping: there is no "what was actually omitted" bookkeeping (a target either
|
||||
names a field of the type or it does not, known before the walk starts); a target already excluded
|
||||
for another reason resolves fine and is silently redundant; and two same-named fields at different
|
||||
depths can never be confused, because distinct fields are distinct objects.
|
||||
|
||||
### Placement
|
||||
|
||||
- **on the embed** (ergonomic): targets are plain field names of that
|
||||
embedded type;
|
||||
- **on the declaration** (power form): a dotted path names the embed
|
||||
chain (`Base.ID`, head consumed per level), a bare name is offered to
|
||||
each embed and resolved against its promoted set.
|
||||
|
||||
Every path segment but the last must name an **embedded** field: `omit` removes promoted content,
|
||||
the only thing the enclosing schema owns. A segment naming a regular field stops the walk and is
|
||||
reported as unresolved — reaching through one would edit either another type's inlined copy or a
|
||||
`$ref`'d definition.
|
||||
|
||||
### Diagnostics (all Hints)
|
||||
|
||||
| code | fires when |
|
||||
|---|---|
|
||||
| `scan.omit-unresolved` | the target names no field of the embedded type — a typo, or a rename upstream |
|
||||
| `scan.omit-behind-ref` | the embed is composed as a `$ref` (an annotated model), where OAS2 cannot subtract a property; the omission is dropped rather than silently forking the definition |
|
||||
| `scan.shadowed-embed-field` | a field re-declared with `json:"-"` carries the Go name of a promoted field (see below) |
|
||||
|
||||
`swagger:omit` is the only construct whose output depends on a hand-written name the compiler never
|
||||
checks — everything else is derived from types. `scan.omit-unresolved` is what stops it rotting
|
||||
silently when a field is renamed upstream.
|
||||
|
||||
### The `json:"-"` shadow is not what authors think
|
||||
|
||||
`fields.go` deletes a promoted property when an outer field re-declares it with `json:"-"`. That is
|
||||
**unfaithful to `encoding/json`**, which ignores a `-` field entirely: it never enters the name set,
|
||||
so it cannot shadow the promoted one and Go keeps marshalling the embedded field. The behaviour is
|
||||
locked by `TestOverridingOneIgnore` and left in place for now; the Hint points at `swagger:omit`,
|
||||
which removes the field for real. Removing the eviction is a separate decision — see
|
||||
`.claude/plans/swagger-omit.md` §7.
|
||||
|
||||
Fixtures: `fixtures/enhancements/swagger-omit` (the annotation, both renderings, all three Hints,
|
||||
plus the go-swagger#1992 shape verbatim) and `fixtures/enhancements/default-allof-embeds-override`
|
||||
(the same overrides *without* the annotation — the documented limit).
|
||||
|
||||
## <a id="embed-depth"></a>§embed-depth — ambiguous-embed diagnostic mechanism
|
||||
|
||||
`Builder.embedDepth` (incremented around `buildNamedEmbedded`'s
|
||||
|
|
@ -1456,70 +1541,36 @@ edges fixture covers a different (strfmt-tagged) shape already.
|
|||
|
||||
---
|
||||
|
||||
### ✅ Named-strfmt + `swagger:model` combo (was 🟡 deferred)
|
||||
|
||||
A type carrying both `swagger:strfmt phone` and `swagger:model` used to emit an
|
||||
inconsistent pair: `{type: string, format: phone}` at the field site, but a
|
||||
struct walk (`{type: object, properties: …}`) for the top-level definition. The
|
||||
decl-level strfmt now wins and the field `$ref`s it — verified in
|
||||
`enhancements_named_struct_tags-ref.json`: `PhoneNumber` is
|
||||
`{type: string, format: phone}` and `Contact.phone` is a `$ref` to it.
|
||||
|
||||
Fixed by the F-series pass (`8e20d2f`, quirk F1), not by the attempt described
|
||||
in the original entry — which was reverted. History:
|
||||
`.claude/plans/archive/deferred-quirks.md` D3.
|
||||
|
||||
### ✅ Cross-package definition-name collisions (was 🟡 silently overwrite)
|
||||
|
||||
Two packages declaring the same identifier (`pkg/a.User`, `pkg/b.User`) both
|
||||
mapped to `definitions["User"]`, and the second build silently overwrote the
|
||||
first — one `User` in the output, no record of the collision.
|
||||
|
||||
Fixed by the name-identity / cyclic-`$ref` work: every definition is keyed by a
|
||||
compiler-unique `DefKey` (`<pkgpath>/<name>`) while building, and a final reduce
|
||||
stage projects each back to the shortest unique name, deconflicting collisions
|
||||
(`AWidget` / `BWidget`) and raising a `scan.renamed-definition` Hint. See
|
||||
[§discovery](#discovery) and `.claude/plans/name-identity-cyclic-ref.md`.
|
||||
|
||||
## <a id="quirks-open"></a>§quirks-open — still open
|
||||
|
||||
### 🟡 Named-strfmt + `swagger:model` combo (deferred)
|
||||
|
||||
When the author combines `swagger:strfmt` with `swagger:model`
|
||||
on the same type, the FIELD reference inlines as `{string, format}`
|
||||
(via the strfmt classifier) but the TOP-LEVEL definition body is
|
||||
still emitted from walking the underlying struct.
|
||||
|
||||
**Reproduction.** Fixture `fixtures/enhancements/named-struct-tags-ref/types.go`
|
||||
declares `PhoneNumber` with both `swagger:strfmt phone` and
|
||||
`swagger:model`, used by `Contact.Phone`. The golden
|
||||
`enhancements_named_struct_tags-ref.json` captures the observable
|
||||
inconsistency:
|
||||
|
||||
- Field site: `{type: "string", format: "phone"}` — strfmt wins.
|
||||
- Top-level definition: `{type: "object", properties: {CountryCode, Number}}` —
|
||||
the struct walk wins; the strfmt annotation is ignored at decl time.
|
||||
|
||||
The author asked for "named strfmt" (a reusable `PhoneNumber`
|
||||
definition rendered as a formatted string) but gets an inconsistent
|
||||
pair: the field says string, the definition says object.
|
||||
|
||||
**Attempted fix and reasons it reverted.** The first attempt
|
||||
(referred to as "Option 1") would have:
|
||||
|
||||
1. Detected `swagger:strfmt` on the decl in `buildDeclNamed` and
|
||||
emitted `{string, fmt}` instead of walking the struct body.
|
||||
2. In `buildNamedStruct`, when the target also has `swagger:model`,
|
||||
emitted `$ref` instead of inlining the strfmt.
|
||||
|
||||
This was reverted before merge because:
|
||||
|
||||
- Pre-existing fixtures in
|
||||
`fixtures/goparsing/classification/transitive/mods/aliases.go` use
|
||||
the same `swagger:strfmt + swagger:model` combination on
|
||||
defined-from-`time.Time` types (e.g. `SomeTimeType time.Time`).
|
||||
The existing tests (`TestAliasedTypes`, `TestAliasedModels`)
|
||||
assert the *inline* baseline (`scantest.AssertProperty(..., "string", ...)`)
|
||||
rather than a `$ref`. Option 1 flips these to `$ref`, requiring
|
||||
coordinated test updates.
|
||||
- The decl-level `StrfmtName` check also over-fires on slice / array /
|
||||
map underlyings: `type SomeTimesType []time.Time` with
|
||||
`swagger:strfmt date-time` should emit
|
||||
`{array, items: {string, date-time}}`, not flatten to `{string}`.
|
||||
A correct fix would gate the check on struct-underlying first,
|
||||
then symmetrically consider whether `buildNamedSlice` /
|
||||
`buildNamedArray` / `buildNamedMap` should also route through
|
||||
`$ref` under the `swagger:model` combination.
|
||||
|
||||
The surface area is wider than the Option 1 code change suggested,
|
||||
and the existing test coverage of the combination is entangled with
|
||||
the inconsistency itself.
|
||||
|
||||
**Why deferred.** The combination is niche, the footgun is narrow
|
||||
(you get what you asked for on one side of the indirection, not
|
||||
both), and v2's annotation redesign can reshape the contract without
|
||||
carrying this legacy. A focused decision on "named strfmt" semantics
|
||||
belongs in the v2 design, not a bug-fix pass.
|
||||
|
||||
The `named-struct-tags-ref` fixture and its golden are checked in as
|
||||
a deliberate marker — the golden captures the observable
|
||||
inconsistency (inline field + struct-body definition) so future work
|
||||
on this decision has a failing test to anchor against.
|
||||
> **Where open quirks live.** This section documents caveats *of this package*.
|
||||
> The project-wide register of what is actually open — verified, with the stale
|
||||
> historical registers called out — is `.claude/plans/quirks-open.md`.
|
||||
|
||||
### 🟦 `interface{}` literals (documented behaviour)
|
||||
|
||||
|
|
@ -1542,155 +1593,18 @@ the substituted underlying via the `TypeArgs` short-circuit
|
|||
without a concrete instantiation simply have no representable
|
||||
schema.
|
||||
|
||||
### 🟡 Cross-package definition-name collisions silently overwrite
|
||||
### 🟡 A field-level enum override discards the type's per-value docs, silently
|
||||
|
||||
`buildFromDecl` writes the top-level schema as
|
||||
`s.definitions[s.Name] = schema`, keyed only by the Go identifier
|
||||
(`decl.Names()[0]`). When two packages in a single scan declare a type
|
||||
with the same identifier — `pkg/a.User` and `pkg/b.User` — both map
|
||||
to `definitions["User"]` and the second build silently overwrites the
|
||||
first. The output spec carries only one `User`, with no record of the
|
||||
collision and no signal of which package won.
|
||||
When a field whose type is marked `swagger:enum TypeName` carries its own
|
||||
`enum:` override, the inherited `x-go-enum-desc` is stripped along with the
|
||||
replaced values — and **no diagnostic is raised**, so the per-value docs
|
||||
`TypeName` contributed vanish without a trace. Reproduced by
|
||||
`fixtures/enhancements/enum-overrides` case E (`NotificationE`).
|
||||
|
||||
The existing `nameByJSON` (`propOwner`) map in field emission is **not**
|
||||
a defense against this case: it tracks JSON property names within a
|
||||
single struct's field set plus its embeds (for the ambiguous-embed
|
||||
diagnostic), not type-level identifier conflicts across packages.
|
||||
Whether the docs should be filtered through (when the override *subsets* the
|
||||
type's values) or dropped with a Hint (when it narrows to *different* ones) is a
|
||||
design call that belongs with the enum feature, not with this package: see
|
||||
`.claude/plans/features/enum-richer-values.md` §1.2b.
|
||||
|
||||
#### Target shape
|
||||
|
||||
A proper fix needs three pieces:
|
||||
|
||||
1. **Detection** — at write time, recognise the case "definition key
|
||||
already exists with non-empty schema and originates from a different
|
||||
package" (use `x-go-package`, or stash origin in the `Builder`).
|
||||
2. **Diagnostic** — emit `CodeNameConflict` (severity
|
||||
`SeverityWarning` minimum, possibly `SeverityError` under strict
|
||||
mode) carrying both `(pkg, name)` pairs.
|
||||
3. **Policy** — open design call:
|
||||
- **a. Rename** — prefix loser(s) with a stable short-package
|
||||
(e.g. `a_User`, `b_User`). Stable but ugly; needs all `$ref`s
|
||||
to follow the rename — cross-cutting.
|
||||
- **b. Skip + warn** — keep the first writer, drop subsequent
|
||||
ones, emit a warning. Predictable but lossy.
|
||||
- **c. Fail the build** — under strict mode, treat as an error.
|
||||
Forces the author to rename in source. Cleanest semantics,
|
||||
most disruptive.
|
||||
|
||||
#### Why deferred
|
||||
|
||||
Each policy choice changes the contract for downstream code generators
|
||||
(go-swagger, oapi-codegen, …) — they have assumptions about
|
||||
`definitions` keys matching exported Go names. The "rename" path
|
||||
additionally requires every `$ref` writer in the builders to consult a
|
||||
rename map; the surface is wide.
|
||||
|
||||
For multi-package scans where the author controls both packages, the
|
||||
workaround today is to scope scans to one package per spec, or to
|
||||
rename one of the colliding types at the source. A future strict-mode
|
||||
flag (e.g. `Options.StrictNameConflicts`) could enable option (c)
|
||||
without breaking existing scans.
|
||||
|
||||
### 🟡 Stale `x-go-enum-desc` after a field-level enum override
|
||||
|
||||
When a field uses a type marked `swagger:enum TypeName` **and** carries
|
||||
its own `enum: …` override, v1 mutates the schema in place: it replaces
|
||||
`Enum`, strips the inherited `x-go-enum-desc`, and trims the matching
|
||||
description suffix. This is **lossy** — the per-value docs contributed
|
||||
by `TypeName` are silently discarded.
|
||||
|
||||
Concretely, given (fixture `fixtures/enhancements/enum-overrides/`,
|
||||
case E):
|
||||
|
||||
```go
|
||||
// swagger:enum PriorityE
|
||||
type PriorityE string
|
||||
|
||||
const (
|
||||
PriorityELow PriorityE = "low" // low-priority requests
|
||||
PriorityEMed PriorityE = "medium" // medium-priority requests
|
||||
PriorityEHigh PriorityE = "high" // high-priority requests
|
||||
)
|
||||
|
||||
type NotificationE struct {
|
||||
// Inline enum provides a narrower set than the const block.
|
||||
//
|
||||
// enum: urgent, normal
|
||||
Priority PriorityE `json:"priority"`
|
||||
}
|
||||
```
|
||||
|
||||
v1 emits:
|
||||
|
||||
```yaml
|
||||
priority:
|
||||
type: string
|
||||
enum: [urgent, normal] # the override wins
|
||||
description: "Inline enum provides a narrower set than the const block."
|
||||
# x-go-enum-desc removed by clearStaleEnumDesc
|
||||
# PriorityE's per-value doc lines silently dropped from description
|
||||
```
|
||||
|
||||
The cleanup runs reactively from `schemaValidations.SetEnum`
|
||||
([typable.go](typable.go#L128)) via `clearStaleEnumDesc`
|
||||
([extensions.go](extensions.go#L42)). It treats any
|
||||
`x-go-enum-desc` present at `SetEnum` time as inherited (and therefore
|
||||
stale once `Enum` is replaced), deletes it, and trims the matching
|
||||
suffix off `Description`. The `TrimSuffix` dance is fragile — it
|
||||
relies on the enum-desc pipeline having appended the doc lines as a
|
||||
literal suffix — but it works under v1's emission discipline.
|
||||
|
||||
#### Target shape (allOf composition)
|
||||
|
||||
OpenAPI 2.0 supports `allOf` for schema composition, so the cleaner
|
||||
model does not have to wait for OAS 3. The replacement shape is:
|
||||
|
||||
```yaml
|
||||
# PriorityE promoted to a top-level definition:
|
||||
definitions:
|
||||
PriorityE:
|
||||
type: string
|
||||
enum: [low, medium, high]
|
||||
description: |
|
||||
low: low-priority requests
|
||||
medium: medium-priority requests
|
||||
high: high-priority requests
|
||||
x-go-enum-desc: |
|
||||
low: low-priority requests
|
||||
medium: medium-priority requests
|
||||
high: high-priority requests
|
||||
|
||||
NotificationE:
|
||||
type: object
|
||||
properties:
|
||||
priority:
|
||||
description: "Inline enum provides a narrower set than the const block."
|
||||
allOf:
|
||||
- $ref: '#/definitions/PriorityE' # inherited enum + per-value docs
|
||||
- enum: [urgent, normal] # the override
|
||||
```
|
||||
|
||||
Each branch keeps its own concern:
|
||||
|
||||
- the `$ref` branch carries `PriorityE`'s full schema (values + docs +
|
||||
`x-go-enum-desc`), untouched and reusable by every field that
|
||||
references `PriorityE`;
|
||||
- the inline branch carries the narrowing override only.
|
||||
|
||||
No mutation of the inherited schema, no `TrimSuffix` dance. Validator
|
||||
semantics for enum-narrowing `allOf` aren't perfectly uniform across
|
||||
tools, but for the documentation / code-gen use cases codescan feeds
|
||||
(go-swagger, oapi-codegen, redoc, …) this composition preserves both
|
||||
layers cleanly.
|
||||
|
||||
#### Prerequisites for the migration (both currently missing)
|
||||
|
||||
1. **Promote unannotated `swagger:enum` types to top-level definitions**
|
||||
so the `$ref` branch has a target. Today they exist only as inlined
|
||||
fragments on each referring field.
|
||||
2. **Move override detection from `SetEnum` (validation hook) to the
|
||||
field-emission path**, so the override is composed alongside the
|
||||
inherited schema instead of mutating it after the fact.
|
||||
|
||||
Until both land, `clearStaleEnumDesc` stays in place. The TODO in
|
||||
`extensions.go` flags it as the replacement target.
|
||||
The stripping itself lives in `handlers/dispatch_schema.go:clearStaleEnumDesc`,
|
||||
which is where either resolution would land.
|
||||
|
|
|
|||
20
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/allof.go
generated
vendored
20
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/allof.go
generated
vendored
|
|
@ -28,6 +28,10 @@ import (
|
|||
func (s *Builder) scanEmbeddedFields(
|
||||
decl *scanner.EntityDecl, st *types.Struct, schema *oaispec.Schema, nameByJSON map[string]propOwner,
|
||||
) (target *oaispec.Schema, hasAllOf bool, err error) {
|
||||
// `swagger:omit` written on the DECLARATION (the power form) applies to the embeds walked below;
|
||||
// the ergonomic form lives on each embed and is read from its fieldDoc.
|
||||
declOmits := s.declOmitTargets(decl.Comments)
|
||||
|
||||
for fld := range st.Fields() {
|
||||
if !fld.Anonymous() {
|
||||
continue
|
||||
|
|
@ -60,8 +64,18 @@ func (s *Builder) scanEmbeddedFields(
|
|||
isAllOf = true
|
||||
}
|
||||
|
||||
// `swagger:omit` is a PRE-filter: the listed fields are dropped before the embed is walked, so
|
||||
// nothing is ever written for them. That makes the annotation mean the same thing whether the
|
||||
// embed is inlined or composed into an allOf member — see omit.go.
|
||||
// An embed emitted as a $ref cannot have a property subtracted; embedOmitTargets reports that
|
||||
// and filters nothing.
|
||||
restoreOmits := s.pushOmitted(
|
||||
s.embedOmitTargets(fld, afld, fd, declOmits, isAllOf && s.isModelEmbed(fld.Type())),
|
||||
)
|
||||
|
||||
if !isAllOf {
|
||||
target, err = s.buildPlainEmbed(fld, afld, fd, isString, omitEmpty, schema, target, nameByJSON)
|
||||
restoreOmits()
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
|
@ -73,8 +87,10 @@ func (s *Builder) scanEmbeddedFields(
|
|||
target = &oaispec.Schema{}
|
||||
}
|
||||
var newSch oaispec.Schema
|
||||
if err := s.buildAllOf(fld.Type(), &newSch); err != nil {
|
||||
return nil, false, err
|
||||
buildErr := s.buildAllOf(fld.Type(), &newSch)
|
||||
restoreOmits()
|
||||
if buildErr != nil {
|
||||
return nil, false, buildErr
|
||||
}
|
||||
|
||||
if fd.AllOfClass != "" {
|
||||
|
|
|
|||
5
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/fields.go
generated
vendored
5
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/fields.go
generated
vendored
|
|
@ -270,6 +270,11 @@ func (s *Builder) structFieldCarrier(fld *types.Var, decl *scanner.EntityDecl, t
|
|||
return fieldCarrier{}, false, err
|
||||
}
|
||||
if ignore {
|
||||
// A `json:"-"` re-declaration does NOT shadow a promoted field in Go — encoding/json ignores the
|
||||
// field entirely, so the embedded one keeps marshalling. Report it and point at swagger:omit,
|
||||
// which drops it for real.
|
||||
s.warnShadowedByJSONDash(fld, afld, target, nameByJSON)
|
||||
|
||||
for jsonName, prior := range nameByJSON {
|
||||
if prior.goName == fld.Name() {
|
||||
delete(target.Properties, jsonName)
|
||||
|
|
|
|||
307
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/omit.go
generated
vendored
Normal file
307
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/omit.go
generated
vendored
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package schema
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/codescan/internal/parsers/grammar"
|
||||
oaispec "github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// omitPathSep separates the segments of a qualified `swagger:omit` target (`Base.ID`).
|
||||
const omitPathSep = "."
|
||||
|
||||
// parseOmitTargets splits a `swagger:omit` argument into its targets.
|
||||
//
|
||||
// The lexer captures the whole remainder verbatim (the list may carry spaces after commas), so the
|
||||
// split happens here: comma-separated, each target trimmed, empties dropped.
|
||||
func parseOmitTargets(arg string) []string {
|
||||
var out []string
|
||||
for raw := range strings.SplitSeq(arg, ",") {
|
||||
if t := strings.TrimSpace(raw); t != "" {
|
||||
out = append(out, t)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// resolveOmitTargets resolves each target against the embedded type, returning the field objects to
|
||||
// filter out of the promotion walk.
|
||||
//
|
||||
// Resolution runs against the TYPE, not the walk: a target either names a (promoted) field of the
|
||||
// embedded type or it does not, and that is known before a single property is written. The scope
|
||||
// then carries field OBJECTS, so the pre-filter is pointer identity — no name matching, no
|
||||
// bookkeeping of what was "actually omitted", and no collision between same-named fields at
|
||||
// different depths.
|
||||
//
|
||||
// [types.LookupFieldOrMethod] is Go's own promoted-field lookup, so depth and ambiguity rules come
|
||||
// for free: a target that Go itself could not resolve unambiguously resolves to nothing here and is
|
||||
// reported.
|
||||
//
|
||||
// Unresolved targets raise a scan.omit-unresolved Hint (see [grammar.CodeOmitUnresolved]) — this is
|
||||
// what stops the annotation rotting silently when a field is renamed upstream.
|
||||
func (s *Builder) resolveOmitTargets(embedded types.Type, targets []string, pos token.Position) []*types.Var {
|
||||
if len(targets) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make([]*types.Var, 0, len(targets))
|
||||
for _, target := range targets {
|
||||
fld, ok := lookupOmitPath(embedded, strings.Split(target, omitPathSep))
|
||||
if !ok {
|
||||
s.hintf(pos, grammar.CodeOmitUnresolved,
|
||||
"swagger:omit: %s has no field %q; the target is ignored", typeLabel(embedded), target)
|
||||
|
||||
continue
|
||||
}
|
||||
out = append(out, fld)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// lookupOmitPath walks a dotted target (`Inner.Deep`) through the embed chain of tpe and returns the
|
||||
// field the last segment names.
|
||||
//
|
||||
// Every segment but the last must name an EMBEDDED field: `swagger:omit` removes promoted content,
|
||||
// which is the only thing the enclosing schema owns. A segment naming a regular field stops the walk
|
||||
// (reported as unresolved by the caller) — reaching through a regular field would either edit
|
||||
// another type's inlined copy or, worse, a `$ref`'d definition.
|
||||
func lookupOmitPath(tpe types.Type, path []string) (*types.Var, bool) {
|
||||
cur := tpe
|
||||
for i, seg := range path {
|
||||
obj, _, _ := types.LookupFieldOrMethod(cur, true, pkgOf(cur), seg)
|
||||
fld, isField := obj.(*types.Var)
|
||||
if !isField {
|
||||
return nil, false
|
||||
}
|
||||
if i == len(path)-1 {
|
||||
return fld, true
|
||||
}
|
||||
if !fld.Embedded() {
|
||||
return nil, false
|
||||
}
|
||||
cur = fld.Type()
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// pkgOf returns the package a named type belongs to, or nil for an unnamed one.
|
||||
//
|
||||
// [types.LookupFieldOrMethod] needs it only to decide whether unexported names are visible; a nil
|
||||
// package restricts the lookup to exported fields, which is the right default for an unnamed type.
|
||||
func pkgOf(tpe types.Type) *types.Package {
|
||||
switch t := types.Unalias(tpe).(type) {
|
||||
case *types.Pointer:
|
||||
return pkgOf(t.Elem())
|
||||
case *types.Named:
|
||||
if obj := t.Obj(); obj != nil {
|
||||
return obj.Pkg()
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// typeLabel names a type for a diagnostic — the declared name when there is one, else the type
|
||||
// string.
|
||||
func typeLabel(tpe types.Type) string {
|
||||
if named, ok := types.Unalias(tpe).(*types.Named); ok {
|
||||
return named.Obj().Name()
|
||||
}
|
||||
|
||||
return tpe.String()
|
||||
}
|
||||
|
||||
// pushOmitted adds fields to the active omit scope and returns the function restoring it.
|
||||
//
|
||||
// The scope is a set of field objects in force for the subtree currently being walked; nesting
|
||||
// accumulates, and each level removes only what it added, so sibling embeds never leak into one
|
||||
// another.
|
||||
func (s *Builder) pushOmitted(fields []*types.Var) func() {
|
||||
if len(fields) == 0 {
|
||||
return func() {}
|
||||
}
|
||||
if s.omitted == nil {
|
||||
s.omitted = make(map[*types.Var]struct{}, len(fields))
|
||||
}
|
||||
|
||||
added := make([]*types.Var, 0, len(fields))
|
||||
for _, fld := range fields {
|
||||
if _, dup := s.omitted[fld]; dup {
|
||||
continue
|
||||
}
|
||||
s.omitted[fld] = struct{}{}
|
||||
added = append(added, fld)
|
||||
}
|
||||
|
||||
return func() {
|
||||
for _, fld := range added {
|
||||
delete(s.omitted, fld)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isOmitted reports whether fld is filtered out by the active `swagger:omit` scope.
|
||||
//
|
||||
// This is the whole enforcement: a pre-filter on the promotion walk, so the property is never
|
||||
// written. Because it runs before any name is computed, it is indifferent to json tags, to
|
||||
// `NameFromTags`, and to whether the enclosing schema is inlined or composed with allOf.
|
||||
func (s *Builder) isOmitted(fld *types.Var) bool {
|
||||
if len(s.omitted) == 0 {
|
||||
return false
|
||||
}
|
||||
_, omitted := s.omitted[fld]
|
||||
|
||||
return omitted
|
||||
}
|
||||
|
||||
// embedOmitTargets collects the `swagger:omit` targets that apply to one embed and resolves them
|
||||
// against the embedded type.
|
||||
//
|
||||
// Sources: the embed's own annotation (the ergonomic form — targets are plain field names of that
|
||||
// type) and the enclosing declaration's annotation (the power form — a bare name resolved against
|
||||
// the promoted set, or a dotted path whose head names this embed).
|
||||
//
|
||||
// isAllOfRef marks an embed that will be emitted as a `$ref` rather than inlined; the omission
|
||||
// cannot be expressed there, so it is dropped with a scan.omit-behind-ref Hint instead of silently
|
||||
// forking the referenced definition.
|
||||
func (s *Builder) embedOmitTargets(
|
||||
fld *types.Var, afld *ast.Field, fd fieldDoc, declOmits []string, isAllOfRef bool,
|
||||
) []*types.Var {
|
||||
targets := append([]string(nil), fd.OmitTargets...)
|
||||
targets = append(targets, declOmitsFor(fld, declOmits)...)
|
||||
if len(targets) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pos := s.Ctx.PosOf(afld.Pos())
|
||||
if isAllOfRef {
|
||||
s.hintf(pos, grammar.CodeOmitBehindRef,
|
||||
"swagger:omit: %s is composed as a $ref; a referenced definition cannot have a property "+
|
||||
"subtracted, so the omission is dropped", typeLabel(fld.Type()))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return s.resolveOmitTargets(fld.Type(), targets, pos)
|
||||
}
|
||||
|
||||
// declOmitsFor selects the declaration-level targets that apply to one embed: a dotted path whose
|
||||
// head names this embed (with the head consumed), and every bare name — a bare name is resolved
|
||||
// against the promoted set of each embed in turn, exactly as Go resolves a promoted field.
|
||||
//
|
||||
// A bare name that matches no embed is reported once per embed it was tried against; that is the
|
||||
// intended behaviour for a typo and is silent for the (redundant, harmless) case where the field was
|
||||
// already excluded for another reason.
|
||||
func declOmitsFor(fld *types.Var, declOmits []string) []string {
|
||||
if len(declOmits) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var out []string
|
||||
for _, target := range declOmits {
|
||||
head, tail, qualified := strings.Cut(target, omitPathSep)
|
||||
if !qualified {
|
||||
out = append(out, target)
|
||||
|
||||
continue
|
||||
}
|
||||
if head == fld.Name() {
|
||||
out = append(out, tail)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// hintf emits an informational diagnostic through the builder's sink.
|
||||
func (s *Builder) hintf(pos token.Position, code grammar.Code, format string, args ...any) {
|
||||
if onDiag := s.Ctx.OnDiagnostic(); onDiag != nil {
|
||||
onDiag(grammar.Hintf(pos, code, format, args...))
|
||||
}
|
||||
}
|
||||
|
||||
// declOmitTargets reads the declaration-level `swagger:omit` targets off a type's doc comment.
|
||||
//
|
||||
// These are the power form, for embeds the author cannot annotate directly (a type they do not own,
|
||||
// or one nested deeper than their own source).
|
||||
func (s *Builder) declOmitTargets(cg *ast.CommentGroup) []string {
|
||||
if cg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var out []string
|
||||
for _, b := range s.ParseBlocks(cg) {
|
||||
if b.AnnotationKind() != grammar.AnnOmit {
|
||||
continue
|
||||
}
|
||||
if arg, ok := b.AnnotationArg(); ok {
|
||||
out = append(out, parseOmitTargets(arg)...)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// isModelEmbed reports whether an embedded type is a `swagger:model`, i.e. whether composing it into
|
||||
// an allOf member emits a `$ref` rather than an inline copy (see buildNamedAllOf).
|
||||
//
|
||||
// A `$ref` member is where `swagger:omit` cannot be expressed at all.
|
||||
func (s *Builder) isModelEmbed(tpe types.Type) bool {
|
||||
named, ok := types.Unalias(derefType(tpe)).(*types.Named)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
obj := named.Obj()
|
||||
if obj == nil || obj.Pkg() == nil {
|
||||
return false
|
||||
}
|
||||
decl, found := s.Ctx.GetModel(obj.Pkg().Path(), obj.Name())
|
||||
|
||||
return found && decl.HasModelAnnotation()
|
||||
}
|
||||
|
||||
// derefType peels a pointer, so `*Base` classifies exactly like `Base`.
|
||||
func derefType(tpe types.Type) types.Type {
|
||||
if ptr, ok := types.Unalias(tpe).(*types.Pointer); ok {
|
||||
return ptr.Elem()
|
||||
}
|
||||
|
||||
return tpe
|
||||
}
|
||||
|
||||
// warnShadowedByJSONDash reports a field re-declared with `json:"-"` that carries the same Go name as
|
||||
// a field promoted from an embed.
|
||||
//
|
||||
// encoding/json ignores a `-` field ENTIRELY — it never enters the name set, so it cannot shadow the
|
||||
// promoted field and Go keeps marshalling the embedded one. The author almost certainly meant
|
||||
// `swagger:omit`, which removes it from the schema for real.
|
||||
//
|
||||
// See [grammar.CodeShadowedEmbedField].
|
||||
func (s *Builder) warnShadowedByJSONDash(fld *types.Var, afld *ast.Field, target *oaispec.Schema, nameByJSON map[string]propOwner) {
|
||||
if afld == nil || len(nameByJSON) == 0 {
|
||||
return
|
||||
}
|
||||
for jsonName, prior := range nameByJSON {
|
||||
if prior.goName != fld.Name() || prior.depth == 0 {
|
||||
continue
|
||||
}
|
||||
if _, written := target.Properties[jsonName]; !written {
|
||||
continue
|
||||
}
|
||||
s.hintf(s.Ctx.PosOf(afld.Pos()), grammar.CodeShadowedEmbedField,
|
||||
"field %s is re-declared with `json:\"-\"`, but encoding/json ignores such a field entirely: "+
|
||||
"it does not shadow the %q promoted from an embed, which Go still marshals. "+
|
||||
"Use swagger:omit on the embed to drop it from the schema", fld.Name(), jsonName)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
7
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/schema.go
generated
vendored
7
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/schema.go
generated
vendored
|
|
@ -48,6 +48,13 @@ type Builder struct {
|
|||
// The mechanism is shared with the parameters and responses builders via common.EmbedInheritance;
|
||||
// the schema builder consumes only Required (it has no `in:` location concept).
|
||||
embedInherited common.EmbedInheritance
|
||||
|
||||
// omitted is the set of struct fields the active `swagger:omit` scope filters out of the
|
||||
// promotion walk, keyed by field object (see omit.go).
|
||||
//
|
||||
// Pushed around each embed walk and popped after it, so sibling embeds never leak into one
|
||||
// another.
|
||||
omitted map[*types.Var]struct{}
|
||||
}
|
||||
|
||||
// NewBuilder constructs an initialized [Builder].
|
||||
|
|
|
|||
6
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/struct.go
generated
vendored
6
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/schema/struct.go
generated
vendored
|
|
@ -74,6 +74,12 @@ func (s *Builder) buildStructFields(decl *scanner.EntityDecl, st *types.Struct,
|
|||
}
|
||||
|
||||
func (s *Builder) processStructField(fld *types.Var, decl *scanner.EntityDecl, target *oaispec.Schema, nameByJSON map[string]propOwner) error {
|
||||
// `swagger:omit` pre-filter: the field is not promoted, so no property is written for it and no
|
||||
// name is ever computed. See omit.go.
|
||||
if s.isOmitted(fld) {
|
||||
return nil
|
||||
}
|
||||
|
||||
c, ok, err := s.structFieldCarrier(fld, decl, target, nameByJSON)
|
||||
if err != nil || !ok {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import (
|
|||
// (never a $ref).
|
||||
//
|
||||
// It is the single resolution point for the keyword consumed at every swagger:type site (the F3
|
||||
// reconciliation — see .claude/plans/quirks-F-series-fix.md).
|
||||
// reconciliation — see .claude/plans/archive/quirks-F-series-fix.md).
|
||||
//
|
||||
// - ownType is the annotated field/decl's Go type, consumed by the
|
||||
// `inline` / `array` keywords (which expand that type in place). May be
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ func (s *Builder) classifierTextMarshal(tpe types.Type, tgt ifaces.SwaggerTypabl
|
|||
// It is the single resolution point for `swagger:type` on a named type: it routes the argument
|
||||
// through resolveTypeOverride (always inlining — keyword scalars / Go builtins / `[]T` / `inline`
|
||||
// / `array` / type-name refs), and applies a co-present `swagger:strfmt` as a supplementary format
|
||||
// only when compatible with the resolved type (F3 — see .claude/plans/quirks-F-series-fix.md).
|
||||
// only when compatible with the resolved type (F3 — see .claude/plans/archive/quirks-F-series-fix.md).
|
||||
// ownType is the named Go type (consumed by the `inline`/`array` keywords); pos drives diagnostics.
|
||||
//
|
||||
// Reports back via the (handled, fallthrough) tuple:
|
||||
|
|
@ -291,6 +291,11 @@ type fieldDoc struct {
|
|||
//
|
||||
// Empty for bare `swagger:allOf`.
|
||||
AllOfClass string
|
||||
// OmitTargets — arguments of `swagger:omit <name>[,<name>…]` written ON AN EMBED: the Go field
|
||||
// names not to promote out of the embedded type.
|
||||
//
|
||||
// Nil when the annotation is absent. See omit.go.
|
||||
OmitTargets []string
|
||||
}
|
||||
|
||||
// scanFieldDoc inspects afld's docstring through the ParseBlocks cache and returns every
|
||||
|
|
@ -306,7 +311,7 @@ func (s *Builder) scanFieldDoc(afld *ast.Field) fieldDoc {
|
|||
}
|
||||
var nameKeyword string
|
||||
for _, b := range s.ParseBlocks(afld.Doc) {
|
||||
switch b.AnnotationKind() { //nolint:exhaustive // field-level walker only consumes these five kinds
|
||||
switch b.AnnotationKind() { //nolint:exhaustive // field-level walker only consumes these six kinds
|
||||
case grammar.AnnIgnore:
|
||||
fd.Ignored = true
|
||||
case grammar.AnnName:
|
||||
|
|
@ -326,6 +331,10 @@ func (s *Builder) scanFieldDoc(afld *ast.Field) fieldDoc {
|
|||
if name, ok := b.AnnotationArg(); ok {
|
||||
fd.AllOfClass = name
|
||||
}
|
||||
case grammar.AnnOmit:
|
||||
if arg, ok := b.AnnotationArg(); ok {
|
||||
fd.OmitTargets = append(fd.OmitTargets, parseOmitTargets(arg)...)
|
||||
}
|
||||
}
|
||||
// The `name:` keyword is the canonical field-naming keyword, honoured uniformly across schema /
|
||||
// param / header (doc-quirk G2).
|
||||
|
|
|
|||
10
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/spec/prune.go
generated
vendored
10
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/spec/prune.go
generated
vendored
|
|
@ -96,6 +96,16 @@ func (s *Builder) pruneUnusedModels() {
|
|||
queue = queue[1:]
|
||||
sch := s.input.Definitions[cur]
|
||||
collectDefRefs(&sch, mark)
|
||||
|
||||
// A reachable DISCRIMINATED base keeps its whole polymorphic family: the subtypes reference the
|
||||
// base, never the reverse, so the $ref walk above cannot see them and would prune the family down
|
||||
// to its base alone.
|
||||
// This is the discriminator reachability rule deferred here by §12 (go-swagger#1913 / §15).
|
||||
if isDiscriminated(&sch) {
|
||||
for _, sub := range s.subtypeKeysOf(cur) {
|
||||
mark(sub)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prune the unreachable, deterministically.
|
||||
|
|
|
|||
21
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/spec/spec.go
generated
vendored
21
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/spec/spec.go
generated
vendored
|
|
@ -55,6 +55,15 @@ type Builder struct {
|
|||
// DefKey, so the prune (scan.pruned-unused) and rename (scan.renamed-definition) Hints can be
|
||||
// located at the originating Go type even though the spec node may by then be gone or renamed.
|
||||
declPos map[string]token.Position
|
||||
// declIdentity records the Go type identity (typeIdentity) behind each discovered definition,
|
||||
// keyed by DefKey — the bridge from definition-key space back to the reverse `swagger:allOf` index
|
||||
// used by the discriminator-subtype pull (see subtypes.go).
|
||||
declIdentity map[string]string
|
||||
// subtypeIdx is the lazily-built reverse `swagger:allOf` index (base type identity → subtype
|
||||
// declarations).
|
||||
//
|
||||
// Built once per Build, from the model index, which is independent of ScanModels.
|
||||
subtypeIdx subtypeIndex
|
||||
// sharedParamPos / sharedRespPos record the source position of each scanned shared parameter /
|
||||
// response, keyed by its registered name, so the shared prune (scan.pruned-unused, C4) can locate
|
||||
// its Hint at the originating Go declaration.
|
||||
|
|
@ -110,6 +119,7 @@ func NewBuilder(input *oaispec.Swagger, sc *scanner.ScanCtx, scanModels bool) *B
|
|||
responses: input.Responses,
|
||||
parameters: input.Parameters,
|
||||
declPos: make(map[string]token.Position),
|
||||
declIdentity: make(map[string]string),
|
||||
sharedParamPos: make(map[string]token.Position),
|
||||
sharedRespPos: make(map[string]token.Position),
|
||||
pinnedParams: pinnedParams,
|
||||
|
|
@ -362,6 +372,10 @@ func (s *Builder) buildDiscoveredSchema(decl *scanner.EntityDecl) error {
|
|||
// node may have been dropped or renamed.
|
||||
s.declPos[decl.DefKey()] = s.ctx.PosOf(decl.Ident.Pos())
|
||||
|
||||
// Stash the Go type behind this definition so the prune reachability walk can ask the reverse
|
||||
// `swagger:allOf` index for the subtypes of a discriminated base (see subtypeKeysOf).
|
||||
s.declIdentity[decl.DefKey()] = typeIdentity(decl.Obj())
|
||||
|
||||
// Cross-ref linkage: initiate the base pointer for this definition so the schema builder
|
||||
// path-joins its members (properties, …) under it, and anchor the definition node itself to its
|
||||
// type declaration.
|
||||
|
|
@ -392,6 +406,13 @@ func (s *Builder) buildDiscoveredSchema(decl *scanner.EntityDecl) error {
|
|||
|
||||
s.discovered = append(s.discovered, sb.PostDeclarations()...)
|
||||
|
||||
// Reverse discovery: if this definition turned out to be a discriminated base, its subtypes belong
|
||||
// to the emitted document too — nothing $refs them, so top-down discovery can never reach them
|
||||
// (go-swagger#1913).
|
||||
// Queued like any other discovery, so the loop above keeps pulling their own dependencies, and a
|
||||
// subtype that is itself a discriminated base cascades.
|
||||
s.discovered = append(s.discovered, s.discriminatedSubtypesOf(decl)...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
293
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/spec/subtypes.go
generated
vendored
Normal file
293
test/tools/vendor/github.com/go-openapi/codescan/internal/builders/spec/subtypes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package spec
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"sort"
|
||||
|
||||
"github.com/go-openapi/codescan/internal/parsers/grammar"
|
||||
"github.com/go-openapi/codescan/internal/scanner"
|
||||
oaispec "github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// subtypeIndex is the reverse `swagger:allOf` index: Go type identity of a base (see typeIdentity)
|
||||
// mapped to every `swagger:model` declaration that declares that base as an `allOf` member.
|
||||
//
|
||||
// It is the inverse of the reference direction the spec carries: a subtype `$ref`s its base, never
|
||||
// the other way round, so a discriminated base entering the reachable closure can only pull its
|
||||
// family in by looking the relation up backwards.
|
||||
// §15 / go-swagger#1913.
|
||||
type subtypeIndex map[string][]*scanner.EntityDecl
|
||||
|
||||
// subtypes returns the reverse `swagger:allOf` index, building it on first use.
|
||||
//
|
||||
// The source is ScanCtx.Models() — populated by classification whether or not ScanModels is set, so
|
||||
// the index sees every annotated subtype even when none of them would be built (the no-`-m` case
|
||||
// this feature exists for).
|
||||
//
|
||||
// Entries are ordered by definition key so the pull order — and hence the order of the emitted
|
||||
// scan.discovered-subtype Hints — does not depend on map iteration.
|
||||
func (s *Builder) subtypes() subtypeIndex {
|
||||
if s.subtypeIdx != nil {
|
||||
return s.subtypeIdx
|
||||
}
|
||||
|
||||
idx := make(subtypeIndex)
|
||||
parser := grammar.NewParser(s.ctx.FileSet())
|
||||
for _, decl := range s.ctx.Models() {
|
||||
for _, base := range allOfBases(decl, parser) {
|
||||
idx[base] = append(idx[base], decl)
|
||||
}
|
||||
}
|
||||
for base := range idx {
|
||||
decls := idx[base]
|
||||
sort.Slice(decls, func(i, j int) bool { return decls[i].DefKey() < decls[j].DefKey() })
|
||||
}
|
||||
|
||||
s.subtypeIdx = idx
|
||||
|
||||
return idx
|
||||
}
|
||||
|
||||
// discriminatedSubtypesOf returns the declarations to pull into discovery because decl — whose
|
||||
// definition has just been built — is a discriminated base.
|
||||
//
|
||||
// The gate is the built definition's own `discriminator`, not a source-level re-derivation: it holds
|
||||
// uniformly for an interface base with a `discriminator: true` member and for a struct base with a
|
||||
// `discriminator: true` field, and it is the same fact the emitted document exposes. A base with no
|
||||
// discriminator pulls nothing: its `allOf` users are ordinary compositions, not a polymorphic
|
||||
// family, and inventing definitions for them would over-generate.
|
||||
//
|
||||
// Under ScanModels the pass is a no-op: buildModels already builds every annotated model, so there
|
||||
// is nothing to pull — and pulling anyway would emit Hints whose order follows the model index's map
|
||||
// iteration. The `-m` case is served by the prune reachability rule instead (subtypeKeysOf), which is
|
||||
// where a discriminated family can actually be lost.
|
||||
//
|
||||
// Subtypes already emitted are skipped; the discovery loop dedups queued ones, and only genuinely new
|
||||
// pulls are reported as Hints.
|
||||
func (s *Builder) discriminatedSubtypesOf(decl *scanner.EntityDecl) []*scanner.EntityDecl {
|
||||
if s.scanModels {
|
||||
return nil
|
||||
}
|
||||
|
||||
sch, built := s.definitions[decl.DefKey()]
|
||||
if !built || !isDiscriminated(&sch) {
|
||||
return nil
|
||||
}
|
||||
|
||||
candidates := s.subtypes()[typeIdentity(decl.Obj())]
|
||||
if len(candidates) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
onDiag := s.ctx.OnDiagnostic()
|
||||
out := make([]*scanner.EntityDecl, 0, len(candidates))
|
||||
for _, sub := range candidates {
|
||||
if _, already := s.definitions[sub.DefKey()]; already {
|
||||
continue
|
||||
}
|
||||
out = append(out, sub)
|
||||
if onDiag != nil {
|
||||
onDiag(grammar.Hintf(s.ctx.PosOf(sub.Ident.Pos()), grammar.CodeDiscoveredSubtype,
|
||||
"definition %q discovered as a subtype of discriminated base %q",
|
||||
leafName(sub.DefKey()), leafName(decl.DefKey())))
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// isDiscriminated reports whether a definition DECLARES a discriminator of its own — the gate both
|
||||
// hooks share.
|
||||
//
|
||||
// Two shapes carry one, depending on how the type is written:
|
||||
//
|
||||
// - a plain base puts it at the top level ({type: object, properties,
|
||||
// discriminator});
|
||||
// - a MID-LEVEL base — a subtype that is itself a base — renders as
|
||||
// `allOf: [{$ref parent}, {own props, discriminator}]`, so its
|
||||
// discriminator sits in its own compound member, not at the top.
|
||||
// Multi-level hierarchies would otherwise stop at the first level.
|
||||
//
|
||||
// Only an inline discriminator counts. A leaf subtype's `$ref` member is not followed, so it does not
|
||||
// inherit its base's discriminator and does not masquerade as a base itself.
|
||||
func isDiscriminated(sch *oaispec.Schema) bool {
|
||||
if sch == nil {
|
||||
return false
|
||||
}
|
||||
if sch.Discriminator != "" {
|
||||
return true
|
||||
}
|
||||
for i := range sch.AllOf {
|
||||
if isDiscriminated(&sch.AllOf[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// subtypeKeysOf returns the definition keys of the subtypes of the base emitted under defKey.
|
||||
//
|
||||
// Used by the prune reachability walk, which works in definition-key space; the bridge back to Go
|
||||
// type identity is the declIdentity side table, recorded for every definition as it is built.
|
||||
// Keys are returned whether or not they are (still) present in the definitions map — marking is
|
||||
// membership-checked by the caller.
|
||||
func (s *Builder) subtypeKeysOf(defKey string) []string {
|
||||
identity, known := s.declIdentity[defKey]
|
||||
if !known {
|
||||
return nil
|
||||
}
|
||||
|
||||
subs := s.subtypes()[identity]
|
||||
if len(subs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make([]string, 0, len(subs))
|
||||
for _, sub := range subs {
|
||||
out = append(out, sub.DefKey())
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// allOfBases returns the Go type identity of every base that decl declares as an `allOf` member,
|
||||
// i.e. each embedded field carrying `swagger:allOf`.
|
||||
//
|
||||
// Only explicit `swagger:allOf` counts. DefaultAllOfForEmbeds — which renders a plain embed AS allOf
|
||||
// composition — is deliberately not honoured: it is a rendering knob, and letting it decide which
|
||||
// definitions exist would make the emitted set depend on an unrelated option. The polymorphic idiom
|
||||
// is the explicit annotation.
|
||||
//
|
||||
// `swagger:ignore` on the embed drops it here exactly as it does in the schema builder, so the index
|
||||
// never claims a relation the document does not carry.
|
||||
// Declarations with no embeddable members (an alias, a named basic type, …) yield nothing.
|
||||
func allOfBases(decl *scanner.EntityDecl, parser grammar.Parser) []string {
|
||||
if decl.Spec == nil || decl.Pkg == nil || decl.Pkg.TypesInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var out []string
|
||||
seen := make(map[string]struct{})
|
||||
for _, afld := range embeddableMembers(decl.Spec) {
|
||||
if len(afld.Names) != 0 { // named field: never an embed
|
||||
continue
|
||||
}
|
||||
if !isAllOfEmbed(afld, parser) {
|
||||
continue
|
||||
}
|
||||
tv, known := decl.Pkg.TypesInfo.Types[afld.Type]
|
||||
if !known {
|
||||
continue
|
||||
}
|
||||
// Deduped: a struct can reach one base through two embeds (the type and an alias of it), and the
|
||||
// index must not list the same subtype twice under one base.
|
||||
for _, id := range baseIdentities(tv.Type) {
|
||||
if _, dup := seen[id]; dup {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
out = append(out, id)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// embeddableMembers returns the member list of a declaration that can hold an embed: a struct's
|
||||
// fields or an interface's method list.
|
||||
//
|
||||
// Both matter: a struct embeds its base as an anonymous field, and an INTERFACE embeds its base as an
|
||||
// anonymous interface — which is how a mid-level type in a multi-level hierarchy is written (a
|
||||
// subtype of the root that is itself a discriminated base). In both AST shapes an embed is the entry
|
||||
// with no Names.
|
||||
// Returns nothing for any other type shape.
|
||||
func embeddableMembers(spec *ast.TypeSpec) []*ast.Field {
|
||||
switch tpe := spec.Type.(type) {
|
||||
case *ast.StructType:
|
||||
if tpe.Fields == nil {
|
||||
return nil
|
||||
}
|
||||
return tpe.Fields.List
|
||||
case *ast.InterfaceType:
|
||||
if tpe.Methods == nil {
|
||||
return nil
|
||||
}
|
||||
return tpe.Methods.List
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// isAllOfEmbed reports whether an embedded field's doc marks it as an `allOf` member.
|
||||
//
|
||||
// This mirrors the `IsAllOfMember` / `Ignored` half of the schema builder's field-doc classifier
|
||||
// (schema.scanFieldDoc) — the index needs those two signals only, and the spec builder owns no
|
||||
// field-level walker to borrow them from.
|
||||
func isAllOfEmbed(afld *ast.Field, parser grammar.Parser) bool {
|
||||
if afld.Doc == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var isAllOf bool
|
||||
for _, b := range parser.ParseAll(afld.Doc) {
|
||||
switch b.AnnotationKind() { //nolint:exhaustive // only these two signals matter to the index
|
||||
case grammar.AnnIgnore:
|
||||
return false
|
||||
case grammar.AnnAllOf:
|
||||
isAllOf = true
|
||||
}
|
||||
}
|
||||
|
||||
return isAllOf
|
||||
}
|
||||
|
||||
// baseIdentities returns every type identity an embedded base may be indexed under: the pointer is
|
||||
// unwrapped (`*Base` composes exactly like `Base`), and an alias contributes BOTH its own identity
|
||||
// and that of the type it names.
|
||||
//
|
||||
// Both alias identities are kept because which one the emitted `allOf` member `$ref`s depends on
|
||||
// RefAliases / TransparentAliases: indexing both means the relation is found either way, and since
|
||||
// identities are unique per declaration there is no risk of matching an unrelated base.
|
||||
//
|
||||
// Returns nothing for an unnamed type — an anonymous struct / interface embed has no declaration to
|
||||
// index against.
|
||||
func baseIdentities(t types.Type) []string {
|
||||
if ptr, isPtr := t.(*types.Pointer); isPtr {
|
||||
t = ptr.Elem()
|
||||
}
|
||||
|
||||
var out []string
|
||||
if alias, isAlias := t.(*types.Alias); isAlias {
|
||||
out = append(out, typeIdentity(alias.Obj()))
|
||||
}
|
||||
if named, isNamed := types.Unalias(t).(*types.Named); isNamed {
|
||||
if id := typeIdentity(named.Obj()); len(out) == 0 || out[0] != id {
|
||||
out = append(out, id)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// typeIdentity is the index key for a base: "<pkgpath>.<Name>", the compiler's identity for the
|
||||
// declared type.
|
||||
//
|
||||
// The Go type — not the swagger definition name — is what both ends of the relation can compute
|
||||
// without knowing the other's annotations: the embed site resolves a type, the base declaration owns
|
||||
// one, while either may carry a `swagger:model <name>` override.
|
||||
// A package-less (universe) type falls back to its bare name.
|
||||
func typeIdentity(obj *types.TypeName) string {
|
||||
if obj == nil {
|
||||
return ""
|
||||
}
|
||||
if pkg := obj.Pkg(); pkg != nil {
|
||||
return pkg.Path() + "." + obj.Name()
|
||||
}
|
||||
|
||||
return obj.Name()
|
||||
}
|
||||
|
|
@ -161,7 +161,7 @@ once a concrete consumer asks for them.
|
|||
the `swagger:type` + `swagger:strfmt` combination, where `swagger:type` wins on
|
||||
the type axis and the strfmt format is applied as a **supplementary hint only
|
||||
when it is consistent with that type** (the F3 reconciliation — see
|
||||
`.claude/plans/quirks-F-series-fix.md`). It is **not** used for the
|
||||
`.claude/plans/archive/quirks-F-series-fix.md`). It is **not** used for the
|
||||
strfmt-alone path, where strfmt still forces `{type: string, format: X}`
|
||||
(go-swagger#1512).
|
||||
|
||||
|
|
|
|||
40
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/annotations.go
generated
vendored
40
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/annotations.go
generated
vendored
|
|
@ -15,18 +15,27 @@ type AnnotationKind int
|
|||
const (
|
||||
AnnUnknown AnnotationKind = iota
|
||||
|
||||
AnnModel // swagger:model
|
||||
AnnResponse // swagger:response
|
||||
AnnParameters // swagger:parameters
|
||||
AnnRoute // swagger:route
|
||||
AnnOperation // swagger:operation
|
||||
AnnMeta // swagger:meta
|
||||
AnnStrfmt // swagger:strfmt
|
||||
AnnAlias // swagger:alias
|
||||
AnnName // swagger:name
|
||||
AnnAllOf // swagger:allOf
|
||||
AnnEnum // swagger:enum
|
||||
AnnIgnore // swagger:ignore
|
||||
AnnModel // swagger:model
|
||||
AnnResponse // swagger:response
|
||||
AnnParameters // swagger:parameters
|
||||
AnnRoute // swagger:route
|
||||
AnnOperation // swagger:operation
|
||||
AnnMeta // swagger:meta
|
||||
AnnStrfmt // swagger:strfmt
|
||||
AnnAlias // swagger:alias
|
||||
AnnName // swagger:name
|
||||
AnnAllOf // swagger:allOf
|
||||
AnnEnum // swagger:enum
|
||||
AnnIgnore // swagger:ignore
|
||||
// AnnOmit — swagger:omit <name>[,<name>…].
|
||||
//
|
||||
// An embed-level / type-level escape hatch: the listed Go field names are not promoted out of the
|
||||
// embedded type, so the author resolves an embed conflict the scanner must not decide for them
|
||||
// (go-swagger#1992).
|
||||
//
|
||||
// The whole remainder is captured as one raw arg token; the schema builder splits the list and
|
||||
// resolves each name against the embedded type.
|
||||
AnnOmit
|
||||
AnnDefaultName // swagger:default — value-only classifier annotation
|
||||
AnnType // swagger:type
|
||||
AnnFile // swagger:file
|
||||
|
|
@ -68,6 +77,7 @@ const (
|
|||
labelAllOf = "allOf"
|
||||
labelEnum = "enum"
|
||||
labelIgnore = "ignore"
|
||||
labelOmit = "omit"
|
||||
labelDefault = "default"
|
||||
labelType = "type"
|
||||
labelFile = "file"
|
||||
|
|
@ -105,6 +115,8 @@ func (a AnnotationKind) String() string {
|
|||
return labelEnum
|
||||
case AnnIgnore:
|
||||
return labelIgnore
|
||||
case AnnOmit:
|
||||
return labelOmit
|
||||
case AnnDefaultName:
|
||||
return labelDefault
|
||||
case AnnType:
|
||||
|
|
@ -155,6 +167,8 @@ func AnnotationKindFromName(name string) AnnotationKind {
|
|||
return AnnEnum
|
||||
case labelIgnore:
|
||||
return AnnIgnore
|
||||
case labelOmit:
|
||||
return AnnOmit
|
||||
case labelDefault:
|
||||
return AnnDefaultName
|
||||
case labelType:
|
||||
|
|
@ -208,7 +222,7 @@ func (a AnnotationKind) family() annotationFamily {
|
|||
case AnnMeta:
|
||||
return familyMeta
|
||||
case AnnStrfmt, AnnAlias, AnnAllOf, AnnEnum,
|
||||
AnnIgnore, AnnDefaultName, AnnType, AnnFile,
|
||||
AnnIgnore, AnnOmit, AnnDefaultName, AnnType, AnnFile,
|
||||
AnnAdditionalProperties, AnnPatternProperties:
|
||||
return familyClassifier
|
||||
case AnnUnknown:
|
||||
|
|
|
|||
37
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/diagnostic.go
generated
vendored
37
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/diagnostic.go
generated
vendored
|
|
@ -89,7 +89,7 @@ const (
|
|||
// is not valid (e.g. `inline`/`array` as an array element).
|
||||
//
|
||||
// The override is dropped and the subject falls through to its Go type.
|
||||
// See the F3 reconciliation in .claude/plans/quirks-F-series-fix.md.
|
||||
// See the F3 reconciliation in .claude/plans/archive/quirks-F-series-fix.md.
|
||||
CodeUnsupportedType Code = "validate.unsupported-type"
|
||||
|
||||
// CodeDeprecated fires when an accepted-but-deprecated annotation or keyword value is used (the
|
||||
|
|
@ -191,6 +191,41 @@ const (
|
|||
// See scanner.Options PruneUnusedModels.
|
||||
CodePrunedUnused Code = "scan.pruned-unused"
|
||||
|
||||
// CodeDiscoveredSubtype fires when a definition is emitted because it is a subtype of a
|
||||
// discriminated base that entered the reachable set — a `swagger:model` declaring that base as an
|
||||
// `allOf` member (go-swagger#1913).
|
||||
//
|
||||
// Such a subtype is unreachable top-down (it references the base, nothing references it), so it is
|
||||
// pulled in by the reverse `swagger:allOf` index rather than by any $ref in the document.
|
||||
// Informational (Hint); carries the subtype's own source position, so a definition that appears
|
||||
// without ScanModels can be traced to the family that pulled it in.
|
||||
CodeDiscoveredSubtype Code = "scan.discovered-subtype"
|
||||
|
||||
// CodeOmitUnresolved fires when a `swagger:omit` target names no field of the embedded type it is
|
||||
// applied to — a typo, or a field renamed upstream.
|
||||
//
|
||||
// `swagger:omit` is the only construct whose output depends on a hand-written name the compiler
|
||||
// never checks (everything else is derived from types), so an unresolved target is reported rather
|
||||
// than silently ignored: otherwise a rename upstream would make the omitted field quietly reappear.
|
||||
// Informational (Hint); located at the annotation.
|
||||
CodeOmitUnresolved Code = "scan.omit-unresolved"
|
||||
|
||||
// CodeOmitBehindRef fires when a `swagger:omit` target resolves, but the embed carrying it is
|
||||
// emitted as a `$ref` (the embedded type is a `swagger:model` composed with allOf).
|
||||
//
|
||||
// Swagger 2.0 cannot subtract a property from a `$ref`, so the omission is dropped rather than
|
||||
// silently forking the referenced definition.
|
||||
// Informational (Hint); located at the annotation.
|
||||
CodeOmitBehindRef Code = "scan.omit-behind-ref"
|
||||
|
||||
// CodeShadowedEmbedField fires when a struct field re-declared with `json:"-"` carries the same Go
|
||||
// name as a field promoted from an embed.
|
||||
//
|
||||
// encoding/json ignores a `-` field entirely, so it never shadows the promoted one: Go keeps
|
||||
// marshalling the embedded field. The author most likely meant `swagger:omit`.
|
||||
// Informational (Hint); located at the re-declared field.
|
||||
CodeShadowedEmbedField Code = "scan.shadowed-embed-field"
|
||||
|
||||
// CodeRenamedDefinition fires when the reduce stage renames a definition to deconflict a
|
||||
// cross-package name collision (e.g. b.Test / c.Test -> BTest / CTest), so a consumer that tracks
|
||||
// source <-> spec links (the genspec TUI) learns the final name a Go type landed under.
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ func classifyHTTPMethod(s string) (string, bool) {
|
|||
// It is a LEXICAL check only: the grammar no longer owns the closed type vocabulary.
|
||||
// Semantic validity (is it a known keyword / scanned type? is the format compatible?) is resolved
|
||||
// by the builder, which alone knows the scanned definitions and the annotated Go type (the F3
|
||||
// reconciliation — see .claude/plans/quirks-F-series-fix.md).
|
||||
// reconciliation — see .claude/plans/archive/quirks-F-series-fix.md).
|
||||
//
|
||||
// The lexer only rejects structurally malformed tokens (empty, embedded spaces, a bare `[]`, a
|
||||
// leading digit, illegal characters), which the parser flags.
|
||||
|
|
|
|||
4
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/lexer.go
generated
vendored
4
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/lexer.go
generated
vendored
|
|
@ -348,6 +348,10 @@ func classifyAnnotationArgs(kind AnnotationKind, rest string, linePos token.Posi
|
|||
// type-name).
|
||||
// The builder does the semantic resolution.
|
||||
return []Token{argTypeRef(rest, pos)}
|
||||
case AnnOmit:
|
||||
// The arg is a comma-separated list of Go field names / dotted embed paths, which may carry
|
||||
// spaces after the commas — capture the whole remainder verbatim; the builder splits it.
|
||||
return []Token{{Kind: TokenRawValue, Pos: pos, Text: strings.TrimSpace(rest)}}
|
||||
case AnnPatternProperties:
|
||||
// The arg is a `"<re>": <spec>, …` pair list that may contain spaces/colons/commas inside
|
||||
// quoted regexes — capture the whole remainder verbatim; the builder parses the pairs.
|
||||
|
|
|
|||
2
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/parser.go
generated
vendored
2
test/tools/vendor/github.com/go-openapi/codescan/internal/parsers/grammar/parser.go
generated
vendored
|
|
@ -615,7 +615,7 @@ func (s *parseState) parseClassifierBlock(annIdx int, annTok Token, kind Annotat
|
|||
s.emit(Errorf(annTok.Args[0].Pos, CodeInvalidTypeRef,
|
||||
"swagger:type: %q is not a well-formed type reference", annTok.Args[0].Text))
|
||||
}
|
||||
case AnnAllOf, AnnIgnore, AnnAlias, AnnFile:
|
||||
case AnnAllOf, AnnIgnore, AnnAlias, AnnFile, AnnOmit:
|
||||
// Optional / no args.
|
||||
default:
|
||||
// ignored annotation
|
||||
|
|
|
|||
|
|
@ -151,7 +151,14 @@ orchestrator level.
|
|||
|
||||
## <a id="quirks-open"></a>§quirks-open — deferred follow-ups
|
||||
|
||||
- **Column tracking.** routebody does not track per-line column
|
||||
> **Where open quirks live.** This section documents caveats *of this package*.
|
||||
> The project-wide register of what is actually open — verified, with the stale
|
||||
> historical registers called out — is `.claude/plans/quirks-open.md`.
|
||||
|
||||
- **Column tracking** (owned by
|
||||
`.claude/plans/features/column-precision-unicode.md` — an LSP prerequisite,
|
||||
paired there with the multi-byte column question since both touch the same
|
||||
`Line.Pos` contract). routebody does not track per-line column
|
||||
information; diagnostics inherit `basePos.Column`. If the LSP
|
||||
integration needs per-token positions on body sub-language
|
||||
diagnostics, the body parser will need to track lex state more
|
||||
|
|
|
|||
97
test/tools/vendor/github.com/go-openapi/codescan/internal/scanner/README.md
generated
vendored
97
test/tools/vendor/github.com/go-openapi/codescan/internal/scanner/README.md
generated
vendored
|
|
@ -20,6 +20,8 @@ parameters, responses) consumed by the builder layer.
|
|||
experimental-API caveat
|
||||
- [§prune](#prune) — `PruneUnusedModels` reachability and why it
|
||||
runs before name reduction
|
||||
- [§subtypes](#subtypes) — discriminator subtype discovery — the
|
||||
reverse `swagger:allOf` index
|
||||
- [§model-lookup](#model-lookup) — `GetModel` vs `FindModel` —
|
||||
pure read vs implicit registration
|
||||
- [§classifier](#classifier) — `detectNodes` bitmask semantics and
|
||||
|
|
@ -155,10 +157,93 @@ provenance for a pruned node is dropped so no anchor dangles. The
|
|||
collision renames the reduce stage *does* perform are surfaced as
|
||||
`scan.renamed-definition` Hints (located at the Go type).
|
||||
|
||||
**Known limitation.** A discriminator base references its subtypes by
|
||||
mapping string, not by `$ref`, so a subtype reachable only through a
|
||||
discriminator could be pruned. codescan does not auto-wire discriminator
|
||||
subtypes today; revisit if it ever does (forthcoming-features §15).
|
||||
**Discriminated families are kept whole.** A subtype `$ref`s its base,
|
||||
never the reverse, so the walk above cannot see the subtypes of a
|
||||
discriminated base and would prune a polymorphic family down to its base
|
||||
alone. A reachable definition carrying `discriminator` therefore also
|
||||
marks its subtypes reachable, via the reverse `swagger:allOf` index
|
||||
(`spec/subtypes.go`, `subtypeKeysOf`). Note the rule keeps a *reached*
|
||||
base's family — it does not make bases roots: a discriminated base
|
||||
nothing references is still pruned, together with its subtypes. See
|
||||
[§subtypes](#subtypes).
|
||||
|
||||
## <a id="subtypes"></a>§subtypes — discriminator subtype discovery
|
||||
|
||||
Interface-based polymorphism emits a base definition carrying
|
||||
`discriminator` plus one `allOf: [{$ref base}, {own props}]` definition
|
||||
per subtype — a struct embedding the base under `swagger:allOf`.
|
||||
|
||||
The reference direction is the problem: **a subtype `$ref`s its base;
|
||||
nothing `$ref`s a subtype.** So a route that references only the base
|
||||
reaches the base and stops, and the emitted family is the base alone —
|
||||
useless to a consumer that has to unmarshal the polymorphic payload
|
||||
(go-swagger/go-swagger#1913). Before v0.37 the only way to get the
|
||||
subtypes was `ScanModels`, which emits every annotated model whether it
|
||||
belongs to the family or not.
|
||||
|
||||
**Reverse index.** `spec/subtypes.go` builds, once per scan, a
|
||||
`base Go type identity → subtype declarations` map from the model index
|
||||
(`TypeIndex.Models`, which classification populates whether or not
|
||||
`ScanModels` is set — that independence is what makes the pull possible).
|
||||
A subtype relation is an *embedded member carrying `swagger:allOf`* — a
|
||||
struct's anonymous field **or an interface's anonymous interface**, which
|
||||
is how a mid-level type in a multi-level hierarchy is written:
|
||||
|
||||
- the pointer is unwrapped (`*Base` composes like `Base`), and an alias
|
||||
embed is indexed under both its own and the aliased type's identity, so
|
||||
the relation is found whichever definition the `allOf` member ends up
|
||||
`$ref`ing under `RefAliases` / `TransparentAliases`;
|
||||
- `swagger:ignore` on the embed drops it, exactly as in the schema
|
||||
builder — the index never claims a relation the document lacks;
|
||||
- a *plain* (unannotated) embed is not a subtype: it inlines the base's
|
||||
properties, no `allOf` member. `DefaultAllOfForEmbeds` is deliberately
|
||||
**not** honoured here — it is a rendering knob, and letting it decide
|
||||
which definitions exist would be a surprising coupling.
|
||||
|
||||
The index is keyed by **Go type identity** (`<pkgpath>.<TypeName>`), not
|
||||
by swagger name: it is the one fact both ends can compute without knowing
|
||||
the other's `swagger:model` override. Entries are ordered by definition
|
||||
key so the pull order — and hence the Hint order — does not follow map
|
||||
iteration.
|
||||
|
||||
**Two hooks, one per hole.**
|
||||
|
||||
1. *Discovery* (`spec.go`, `buildDiscoveredSchema` →
|
||||
`discriminatedSubtypesOf`): when a definition has just been built and
|
||||
carries a `discriminator`, its subtypes are appended to `s.discovered`,
|
||||
so the existing fixpoint loop builds them, discovers *their*
|
||||
dependencies, and cascades if a subtype is itself a discriminated
|
||||
base. Each genuinely new pull raises a located
|
||||
`scan.discovered-subtype` Hint. A no-op under `ScanModels`, where every
|
||||
model is built up front anyway.
|
||||
2. *Prune reachability* (`prune.go`): see
|
||||
[§prune](#prune) — required because under `ScanModels` the family is
|
||||
built and then lost, not never-built.
|
||||
|
||||
**The gate is the built definition's own `discriminator`**
|
||||
(`isDiscriminated`), not a source-level re-derivation. It reads
|
||||
identically for an interface base with a `discriminator: true` member and
|
||||
a struct base with a `discriminator: true` property, and it is the same
|
||||
fact the emitted document exposes. A base with no discriminator pulls
|
||||
nothing: its `allOf` users are ordinary compositions, not a polymorphic
|
||||
family.
|
||||
|
||||
**Multi-level hierarchies.** A mid-level type — a subtype that is itself a
|
||||
base — renders as `allOf: [{$ref parent}, {own props, discriminator}]`:
|
||||
its properties, and therefore its discriminator, sit in its own compound
|
||||
member, *not* at the top level. So the gate looks for an inline
|
||||
discriminator anywhere in the definition's own schema. The `$ref` member
|
||||
is deliberately **not** followed: a leaf must not inherit its base's
|
||||
discriminator, or every subtype would pull in its own siblings. Because
|
||||
hook A feeds the discovery fixpoint, the levels cascade — the root pulls
|
||||
the mid-level, and the mid-level (only just pulled in itself) pulls the
|
||||
leaves on the next round.
|
||||
|
||||
Fixtures: `fixtures/enhancements/discriminated-subtypes` (`edges/` holds
|
||||
the embed-shape corner cases, in a family no route references — which
|
||||
also locks the other half of the gate: an unreached base pulls nothing)
|
||||
and `fixtures/enhancements/discriminated-subtypes-nested` (two-level
|
||||
hierarchy: `Shape` → `Polygon` → `Square`/`Triangle`).
|
||||
|
||||
## <a id="model-lookup"></a>§model-lookup — `GetModel` vs `FindModel`
|
||||
|
||||
|
|
@ -297,6 +382,10 @@ prose** — author-written overrides (harvested separately) are never filtered.
|
|||
|
||||
## <a id="quirks-open"></a>§quirks-open — deferred follow-ups
|
||||
|
||||
> **Where open quirks live.** This section documents caveats *of this package*.
|
||||
> The project-wide register of what is actually open — verified, with the stale
|
||||
> historical registers called out — is `.claude/plans/quirks-open.md`.
|
||||
|
||||
- **`FindModel` deprecation.** The deprecated alias is still on the
|
||||
`ScanCtx` surface for in-tree callers. Once every builder has been
|
||||
audited and migrated to the `GetModel` + `AddDiscoveredModel` pair,
|
||||
|
|
|
|||
2
test/tools/vendor/github.com/go-openapi/codescan/internal/scanner/index.go
generated
vendored
2
test/tools/vendor/github.com/go-openapi/codescan/internal/scanner/index.go
generated
vendored
|
|
@ -521,7 +521,7 @@ func (a *TypeIndex) detectNodes(file *ast.File) (node, error) {
|
|||
}
|
||||
case "strfmt", "name", "discriminated", "file", "enum", "default", "alias", "type", "additionalProperties", "patternProperties", "title", "description":
|
||||
// Proposal for enhancement: perhaps collect these and pass along to avoid lookups later on
|
||||
case "allOf":
|
||||
case "allOf", "omit":
|
||||
case "ignore":
|
||||
default:
|
||||
return 0, fmt.Errorf("classifier: unknown swagger annotation %q: %w", annotation, ErrScanner)
|
||||
|
|
|
|||
4
test/tools/vendor/github.com/go-openapi/inflect/CONTRIBUTORS.md
generated
vendored
4
test/tools/vendor/github.com/go-openapi/inflect/CONTRIBUTORS.md
generated
vendored
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
| Total Contributors | Total Contributions |
|
||||
| --- | --- |
|
||||
| 5 | 47 |
|
||||
| 5 | 52 |
|
||||
|
||||
| Username | All Time Contribution Count | All Commits |
|
||||
| --- | --- | --- |
|
||||
| @fredbi | 26 | <https://github.com/go-openapi/inflect/commits?author=fredbi> |
|
||||
| @fredbi | 31 | <https://github.com/go-openapi/inflect/commits?author=fredbi> |
|
||||
| @chrisfarms | 15 | <https://github.com/go-openapi/inflect/commits?author=chrisfarms> |
|
||||
| @hirochachacha | 4 | <https://github.com/go-openapi/inflect/commits?author=hirochachacha> |
|
||||
| @casualjim | 1 | <https://github.com/go-openapi/inflect/commits?author=casualjim> |
|
||||
|
|
|
|||
18
test/tools/vendor/github.com/go-openapi/inflect/README.md
generated
vendored
18
test/tools/vendor/github.com/go-openapi/inflect/README.md
generated
vendored
|
|
@ -20,12 +20,9 @@ Originally forked from https://bitbucket.org/pkg/inflect under a MIT License.
|
|||
|
||||
* **2025-12-19** : new community chat on discord
|
||||
* a new discord community channel is available to be notified of changes and support users
|
||||
* our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31**
|
||||
|
||||
You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url]
|
||||
|
||||
Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url]
|
||||
|
||||
## Status
|
||||
|
||||
API is stable.
|
||||
|
|
@ -73,11 +70,9 @@ on top of which it has been built.
|
|||
## Other documentation
|
||||
|
||||
* [All-time contributors](./CONTRIBUTORS.md)
|
||||
* [Contributing guidelines](.github/CONTRIBUTING.md)
|
||||
<!--
|
||||
* [Maintainers documentation](docs/MAINTAINERS.md)
|
||||
* [Code style](docs/STYLE.md)
|
||||
-->
|
||||
* [Contributing guidelines][contributing-doc-site]
|
||||
* [Maintainers documentation][maintainers-doc-site]
|
||||
* [Code style][style-doc-site]
|
||||
|
||||
## Cutting a new release
|
||||
|
||||
|
|
@ -112,9 +107,6 @@ Maintainers can cut a new release by either:
|
|||
[doc-url]: https://goswagger.io/go-openapi
|
||||
[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/inflect
|
||||
[godoc-url]: http://pkg.go.dev/github.com/go-openapi/inflect
|
||||
[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png
|
||||
[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM
|
||||
[slack-url]: https://goswagger.slack.com/archives/C04R30YMU
|
||||
[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue
|
||||
[discord-url]: https://discord.gg/FfnFYaC3k5
|
||||
|
||||
|
|
@ -126,3 +118,7 @@ Maintainers can cut a new release by either:
|
|||
[goversion-url]: https://github.com/go-openapi/inflect/blob/master/go.mod
|
||||
[top-badge]: https://img.shields.io/github/languages/top/go-openapi/inflect
|
||||
[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/inflect/latest
|
||||
<!-- Organization docs -->
|
||||
[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html
|
||||
[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html
|
||||
[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html
|
||||
|
|
|
|||
13
test/tools/vendor/github.com/go-openapi/runtime/form.go
generated
vendored
13
test/tools/vendor/github.com/go-openapi/runtime/form.go
generated
vendored
|
|
@ -71,11 +71,16 @@ type FileBinder func(file multipart.File, header *multipart.FileHeader) error
|
|||
// behaviour) be added without breaking the signature.
|
||||
type BindOption func(*bindConfig)
|
||||
|
||||
type bindConfig struct {
|
||||
maxParseMemory int64
|
||||
type multipartFormLimits struct {
|
||||
maxBody int64
|
||||
maxFiles int
|
||||
maxFilenameLen int
|
||||
}
|
||||
|
||||
type bindConfig struct {
|
||||
multipartFormLimits
|
||||
|
||||
maxParseMemory int64
|
||||
files []formFileSpec
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +203,9 @@ func BindFormFile(name string, required bool, bind FileBinder) BindOption {
|
|||
// it directly as a filesystem path.
|
||||
func BindForm(r *http.Request, opts ...BindOption) (fatal bool, err error) {
|
||||
cfg := bindConfig{
|
||||
maxFilenameLen: DefaultMaxUploadFilenameLength,
|
||||
multipartFormLimits: multipartFormLimits{
|
||||
maxFilenameLen: DefaultMaxUploadFilenameLength,
|
||||
},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&cfg)
|
||||
|
|
|
|||
556
test/tools/vendor/github.com/go-openapi/runtime/multipart_stream.go
generated
vendored
Normal file
556
test/tools/vendor/github.com/go-openapi/runtime/multipart_stream.go
generated
vendored
Normal file
|
|
@ -0,0 +1,556 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2015-2026 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"context"
|
||||
stderrors "errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
)
|
||||
|
||||
// MultipartFormStreamOption configures [NewMultipartFormStream].
|
||||
type MultipartFormStreamOption func(*multipartFormStreamConfig)
|
||||
|
||||
const defaultMultipartFormStreamMaxParts = 1000
|
||||
|
||||
type multipartFormStreamConfig struct {
|
||||
multipartFormLimits
|
||||
|
||||
maxParts int
|
||||
}
|
||||
|
||||
// MultipartFormStreamMaxBody caps the total number of request-body bytes read
|
||||
// by a [MultipartFormStream].
|
||||
//
|
||||
// A value of 0 applies [DefaultMaxUploadBodySize]. A negative value disables
|
||||
// the cap when the caller has already limited the request body upstream.
|
||||
func MultipartFormStreamMaxBody(n int64) MultipartFormStreamOption {
|
||||
return func(c *multipartFormStreamConfig) { c.maxBody = n }
|
||||
}
|
||||
|
||||
// MultipartFormStreamMaxFiles rejects a multipart stream after more than n
|
||||
// file parts have been encountered. A value of 0 means no file-count cap.
|
||||
func MultipartFormStreamMaxFiles(n int) MultipartFormStreamOption {
|
||||
return func(c *multipartFormStreamConfig) { c.maxFiles = n }
|
||||
}
|
||||
|
||||
// MultipartFormStreamMaxParts rejects a multipart stream after more than n
|
||||
// total parts have been encountered. The default is 1000, matching
|
||||
// [multipart.Reader.ReadForm]. A value of 0 disables the limit.
|
||||
func MultipartFormStreamMaxParts(n int) MultipartFormStreamOption {
|
||||
return func(c *multipartFormStreamConfig) { c.maxParts = n }
|
||||
}
|
||||
|
||||
// MultipartFormStreamMaxFilenameLen rejects file parts whose filename exceeds
|
||||
// n bytes. A value of 0 disables the limit. When this option is not supplied,
|
||||
// [DefaultMaxUploadFilenameLength] is used.
|
||||
func MultipartFormStreamMaxFilenameLen(n int) MultipartFormStreamOption {
|
||||
return func(c *multipartFormStreamConfig) { c.maxFilenameLen = n }
|
||||
}
|
||||
|
||||
// StreamedFile exposes a file part directly from the multipart request body.
|
||||
//
|
||||
// Reads block until bytes arrive from the client. StreamedFile is not seekable
|
||||
// and is not safe for concurrent use. Its form name, filename and MIME headers
|
||||
// are available before the payload is consumed. The underlying [multipart.Part]
|
||||
// remains private so callers cannot bypass Close and its error-preserving drain
|
||||
// semantics; Header exposes the part metadata without exposing that lifecycle.
|
||||
//
|
||||
// Closing a StreamedFile drains only the unread remainder of that file part.
|
||||
// Close may therefore block while the client is still uploading the current
|
||||
// part. The owning [MultipartFormStream] may then advance to the next part.
|
||||
type StreamedFile struct {
|
||||
FieldName string
|
||||
Filename string
|
||||
Header textproto.MIMEHeader
|
||||
part *multipart.Part
|
||||
closeErr error
|
||||
}
|
||||
|
||||
// MultipartFileInfo describes a file part discovered by [MultipartFormStream].
|
||||
//
|
||||
// The payload reader is intentionally omitted. File parts remain sequential and
|
||||
// are consumed through [MultipartFormStream.NextFile]. Header is a snapshot of
|
||||
// the client-supplied MIME headers and must be treated as untrusted input.
|
||||
type MultipartFileInfo struct {
|
||||
FieldName string
|
||||
Filename string
|
||||
Header textproto.MIMEHeader
|
||||
}
|
||||
|
||||
// Read reads file payload bytes directly from the request body.
|
||||
func (f *StreamedFile) Read(p []byte) (int, error) {
|
||||
if f == nil || f.part == nil {
|
||||
return 0, io.ErrClosedPipe
|
||||
}
|
||||
|
||||
return f.part.Read(p)
|
||||
}
|
||||
|
||||
// Close discards the unread remainder of this file part.
|
||||
//
|
||||
// Close does not close the underlying HTTP request body and does not consume
|
||||
// subsequent multipart parts. After Close returns successfully, the parent
|
||||
// MultipartFormStream may advance to the next part.
|
||||
//
|
||||
// Any error encountered while discarding the unread payload is returned.
|
||||
func (f *StreamedFile) Close() error {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
if f.part == nil {
|
||||
return f.closeErr
|
||||
}
|
||||
|
||||
part := f.part
|
||||
f.part = nil
|
||||
// multipart.Part.Close drains with io.Copy but intentionally discards the
|
||||
// resulting error, so drain explicitly to preserve error propagation.
|
||||
_, f.closeErr = io.Copy(io.Discard, part)
|
||||
|
||||
return f.closeErr
|
||||
}
|
||||
|
||||
// MultipartFormStream reads multipart/form-data sequentially without parsing
|
||||
// the complete request body before exposing file payloads.
|
||||
//
|
||||
// [MultipartFormStream.NextFile] consumes ordinary form fields until it reaches
|
||||
// the next file part. Fields are appended to request.PostForm and request.Form
|
||||
// as they are encountered. Consequently, fields after a file become visible
|
||||
// only after the caller consumes or closes that file and advances the stream.
|
||||
//
|
||||
// A stream and its returned files are not safe for concurrent use. There is at
|
||||
// most one active file part. Calling [MultipartFormStream.NextFile] closes and
|
||||
// drains an unread active file before advancing, and may therefore block until
|
||||
// the current part finishes arriving. No background goroutines are started.
|
||||
//
|
||||
// The caller owns the stream. Call [MultipartFormStream.Drain] to consume the
|
||||
// remaining body, collect trailing fields and allow HTTP connection reuse when
|
||||
// possible. Call [MultipartFormStream.Close] to stop multipart processing
|
||||
// without explicitly draining the remaining parts.
|
||||
//
|
||||
// [MultipartFormStream.Fields] and [MultipartFormStream.Files] expose snapshots
|
||||
// of the multipart fields and file metadata discovered so far. They never read
|
||||
// ahead: fields or files after the active file become visible only after the
|
||||
// stream advances.
|
||||
type MultipartFormStream struct {
|
||||
multipartFormStreamConfig
|
||||
|
||||
request *http.Request
|
||||
reader *multipart.Reader
|
||||
current *StreamedFile
|
||||
|
||||
fields url.Values
|
||||
fileInfos []MultipartFileInfo
|
||||
parts int
|
||||
closed bool
|
||||
done bool
|
||||
}
|
||||
|
||||
// NewMultipartFormStream creates a sequential multipart/form-data stream over
|
||||
// r.Body.
|
||||
//
|
||||
// For POST, PUT and PATCH requests, the constructor accepts only
|
||||
// multipart/form-data, validates that a non-empty boundary is present, but does
|
||||
// not consume multipart parts. For other methods, it returns an empty stream
|
||||
// whose NextFile method reports io.EOF without reading the request body.
|
||||
//
|
||||
// The constructor initializes request.Form and request.PostForm in the same way
|
||||
// as [http.Request.ParseForm], then populates multipart values incrementally as
|
||||
// [MultipartFormStream.NextFile] advances.
|
||||
//
|
||||
// For POST, PUT and PATCH requests, NewMultipartFormStream marks the request
|
||||
// as handled by MultipartReader. Callers must not subsequently call
|
||||
// [http.Request.ParseMultipartForm] or [BindForm] for the same request.
|
||||
//
|
||||
// File payloads are exposed directly from the request body and are not buffered
|
||||
// in memory or temporary files. Ordinary form values are read into memory as
|
||||
// they are encountered. Parts are processed in wire order.
|
||||
//
|
||||
// At most one StreamedFile may be active at a time. Calling
|
||||
// [MultipartFormStream.NextFile] automatically closes and drains an unread
|
||||
// current file before advancing. No background goroutines are started.
|
||||
//
|
||||
// MultipartFormStream is not safe for concurrent use.
|
||||
//
|
||||
// File names and MIME headers are supplied by the client and remain untrusted.
|
||||
func NewMultipartFormStream(r *http.Request, opts ...MultipartFormStreamOption) (*MultipartFormStream, error) {
|
||||
cfg := multipartFormStreamConfig{
|
||||
multipartFormLimits: multipartFormLimits{
|
||||
maxFilenameLen: DefaultMaxUploadFilenameLength,
|
||||
},
|
||||
maxParts: defaultMultipartFormStreamMaxParts,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&cfg)
|
||||
}
|
||||
|
||||
if r == nil {
|
||||
return nil, errors.NewParseError("body", "formData", "", stderrors.New("nil request"))
|
||||
}
|
||||
|
||||
if !supportsMultipartFormStream(r.Method) {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
return nil, errors.NewParseError("body", "formData", "", err)
|
||||
}
|
||||
|
||||
return &MultipartFormStream{
|
||||
request: r,
|
||||
multipartFormStreamConfig: cfg,
|
||||
fields: make(url.Values),
|
||||
done: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if r.Body == nil {
|
||||
return nil, errors.NewParseError("body", "formData", "", stderrors.New("nil request body"))
|
||||
}
|
||||
|
||||
contentType := r.Header.Get(HeaderContentType)
|
||||
mediaType, params, err := mime.ParseMediaType(contentType)
|
||||
if err != nil {
|
||||
return nil, errors.NewParseError(HeaderContentType, "header", contentType, err)
|
||||
}
|
||||
if mediaType != MultipartFormMime {
|
||||
return nil, errors.NewParseError(HeaderContentType, "header", mediaType, http.ErrNotMultipart)
|
||||
}
|
||||
if params["boundary"] == "" {
|
||||
return nil, errors.NewParseError(HeaderContentType, "header", contentType, http.ErrMissingBoundary)
|
||||
}
|
||||
if err = r.ParseForm(); err != nil {
|
||||
return nil, errors.NewParseError("body", "formData", "", err)
|
||||
}
|
||||
|
||||
body := r.Body
|
||||
if cfg.maxBody >= 0 {
|
||||
maxBody := cfg.maxBody
|
||||
if maxBody == 0 {
|
||||
maxBody = DefaultMaxUploadBodySize
|
||||
}
|
||||
body = http.MaxBytesReader(nil, body, maxBody)
|
||||
}
|
||||
body = &contextReadCloser{ctx: r.Context(), ReadCloser: body}
|
||||
r.Body = body
|
||||
|
||||
reader, err := r.MultipartReader()
|
||||
if err != nil {
|
||||
return nil, errors.NewParseError("body", "formData", "", err)
|
||||
}
|
||||
|
||||
return &MultipartFormStream{
|
||||
request: r,
|
||||
reader: reader,
|
||||
multipartFormStreamConfig: cfg,
|
||||
fields: make(url.Values),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Fields returns a snapshot of ordinary multipart form fields discovered so far.
|
||||
//
|
||||
// URL query values are not included. Repeated multipart fields preserve their
|
||||
// encounter order. Fields after the active file are not visible until that file
|
||||
// is consumed or closed and the stream advances. Mutating the returned values
|
||||
// does not affect the stream or the request.
|
||||
func (s *MultipartFormStream) Fields() url.Values {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cloneMultipartValues(s.fields)
|
||||
}
|
||||
|
||||
// Files returns snapshots of file metadata discovered so far in wire order.
|
||||
//
|
||||
// The currently active file is included as soon as NextFile returns it. Payload
|
||||
// readers are not retained in the index. Mutating the returned slice or MIME
|
||||
// headers does not affect the stream.
|
||||
func (s *MultipartFormStream) Files() []MultipartFileInfo {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
files := make([]MultipartFileInfo, len(s.fileInfos))
|
||||
for i, file := range s.fileInfos {
|
||||
files[i] = MultipartFileInfo{
|
||||
FieldName: file.FieldName,
|
||||
Filename: file.Filename,
|
||||
Header: cloneMultipartMIMEHeader(file.Header),
|
||||
}
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
||||
|
||||
// NextFile advances through the multipart body and returns the next file part.
|
||||
// Ordinary form fields encountered before that file are added to request.Form
|
||||
// and request.PostForm.
|
||||
//
|
||||
// If the previously returned file is still open, NextFile closes and drains it
|
||||
// before advancing. This may block while the client is still uploading that
|
||||
// part. Any drain error is returned and the stream is aborted.
|
||||
//
|
||||
// NextFile returns io.EOF when no file parts remain. At that point all trailing
|
||||
// ordinary fields have been collected.
|
||||
func (s *MultipartFormStream) NextFile() (*StreamedFile, error) {
|
||||
if err := s.prepareNextFile(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.readNextFile()
|
||||
}
|
||||
|
||||
// Drain consumes the rest of the multipart body.
|
||||
//
|
||||
// Unread file payloads are discarded. Non-file form fields encountered while
|
||||
// draining are collected in the request form values.
|
||||
//
|
||||
// Drain closes the underlying request body after reaching EOF. Subsequent calls
|
||||
// to NextFile return io.EOF. Drain returns any multipart parsing, payload drain
|
||||
// or request-body close error.
|
||||
func (s *MultipartFormStream) Drain() error {
|
||||
if s == nil || s.closed {
|
||||
return nil
|
||||
}
|
||||
|
||||
for {
|
||||
file, err := s.NextFile()
|
||||
if stderrors.Is(err, io.EOF) {
|
||||
return s.Close()
|
||||
}
|
||||
if err != nil {
|
||||
return stderrors.Join(err, s.Close())
|
||||
}
|
||||
if err = file.Close(); err != nil {
|
||||
return stderrors.Join(err, s.Close())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close stops multipart processing and closes the underlying HTTP request body
|
||||
// without explicitly draining the remaining multipart parts.
|
||||
//
|
||||
// The concrete request body may perform its own work during Close. In
|
||||
// particular, a net/http server request body may discard a limited amount of
|
||||
// unread data to allow connection reuse, so Close is not guaranteed to return
|
||||
// immediately. Call Drain when trailing form fields must be collected.
|
||||
func (s *MultipartFormStream) Close() error {
|
||||
if s == nil || s.closed {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.closed = true
|
||||
if s.current != nil {
|
||||
s.current.part = nil
|
||||
s.current = nil
|
||||
}
|
||||
|
||||
if s.request == nil || s.request.Body == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return s.request.Body.Close()
|
||||
}
|
||||
|
||||
func supportsMultipartFormStream(method string) bool {
|
||||
switch method {
|
||||
case http.MethodPost, http.MethodPut, http.MethodPatch:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MultipartFormStream) abort(err error) error {
|
||||
return stderrors.Join(err, s.Close())
|
||||
}
|
||||
|
||||
func (s *MultipartFormStream) closeCurrent() error {
|
||||
if s.current == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := s.current.Close()
|
||||
s.current = nil
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *MultipartFormStream) bindValue(part *multipart.Part, name string) error {
|
||||
value, err := io.ReadAll(part)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.fields.Add(name, string(value))
|
||||
s.request.PostForm.Add(name, string(value))
|
||||
// Match net/http.ParseMultipartForm: query values already present in Form
|
||||
// keep precedence over multipart body values, which are appended.
|
||||
s.request.Form.Add(name, string(value))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func discardPart(part *multipart.Part) error {
|
||||
_, err := io.Copy(io.Discard, part)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func cloneMultipartValues(values url.Values) url.Values {
|
||||
cloned := make(url.Values, len(values))
|
||||
for name, entries := range values {
|
||||
cloned[name] = append([]string(nil), entries...)
|
||||
}
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
func cloneMultipartMIMEHeader(header textproto.MIMEHeader) textproto.MIMEHeader {
|
||||
cloned := make(textproto.MIMEHeader, len(header))
|
||||
for name, entries := range header {
|
||||
cloned[name] = append([]string(nil), entries...)
|
||||
}
|
||||
|
||||
return cloned
|
||||
}
|
||||
|
||||
type contextReadCloser struct {
|
||||
io.ReadCloser
|
||||
|
||||
ctx context.Context //nolint:containedctx // Read has no context parameter, so the wrapper must retain it
|
||||
}
|
||||
|
||||
func (r *contextReadCloser) Read(p []byte) (int, error) {
|
||||
if err := r.ctx.Err(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return r.ReadCloser.Read(p)
|
||||
}
|
||||
|
||||
func (s *MultipartFormStream) prepareNextFile() error {
|
||||
if s == nil {
|
||||
return io.ErrClosedPipe
|
||||
}
|
||||
if s.done {
|
||||
return io.EOF
|
||||
}
|
||||
if s.closed {
|
||||
return io.ErrClosedPipe
|
||||
}
|
||||
if err := s.closeCurrent(); err != nil {
|
||||
return s.abort(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MultipartFormStream) readNextFile() (*StreamedFile, error) {
|
||||
for {
|
||||
part, err := s.reader.NextPart()
|
||||
if err != nil {
|
||||
return nil, s.handleNextPartError(err)
|
||||
}
|
||||
|
||||
s.parts++
|
||||
if s.maxParts > 0 && s.parts > s.maxParts {
|
||||
err := errors.NewParseError(
|
||||
"body",
|
||||
"formData",
|
||||
"",
|
||||
fmt.Errorf(
|
||||
"multipart form contains %d parts, exceeds limit %d",
|
||||
s.parts,
|
||||
s.maxParts,
|
||||
),
|
||||
)
|
||||
|
||||
return nil, s.abort(err)
|
||||
}
|
||||
|
||||
fieldName := part.FormName()
|
||||
if fieldName == "" {
|
||||
if err := discardPart(part); err != nil {
|
||||
return nil, s.abort(err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
filename := part.FileName()
|
||||
if filename == "" {
|
||||
if err := s.bindValue(part, fieldName); err != nil {
|
||||
return nil, s.abort(err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
return s.openFile(part, fieldName, filename)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MultipartFormStream) handleNextPartError(err error) error {
|
||||
if stderrors.Is(err, io.EOF) {
|
||||
s.done = true
|
||||
|
||||
return io.EOF
|
||||
}
|
||||
|
||||
return s.abort(err)
|
||||
}
|
||||
|
||||
func (s *MultipartFormStream) openFile(
|
||||
part *multipart.Part,
|
||||
fieldName string,
|
||||
filename string,
|
||||
) (*StreamedFile, error) {
|
||||
fileCount := len(s.fileInfos) + 1
|
||||
if s.maxFiles > 0 && fileCount > s.maxFiles {
|
||||
err := errors.NewParseError(
|
||||
"body",
|
||||
"formData",
|
||||
"",
|
||||
fmt.Errorf(
|
||||
"multipart form contains %d file parts, exceeds limit %d",
|
||||
fileCount,
|
||||
s.maxFiles,
|
||||
),
|
||||
)
|
||||
|
||||
return nil, s.abort(err)
|
||||
}
|
||||
|
||||
if err := ValidateFilenameLength(
|
||||
fieldName,
|
||||
"formData",
|
||||
filename,
|
||||
s.maxFilenameLen,
|
||||
); err != nil {
|
||||
return nil, s.abort(err)
|
||||
}
|
||||
|
||||
file := &StreamedFile{
|
||||
FieldName: fieldName,
|
||||
Filename: filename,
|
||||
Header: part.Header,
|
||||
part: part,
|
||||
}
|
||||
s.fileInfos = append(s.fileInfos, MultipartFileInfo{
|
||||
FieldName: fieldName,
|
||||
Filename: filename,
|
||||
Header: cloneMultipartMIMEHeader(part.Header),
|
||||
})
|
||||
s.current = file
|
||||
|
||||
return file, nil
|
||||
}
|
||||
26
test/tools/vendor/github.com/go-openapi/swag/conv/format.go
generated
vendored
26
test/tools/vendor/github.com/go-openapi/swag/conv/format.go
generated
vendored
|
|
@ -7,14 +7,16 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
const baseDecimal = 10
|
||||
|
||||
// FormatInteger turns an integer type into a string.
|
||||
func FormatInteger[T Signed](value T) string {
|
||||
return strconv.FormatInt(int64(value), 10)
|
||||
return strconv.FormatInt(int64(value), baseDecimal)
|
||||
}
|
||||
|
||||
// FormatUinteger turns an unsigned integer type into a string.
|
||||
func FormatUinteger[T Unsigned](value T) string {
|
||||
return strconv.FormatUint(uint64(value), 10)
|
||||
return strconv.FormatUint(uint64(value), baseDecimal)
|
||||
}
|
||||
|
||||
// FormatFloat turns a floating point numerical value into a string.
|
||||
|
|
@ -26,3 +28,23 @@ func FormatFloat[T Float](value T) string {
|
|||
func FormatBool(value bool) string {
|
||||
return strconv.FormatBool(value)
|
||||
}
|
||||
|
||||
// AppendInteger appends the decimal representation of an integer to a slice of bytes.
|
||||
func AppendInteger[T Signed](dst []byte, value T) []byte {
|
||||
return strconv.AppendInt(dst, int64(value), baseDecimal)
|
||||
}
|
||||
|
||||
// AppendUinteger appends the decimal representation of an unsigned integer to a slice of bytes.
|
||||
func AppendUinteger[T Unsigned](dst []byte, value T) []byte {
|
||||
return strconv.AppendUint(dst, uint64(value), baseDecimal)
|
||||
}
|
||||
|
||||
// AppendFloat appends the decimal representation of a floating point number to a slice of bytes.
|
||||
func AppendFloat[T Float](dst []byte, value T) []byte {
|
||||
return strconv.AppendFloat(dst, float64(value), 'g', -1, bitsize(value))
|
||||
}
|
||||
|
||||
// AppendBool appends the text representation of a boolean to a slice of bytes.
|
||||
func AppendBool(dst []byte, value bool) []byte {
|
||||
return strconv.AppendBool(dst, value)
|
||||
}
|
||||
|
|
|
|||
74
test/tools/vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
74
test/tools/vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
|
|
@ -260,6 +260,11 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
var hasQueryParams, hasPathParams, hasHeaderParams, hasFormParams, hasFileParams, hasFormValueParams, hasBodyParams bool
|
||||
paramsForOperation := b.Analyzed.ParamsFor(b.Method, b.Path)
|
||||
|
||||
hasStreamingForm, err := streamingFormEnabled(paramsForOperation, b.Method, b.Path)
|
||||
if err != nil {
|
||||
return GenOperation{}, err
|
||||
}
|
||||
|
||||
idMapping, timeoutName, ctxName, err := b.paramMappings(paramsForOperation)
|
||||
if err != nil {
|
||||
return GenOperation{}, err
|
||||
|
|
@ -303,6 +308,12 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
sort.Sort(hp)
|
||||
sort.Sort(fp)
|
||||
|
||||
serverParams := serverParameters(params, hasStreamingForm)
|
||||
multipartFormName := ""
|
||||
if hasStreamingForm {
|
||||
multipartFormName = deconflictMultipartFormName(serverParams)
|
||||
}
|
||||
|
||||
var srs responses
|
||||
if operation.Responses != nil {
|
||||
srs = sortedResponses(operation.Responses.StatusCodeResponses)
|
||||
|
|
@ -415,6 +426,7 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
DefaultImports: b.DefaultImports,
|
||||
Imports: b.Imports,
|
||||
Params: params,
|
||||
ServerParams: serverParams,
|
||||
Summary: trimBOM(operation.Summary),
|
||||
QueryParams: qp,
|
||||
PathParams: pp,
|
||||
|
|
@ -427,7 +439,9 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
HasFormValueParams: hasFormValueParams,
|
||||
HasFileParams: hasFileParams,
|
||||
HasBodyParams: hasBodyParams,
|
||||
HasStreamingForm: hasStreamingForm,
|
||||
HasStreamingResponse: hasStreamingResponse,
|
||||
MultipartFormName: multipartFormName,
|
||||
Authorized: b.Authed,
|
||||
Security: b.makeSecurityRequirements(receiver), // resolved security requirements, for codegen
|
||||
SecurityDefinitions: b.makeSecuritySchemes(receiver),
|
||||
|
|
@ -874,6 +888,57 @@ func (b *codeGenOpBuilder) MakeBodyParameterItemsAndMaps(res *GenParameter, it *
|
|||
return items
|
||||
}
|
||||
|
||||
func streamingFormEnabled(params map[string]spec.Parameter, method, path string) (bool, error) {
|
||||
enabled := false
|
||||
for _, param := range params {
|
||||
raw, found := param.Extensions[xGoServerStreaming]
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
streaming, ok := raw.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf(`%s %s, parameter %q: %q must be a boolean, not a %T`,
|
||||
method, path, param.Name, xGoServerStreaming, raw)
|
||||
}
|
||||
if !streaming {
|
||||
continue
|
||||
}
|
||||
if param.In != formData || param.Type != file {
|
||||
return false, fmt.Errorf(`%s %s, parameter %q: %q may only be enabled on a formData file parameter`,
|
||||
method, path, param.Name, xGoServerStreaming)
|
||||
}
|
||||
enabled = true
|
||||
}
|
||||
|
||||
return enabled, nil
|
||||
}
|
||||
|
||||
func serverParameters(params GenParameters, streamingForm bool) GenParameters {
|
||||
if !streamingForm {
|
||||
return params
|
||||
}
|
||||
|
||||
serverParams := make(GenParameters, 0, len(params))
|
||||
for _, param := range params {
|
||||
if param.IsFormParam() {
|
||||
continue
|
||||
}
|
||||
serverParams = append(serverParams, param)
|
||||
}
|
||||
|
||||
return serverParams
|
||||
}
|
||||
|
||||
func deconflictMultipartFormName(params GenParameters) string {
|
||||
seenIDs := make(map[string]any, len(params))
|
||||
for _, param := range params {
|
||||
seenIDs[strings.ToLower(param.ID)] = struct{}{}
|
||||
}
|
||||
|
||||
return rename(multipartFormNamePreferences)(seenIDs, multipartFormNamePreferences[0], 0)
|
||||
}
|
||||
|
||||
// paramMappings yields a map of safe parameter names for an operation.
|
||||
func (b *codeGenOpBuilder) paramMappings(params map[string]spec.Parameter) (map[string]map[string]string, string, string, error) {
|
||||
idMapping := map[string]map[string]string{
|
||||
|
|
@ -964,6 +1029,15 @@ var (
|
|||
"opContext",
|
||||
"operContext",
|
||||
}
|
||||
|
||||
multipartFormNamePreferences = []string{
|
||||
"MultipartForm",
|
||||
"RequestMultipartForm",
|
||||
"HTTPMultipartForm",
|
||||
"SwaggerMultipartForm",
|
||||
"OperationMultipartForm",
|
||||
"OpMultipartForm",
|
||||
}
|
||||
)
|
||||
|
||||
// rename the variable in use by client template to avoid conflicting
|
||||
|
|
|
|||
3
test/tools/vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
3
test/tools/vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
|
|
@ -639,6 +639,7 @@ type GenOperation struct {
|
|||
DefaultResponse *GenResponse
|
||||
|
||||
Params GenParameters
|
||||
ServerParams GenParameters
|
||||
QueryParams GenParameters
|
||||
PathParams GenParameters
|
||||
HeaderParams GenParameters
|
||||
|
|
@ -650,7 +651,9 @@ type GenOperation struct {
|
|||
HasFormValueParams bool
|
||||
HasFileParams bool
|
||||
HasBodyParams bool
|
||||
HasStreamingForm bool
|
||||
HasStreamingResponse bool
|
||||
MultipartFormName string
|
||||
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
|
|
|
|||
|
|
@ -128,7 +128,10 @@ func configureAPI(api *{{.APIPackageAlias}}.{{ pascalize .Name }}API) http.Handl
|
|||
{{- $package := .Package }}
|
||||
{{- $apipackagealias := .APIPackageAlias }}
|
||||
{{- range .Operations }}
|
||||
{{- if .HasFormParams }}
|
||||
{{- if .HasStreamingForm }}
|
||||
// You may change here the maximum body size for this streaming multipart form. Below is the default (32 MB).
|
||||
// {{ if ne .Package $package }}{{ .PackageAlias }}{{ else }}{{ $apipackagealias }}{{ end }}.{{ pascalize .Name }}MaxBodySize = 32 << 20
|
||||
{{- else if .HasFormParams }}
|
||||
// You may change here the memory limit for this multipart form parser. Below is the default (32 MB).
|
||||
// {{ if ne .Package $package }}{{ .PackageAlias }}{{ else }}{{ $apipackagealias }}{{ end }}.{{ pascalize .Name }}MaxParseMemory = 32 << 20
|
||||
{{- end }}
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ import (
|
|||
)
|
||||
|
||||
{{- if .HasFormParams }}
|
||||
{{- if not .HasStreamingForm }}
|
||||
|
||||
// {{ pascalize .Name }}MaxParseMemory sets the maximum size in bytes for
|
||||
// the multipart form parser for this operation.
|
||||
|
|
@ -326,6 +327,7 @@ import (
|
|||
// The default value is 32 MB.
|
||||
// The multipart parser stores up to this + 10MB.
|
||||
var {{ pascalize .Name }}MaxParseMemory int64 = 32 << 20
|
||||
{{- end }}
|
||||
|
||||
// {{ pascalize .Name }}MaxBodySize caps the size of the form body.
|
||||
//
|
||||
|
|
@ -334,17 +336,17 @@ var {{ pascalize .Name }}MaxBodySize int64 = 32 << 20
|
|||
{{- end }}
|
||||
|
||||
// New{{ pascalize .Name }}Params creates a new {{ pascalize .Name }}Params object
|
||||
{{- if .Params.HasSomeDefaults }}
|
||||
{{- if .ServerParams.HasSomeDefaults }}
|
||||
// with the default values initialized.
|
||||
{{- else }}
|
||||
//
|
||||
// There are no default values defined in the spec.
|
||||
{{- end }}
|
||||
func New{{ pascalize .Name }}Params() {{ pascalize .Name }}Params {
|
||||
{{ if .Params.HasSomeDefaults }}
|
||||
{{ if .ServerParams.HasSomeDefaults }}
|
||||
var (
|
||||
// initialize parameters with default values
|
||||
{{ range .Params }}
|
||||
{{ range .ServerParams }}
|
||||
{{ if .HasDefault -}}
|
||||
{{ if not .IsFileParam }}{{ varname .ID}}Default =
|
||||
{{- if and .IsPrimitive .IsCustomFormatter (not (stringContains .Zero "(\"" )) }}{{ .Zero }}{{/* strfmt type initializer requires UnmarshalText(), e.g. Date, Datetime, Duration */}}
|
||||
|
|
@ -363,7 +365,7 @@ func New{{ pascalize .Name }}Params() {{ pascalize .Name }}Params {
|
|||
{{- end }}
|
||||
)
|
||||
|
||||
{{ range .Params }}{{ if .HasDefault -}}{{- /* carry out UnmarshalText initialization strategy */ -}}
|
||||
{{ range .ServerParams }}{{ if .HasDefault -}}{{- /* carry out UnmarshalText initialization strategy */ -}}
|
||||
{{ if and .IsPrimitive .IsCustomFormatter (not (stringContains .Zero "(\"")) }}{{ varname .ID}}Default.UnmarshalText([]byte({{ printf "%q" .Default }}))
|
||||
{{ else if .IsArray -}}
|
||||
{{ if or ( and .Child.IsPrimitive .Child.IsCustomFormatter ) .Child.IsArray -}}
|
||||
|
|
@ -377,7 +379,7 @@ func New{{ pascalize .Name }}Params() {{ pascalize .Name }}Params {
|
|||
{{ end -}}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
return {{ pascalize .Name }}Params{ {{ range .Params }}{{ if .HasDefault }}
|
||||
return {{ pascalize .Name }}Params{ {{ range .ServerParams }}{{ if .HasDefault }}
|
||||
{{ .ID}}: {{ if and (not .IsArray) (not .HasDiscriminator) (not .IsInterface) (not .IsStream) .IsNullable }}&{{ end }}{{ varname .ID }}Default,
|
||||
{{ end }}{{ end }} }
|
||||
}
|
||||
|
|
@ -389,7 +391,14 @@ func New{{ pascalize .Name }}Params() {{ pascalize .Name }}Params {
|
|||
type {{ pascalize .Name }}Params struct {
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
{{- range .Params }}
|
||||
{{- if .HasStreamingForm }}
|
||||
|
||||
// {{ .MultipartFormName }} is the lazily consumed multipart form stream.
|
||||
//
|
||||
// The handler owns traversal, validation and closing or draining this stream.
|
||||
{{ .MultipartFormName }} *runtime.MultipartFormStream `json:"-"`
|
||||
{{- end }}
|
||||
{{- range .ServerParams }}
|
||||
|
||||
{{- if .Description }}
|
||||
{{ lineComment .Description }}
|
||||
|
|
@ -422,11 +431,11 @@ func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) BindRequest(r *http.Requ
|
|||
{{- if .HasQueryParams }}
|
||||
qs := runtime.Values(r.URL.Query())
|
||||
{{- end }}
|
||||
{{- if .HasFormParams }}
|
||||
{{- if and .HasFormParams (not .HasStreamingForm) }}
|
||||
isBlocking, err := runtime.BindForm(r,
|
||||
runtime.BindFormMaxParseMemory({{ pascalize .Name }}MaxParseMemory),
|
||||
runtime.BindFormMaxBody({{ pascalize .Name }}MaxBodySize),
|
||||
{{- range .Params }}
|
||||
{{- range .ServerParams }}
|
||||
{{- if .IsFileParam }}
|
||||
runtime.BindFormFile({{ .Path }}, {{ or .Required (not .IsNullable) }}, {{ .ReceiverName }}.bind{{ .ID }}),
|
||||
{{- end }}
|
||||
|
|
@ -445,7 +454,7 @@ func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) BindRequest(r *http.Requ
|
|||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ range .Params }}
|
||||
{{ range .ServerParams }}
|
||||
{{- if not .IsArray }}
|
||||
{{- if .IsQueryParam }}
|
||||
|
||||
|
|
@ -542,11 +551,22 @@ func ({{ .ReceiverName }} *{{ pascalize .Name }}Params) BindRequest(r *http.Requ
|
|||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
{{- if .HasStreamingForm }}
|
||||
|
||||
multipartForm, err := runtime.NewMultipartFormStream(
|
||||
r,
|
||||
runtime.MultipartFormStreamMaxBody({{ pascalize .Name }}MaxBodySize),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{ .ReceiverName }}.{{ .MultipartFormName }} = multipartForm
|
||||
{{- end }}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{- $className := (pascalize .Name) }}
|
||||
{{ range .Params }}
|
||||
{{ range .ServerParams }}
|
||||
{{- if .IsFileParam }}
|
||||
// bind{{ .ID }} validates file parameter File1 and assigns it as a *runtime.File on success.
|
||||
//
|
||||
|
|
|
|||
23
test/tools/vendor/github.com/go-swagger/go-swagger/generator/types.go
generated
vendored
23
test/tools/vendor/github.com/go-swagger/go-swagger/generator/types.go
generated
vendored
|
|
@ -36,17 +36,18 @@ const (
|
|||
|
||||
// Extensions supported by go-swagger.
|
||||
const (
|
||||
xClass = "x-class" // class name used by discriminator
|
||||
xGoCustomTag = "x-go-custom-tag" // additional tag for serializers on struct fields
|
||||
xGoName = "x-go-name" // name of the generated go variable
|
||||
xGoType = "x-go-type" // reuse existing type (do not generate)
|
||||
xIsNullable = "x-isnullable"
|
||||
xNullable = "x-nullable" // turns the schema into a pointer
|
||||
xOmitEmpty = "x-omitempty"
|
||||
xSchemes = "x-schemes" // additional schemes supported for operations (server generation)
|
||||
xOrder = "x-order" // sort order for properties (or any schema)
|
||||
xGoJSONString = "x-go-json-string"
|
||||
xGoEnumCI = "x-go-enum-ci" // make string enumeration case-insensitive
|
||||
xClass = "x-class" // class name used by discriminator
|
||||
xGoCustomTag = "x-go-custom-tag" // additional tag for serializers on struct fields
|
||||
xGoName = "x-go-name" // name of the generated go variable
|
||||
xGoType = "x-go-type" // reuse existing type (do not generate)
|
||||
xIsNullable = "x-isnullable"
|
||||
xNullable = "x-nullable" // turns the schema into a pointer
|
||||
xOmitEmpty = "x-omitempty"
|
||||
xSchemes = "x-schemes" // additional schemes supported for operations (server generation)
|
||||
xOrder = "x-order" // sort order for properties (or any schema)
|
||||
xGoJSONString = "x-go-json-string"
|
||||
xGoEnumCI = "x-go-enum-ci" // make string enumeration case-insensitive
|
||||
xGoServerStreaming = "x-go-server-streaming" // stream multipart form payloads directly to server handlers
|
||||
|
||||
xGoOperationTag = "x-go-operation-tag" // additional tag to override generation in operation groups
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,8 +8,12 @@ package isatty
|
|||
import "golang.org/x/sys/unix"
|
||||
|
||||
// IsTerminal return true if the file descriptor is terminal.
|
||||
// TIOCGWINSZ is used instead of TCGETS because TCGETS shares its ioctl
|
||||
// number with SNDCTL_TMR_TIMEBASE of the OSS sound API, so it may succeed
|
||||
// (and even change the device mode) on non-tty devices. musl's isatty does
|
||||
// the same.
|
||||
func IsTerminal(fd uintptr) bool {
|
||||
_, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
|
||||
_, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
11
test/tools/vendor/github.com/oklog/ulid/v2/ulid.go
generated
vendored
11
test/tools/vendor/github.com/oklog/ulid/v2/ulid.go
generated
vendored
|
|
@ -505,7 +505,16 @@ func (id *ULID) Scan(src interface{}) error {
|
|||
case string:
|
||||
return id.UnmarshalText([]byte(x))
|
||||
case []byte:
|
||||
return id.UnmarshalBinary(x)
|
||||
// Drivers often return text/varchar columns as []byte. Accept both
|
||||
// the 16-byte binary form and the 26-character text encoding.
|
||||
switch len(x) {
|
||||
case len(*id):
|
||||
return id.UnmarshalBinary(x)
|
||||
case EncodedSize:
|
||||
return id.UnmarshalText(x)
|
||||
default:
|
||||
return ErrDataSize
|
||||
}
|
||||
}
|
||||
|
||||
return ErrScanValue
|
||||
|
|
|
|||
178
test/tools/vendor/go.yaml.in/yaml/v3/parserc.go
generated
vendored
178
test/tools/vendor/go.yaml.in/yaml/v3/parserc.go
generated
vendored
|
|
@ -226,9 +226,9 @@ func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool
|
|||
}
|
||||
|
||||
// Parse the production:
|
||||
// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
||||
//
|
||||
// ************
|
||||
// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
||||
// ************
|
||||
func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -249,13 +249,11 @@ func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t)
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// implicit_document ::= block_node DOCUMENT-END*
|
||||
//
|
||||
// *
|
||||
//
|
||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
//
|
||||
// *************************
|
||||
// implicit_document ::= block_node DOCUMENT-END*
|
||||
// *
|
||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
// *************************
|
||||
func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool {
|
||||
|
||||
token := peek_token(parser)
|
||||
|
|
@ -359,9 +357,9 @@ func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
//
|
||||
// ***********
|
||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
// ***********
|
||||
func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -382,11 +380,10 @@ func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// implicit_document ::= block_node DOCUMENT-END*
|
||||
//
|
||||
// *************
|
||||
//
|
||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
// implicit_document ::= block_node DOCUMENT-END*
|
||||
// *************
|
||||
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
||||
func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -432,42 +429,32 @@ func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t)
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// block_node_or_indentless_sequence ::=
|
||||
//
|
||||
// ALIAS
|
||||
// *****
|
||||
// | properties (block_content | indentless_block_sequence)?
|
||||
// ********** *
|
||||
// | block_content | indentless_block_sequence
|
||||
// *
|
||||
//
|
||||
// block_node ::= ALIAS
|
||||
//
|
||||
// *****
|
||||
// | properties block_content?
|
||||
// ********** *
|
||||
// | block_content
|
||||
// *
|
||||
//
|
||||
// flow_node ::= ALIAS
|
||||
//
|
||||
// *****
|
||||
// | properties flow_content?
|
||||
// ********** *
|
||||
// | flow_content
|
||||
// *
|
||||
//
|
||||
// properties ::= TAG ANCHOR? | ANCHOR TAG?
|
||||
//
|
||||
// *************************
|
||||
//
|
||||
// block_content ::= block_collection | flow_collection | SCALAR
|
||||
//
|
||||
// ******
|
||||
//
|
||||
// flow_content ::= flow_collection | SCALAR
|
||||
//
|
||||
// ******
|
||||
// block_node_or_indentless_sequence ::=
|
||||
// ALIAS
|
||||
// *****
|
||||
// | properties (block_content | indentless_block_sequence)?
|
||||
// ********** *
|
||||
// | block_content | indentless_block_sequence
|
||||
// *
|
||||
// block_node ::= ALIAS
|
||||
// *****
|
||||
// | properties block_content?
|
||||
// ********** *
|
||||
// | block_content
|
||||
// *
|
||||
// flow_node ::= ALIAS
|
||||
// *****
|
||||
// | properties flow_content?
|
||||
// ********** *
|
||||
// | flow_content
|
||||
// *
|
||||
// properties ::= TAG ANCHOR? | ANCHOR TAG?
|
||||
// *************************
|
||||
// block_content ::= block_collection | flow_collection | SCALAR
|
||||
// ******
|
||||
// flow_content ::= flow_collection | SCALAR
|
||||
// ******
|
||||
func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool {
|
||||
//defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)()
|
||||
|
||||
|
|
@ -697,9 +684,9 @@ func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, i
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
|
||||
//
|
||||
// ******************** *********** * *********
|
||||
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
|
||||
// ******************** *********** * *********
|
||||
func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||
if first {
|
||||
token := peek_token(parser)
|
||||
|
|
@ -755,9 +742,9 @@ func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_e
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
|
||||
//
|
||||
// *********** *
|
||||
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
|
||||
// *********** *
|
||||
func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -821,15 +808,15 @@ func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) {
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// block_mapping ::= BLOCK-MAPPING_START
|
||||
//
|
||||
// *******************
|
||||
// ((KEY block_node_or_indentless_sequence?)?
|
||||
// *** *
|
||||
// (VALUE block_node_or_indentless_sequence?)?)*
|
||||
// block_mapping ::= BLOCK-MAPPING_START
|
||||
// *******************
|
||||
// ((KEY block_node_or_indentless_sequence?)?
|
||||
// *** *
|
||||
// (VALUE block_node_or_indentless_sequence?)?)*
|
||||
//
|
||||
// BLOCK-END
|
||||
// *********
|
||||
// BLOCK-END
|
||||
// *********
|
||||
func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||
if first {
|
||||
token := peek_token(parser)
|
||||
|
|
@ -896,13 +883,14 @@ func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_even
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// block_mapping ::= BLOCK-MAPPING_START
|
||||
//
|
||||
// ((KEY block_node_or_indentless_sequence?)?
|
||||
// block_mapping ::= BLOCK-MAPPING_START
|
||||
//
|
||||
// (VALUE block_node_or_indentless_sequence?)?)*
|
||||
// ***** *
|
||||
// BLOCK-END
|
||||
// ((KEY block_node_or_indentless_sequence?)?
|
||||
//
|
||||
// (VALUE block_node_or_indentless_sequence?)?)*
|
||||
// ***** *
|
||||
// BLOCK-END
|
||||
func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -929,19 +917,17 @@ func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_ev
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// flow_sequence ::= FLOW-SEQUENCE-START
|
||||
//
|
||||
// *******************
|
||||
// (flow_sequence_entry FLOW-ENTRY)*
|
||||
// * **********
|
||||
// flow_sequence_entry?
|
||||
// *
|
||||
// FLOW-SEQUENCE-END
|
||||
// *****************
|
||||
//
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
//
|
||||
// *
|
||||
// flow_sequence ::= FLOW-SEQUENCE-START
|
||||
// *******************
|
||||
// (flow_sequence_entry FLOW-ENTRY)*
|
||||
// * **********
|
||||
// flow_sequence_entry?
|
||||
// *
|
||||
// FLOW-SEQUENCE-END
|
||||
// *****************
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// *
|
||||
func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||
if first {
|
||||
token := peek_token(parser)
|
||||
|
|
@ -1005,9 +991,9 @@ func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_ev
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
//
|
||||
// *** *
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// *** *
|
||||
func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -1026,9 +1012,9 @@ func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, ev
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
//
|
||||
// ***** *
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// ***** *
|
||||
func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -1050,9 +1036,9 @@ func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t,
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
//
|
||||
// *
|
||||
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// *
|
||||
func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
@ -1068,18 +1054,17 @@ func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, ev
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// flow_mapping ::= FLOW-MAPPING-START
|
||||
//
|
||||
// ******************
|
||||
// (flow_mapping_entry FLOW-ENTRY)*
|
||||
// * **********
|
||||
// flow_mapping_entry?
|
||||
// ******************
|
||||
// FLOW-MAPPING-END
|
||||
// ****************
|
||||
//
|
||||
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// - *** *
|
||||
// flow_mapping ::= FLOW-MAPPING-START
|
||||
// ******************
|
||||
// (flow_mapping_entry FLOW-ENTRY)*
|
||||
// * **********
|
||||
// flow_mapping_entry?
|
||||
// ******************
|
||||
// FLOW-MAPPING-END
|
||||
// ****************
|
||||
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// * *** *
|
||||
func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool {
|
||||
if first {
|
||||
token := peek_token(parser)
|
||||
|
|
@ -1144,8 +1129,9 @@ func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event
|
|||
}
|
||||
|
||||
// Parse the productions:
|
||||
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// - ***** *
|
||||
//
|
||||
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
||||
// * ***** *
|
||||
func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool {
|
||||
token := peek_token(parser)
|
||||
if token == nil {
|
||||
|
|
|
|||
44
test/tools/vendor/go.yaml.in/yaml/v3/yamlh.go
generated
vendored
44
test/tools/vendor/go.yaml.in/yaml/v3/yamlh.go
generated
vendored
|
|
@ -433,21 +433,19 @@ type yaml_document_t struct {
|
|||
|
||||
// The prototype of a read handler.
|
||||
//
|
||||
// The read handler is called when the parser needs to read more bytes from the
|
||||
// source. The handler should write not more than size bytes to the buffer.
|
||||
// The number of written bytes should be set to the size_read variable.
|
||||
// The read handler is called when the parser needs to read more bytes from the
|
||||
// source. The handler should write not more than size bytes to the buffer.
|
||||
// The number of written bytes should be set to the size_read variable.
|
||||
//
|
||||
// [in,out] data A pointer to an application data specified by
|
||||
// [in,out] data A pointer to an application data specified by
|
||||
// yaml_parser_set_input().
|
||||
// [out] buffer The buffer to write the data from the source.
|
||||
// [in] size The size of the buffer.
|
||||
// [out] size_read The actual number of bytes read from the source.
|
||||
//
|
||||
// yaml_parser_set_input().
|
||||
//
|
||||
// [out] buffer The buffer to write the data from the source.
|
||||
// [in] size The size of the buffer.
|
||||
// [out] size_read The actual number of bytes read from the source.
|
||||
//
|
||||
// On success, the handler should return 1. If the handler failed,
|
||||
// the returned value should be 0. On EOF, the handler should set the
|
||||
// size_read to 0 and return 1.
|
||||
// On success, the handler should return 1. If the handler failed,
|
||||
// the returned value should be 0. On EOF, the handler should set the
|
||||
// size_read to 0 and return 1.
|
||||
type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error)
|
||||
|
||||
// This structure holds information about a potential simple key.
|
||||
|
|
@ -655,19 +653,17 @@ type yaml_comment_t struct {
|
|||
|
||||
// The prototype of a write handler.
|
||||
//
|
||||
// The write handler is called when the emitter needs to flush the accumulated
|
||||
// characters to the output. The handler should write @a size bytes of the
|
||||
// @a buffer to the output.
|
||||
// The write handler is called when the emitter needs to flush the accumulated
|
||||
// characters to the output. The handler should write @a size bytes of the
|
||||
// @a buffer to the output.
|
||||
//
|
||||
// @param[in,out] data A pointer to an application data specified by
|
||||
// @param[in,out] data A pointer to an application data specified by
|
||||
// yaml_emitter_set_output().
|
||||
// @param[in] buffer The buffer with bytes to be written.
|
||||
// @param[in] size The size of the buffer.
|
||||
//
|
||||
// yaml_emitter_set_output().
|
||||
//
|
||||
// @param[in] buffer The buffer with bytes to be written.
|
||||
// @param[in] size The size of the buffer.
|
||||
//
|
||||
// @returns On success, the handler should return @c 1. If the handler failed,
|
||||
// the returned value should be @c 0.
|
||||
// @returns On success, the handler should return @c 1. If the handler failed,
|
||||
// the returned value should be @c 0.
|
||||
type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error
|
||||
|
||||
type yaml_emitter_state_t int
|
||||
|
|
|
|||
36
test/tools/vendor/modules.txt
vendored
36
test/tools/vendor/modules.txt
vendored
|
|
@ -37,7 +37,7 @@ github.com/go-openapi/analysis/internal/flatten/operations
|
|||
github.com/go-openapi/analysis/internal/flatten/replace
|
||||
github.com/go-openapi/analysis/internal/flatten/schutils
|
||||
github.com/go-openapi/analysis/internal/flatten/sortref
|
||||
# github.com/go-openapi/codescan v0.35.1
|
||||
# github.com/go-openapi/codescan v0.36.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/codescan
|
||||
github.com/go-openapi/codescan/internal/builders/common
|
||||
|
|
@ -62,7 +62,7 @@ github.com/go-openapi/codescan/internal/scanner/classify
|
|||
# github.com/go-openapi/errors v0.22.8
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/errors
|
||||
# github.com/go-openapi/inflect v0.21.6
|
||||
# github.com/go-openapi/inflect v1.0.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/inflect
|
||||
# github.com/go-openapi/jsonpointer v1.0.0
|
||||
|
|
@ -76,10 +76,10 @@ github.com/go-openapi/jsonreference/internal
|
|||
# github.com/go-openapi/loads v0.25.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/loads
|
||||
# github.com/go-openapi/runtime v0.32.6
|
||||
# github.com/go-openapi/runtime v0.33.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/runtime
|
||||
# github.com/go-openapi/runtime/server-middleware v0.32.6
|
||||
# github.com/go-openapi/runtime/server-middleware v0.33.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/runtime/server-middleware/docui
|
||||
# github.com/go-openapi/spec v0.22.9
|
||||
|
|
@ -90,43 +90,43 @@ github.com/go-openapi/spec
|
|||
github.com/go-openapi/strfmt
|
||||
github.com/go-openapi/strfmt/internal/bsonlite
|
||||
github.com/go-openapi/strfmt/internal/countries
|
||||
# github.com/go-openapi/swag/conv v0.27.3
|
||||
# github.com/go-openapi/swag/conv v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/conv
|
||||
# github.com/go-openapi/swag/fileutils v0.27.3
|
||||
# github.com/go-openapi/swag/fileutils v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/fileutils
|
||||
# github.com/go-openapi/swag/jsonutils v0.27.3
|
||||
# github.com/go-openapi/swag/jsonutils v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/jsonutils
|
||||
github.com/go-openapi/swag/jsonutils/adapters
|
||||
github.com/go-openapi/swag/jsonutils/adapters/ifaces
|
||||
github.com/go-openapi/swag/jsonutils/adapters/stdlib/json
|
||||
# github.com/go-openapi/swag/loading v0.27.3
|
||||
# github.com/go-openapi/swag/loading v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/loading
|
||||
# github.com/go-openapi/swag/mangling v0.27.3
|
||||
# github.com/go-openapi/swag/mangling v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/mangling
|
||||
# github.com/go-openapi/swag/netutils v0.27.3
|
||||
# github.com/go-openapi/swag/netutils v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/netutils
|
||||
# github.com/go-openapi/swag/pools v0.27.3
|
||||
# github.com/go-openapi/swag/pools v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/pools
|
||||
# github.com/go-openapi/swag/stringutils v0.27.3
|
||||
# github.com/go-openapi/swag/stringutils v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/stringutils
|
||||
# github.com/go-openapi/swag/typeutils v0.27.3
|
||||
# github.com/go-openapi/swag/typeutils v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/typeutils
|
||||
# github.com/go-openapi/swag/yamlutils v0.27.3
|
||||
# github.com/go-openapi/swag/yamlutils v0.28.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/swag/yamlutils
|
||||
# github.com/go-openapi/validate v0.26.1
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-openapi/validate
|
||||
# github.com/go-swagger/go-swagger v0.35.3
|
||||
# github.com/go-swagger/go-swagger v0.36.0
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-swagger/go-swagger/cmd/swagger
|
||||
github.com/go-swagger/go-swagger/cmd/swagger/commands
|
||||
|
|
@ -161,7 +161,7 @@ github.com/kr/text
|
|||
# github.com/mattn/go-colorable v0.1.15
|
||||
## explicit; go 1.18
|
||||
github.com/mattn/go-colorable
|
||||
# github.com/mattn/go-isatty v0.0.23
|
||||
# github.com/mattn/go-isatty v0.0.24
|
||||
## explicit; go 1.20
|
||||
github.com/mattn/go-isatty
|
||||
# github.com/mitchellh/copystructure v1.2.0
|
||||
|
|
@ -170,7 +170,7 @@ github.com/mitchellh/copystructure
|
|||
# github.com/mitchellh/reflectwalk v1.0.2
|
||||
## explicit
|
||||
github.com/mitchellh/reflectwalk
|
||||
# github.com/oklog/ulid/v2 v2.1.1
|
||||
# github.com/oklog/ulid/v2 v2.1.2
|
||||
## explicit; go 1.15
|
||||
github.com/oklog/ulid/v2
|
||||
# github.com/pelletier/go-toml/v2 v2.4.3
|
||||
|
|
@ -218,7 +218,7 @@ github.com/subosito/gotenv
|
|||
# github.com/toqueteos/webbrowser v1.2.1
|
||||
## explicit; go 1.12
|
||||
github.com/toqueteos/webbrowser
|
||||
# go.yaml.in/yaml/v3 v3.0.4
|
||||
# go.yaml.in/yaml/v3 v3.0.5
|
||||
## explicit; go 1.16
|
||||
go.yaml.in/yaml/v3
|
||||
# golang.org/x/crypto v0.54.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue